diff --git a/alist.cpp b/alist.cpp index 61367fba..644cbc32 100644 --- a/alist.cpp +++ b/alist.cpp @@ -53,7 +53,7 @@ AList::~AList() void AList::DeleteAll() { AListElem * temp; ///< A temporary variable to contain the current list element. - ///< Otherwise, when we delete list, we lose list->next too! + /// Otherwise, when we delete list, we lose list->next too! while (list) { temp = list->next; delete list; @@ -70,7 +70,7 @@ void AList::DeleteAll() void AList::Empty() { AListElem * temp; ///< A temporary variable to contain the current list element. - ///< Otherwise, when we delete list, we lose list->next too! + /// Otherwise, when we delete list, we lose list->next too! while (list) { temp = list->next; list->next = 0; diff --git a/army.cpp b/army.cpp index 83386406..58abdbf0 100644 --- a/army.cpp +++ b/army.cpp @@ -488,8 +488,16 @@ Army::Army(Unit * ldr,AList * locs,int regtype,int ass) } } } - tactitian->PracticeAttribute("tactics"); - + // If TACTICS_NEEDS_WAR is enabled, we don't want to push leaders + // from tact-4 to tact-5! + if (Globals->TACTICS_NEEDS_WAR) { + int currskill = tactitian->skills.GetDays(S_TACTICS)/tactitian->GetMen(); + if (currskill < 450 - Globals->SKILL_PRACTICE_AMOUNT) { + tactitian->PracticeAttribute("tactics"); + } + } else { // Only Globals->TACTICS_NEEDS_WAR == 0 + tactitian->PracticeAttribute("tactics"); + } soldiers = new SoldierPtr[count]; int x = 0; int y = count; diff --git a/ceran/rules.cpp b/ceran/rules.cpp index 85ea3710..d46794a0 100644 --- a/ceran/rules.cpp +++ b/ceran/rules.cpp @@ -53,6 +53,11 @@ static int aq[] = { 2, 3, 4, 5, 8, 12, 20 }; int *allowedQuartermasters = aq; int allowedQuartermastersSize = sizeof(aq)/ sizeof(aq[0]); +// at is already taken up for allowedtaxes, so I'll use ag (allowedgenghises) ;) +static int ag[] = { 0, 1, 2, 4, 6, 10 }; +int *allowedTacticians = ag; +int allowedTacticiansSize = sizeof(ag) / sizeof(ag[0]); + static GameDefs g = { "Ceran", // RULESET_NAME MAKE_ATL_VER( 3, 0, 0 ), // RULESET_VERSION @@ -211,6 +216,7 @@ static GameDefs g = { 3, // DELAY_MORTALITY 6, // DELAY_GROWTH 100, // TOWN_DEVELOPMENT + 0, //TACTICS_NEEDS_WAR }; GameDefs *Globals = &g; diff --git a/conquest/rules.cpp b/conquest/rules.cpp index 628a2179..dfbfe096 100644 --- a/conquest/rules.cpp +++ b/conquest/rules.cpp @@ -52,6 +52,11 @@ static int aq[] = { -1 }; int *allowedQuartermasters = aq; int allowedQuartermastersSize = sizeof(aq) / sizeof(aq[0]); +// at is already taken up for allowedtaxes, so I'll use ag (allowedgenghises) ;) +static int ag[] = { -1 }; +int *allowedTacticians = ag; +int allowedTacticiansSize = sizeof(ag) / sizeof(ag[0]); + static GameDefs g = { "Atlantis Conquest", // RULESET_NAME MAKE_ATL_VER( 2, 0, 0 ), // RULESET_VERSION @@ -210,6 +215,7 @@ static GameDefs g = { 3, // DELAY_MORTALITY 6, // DELAY_GROWTH 100, // TOWN_DEVELOPMENT + 0, //TACTICS_NEEDS_WAR }; GameDefs *Globals = &g; diff --git a/faction.cpp b/faction.cpp index fbaa7f79..20fdccc6 100644 --- a/faction.cpp +++ b/faction.cpp @@ -436,6 +436,10 @@ void Faction::WriteReport(Areport *f, Game *pGame) f->PutStr(AString("Quartermasters: ") + numqms + " (" + pGame->AllowedQuarterMasters(this) + ")"); } + if (Globals->TACTICS_NEEDS_WAR) { + f->PutStr(AString("Tacticians: ") + numtacts + " (" + + pGame->AllowedTacticians(this) + ")"); + } f->PutStr(AString("Mages: ") + nummages + " (" + pGame->AllowedMages(this) + ")"); if(Globals->APPRENTICES_EXIST) { diff --git a/faction.h b/faction.h index b0656c2e..c4639b21 100644 --- a/faction.h +++ b/faction.h @@ -185,6 +185,7 @@ class Faction : public AListElem int nummages; int numapprentices; int numqms; + int numtacts; AList war_regions; AList trade_regions; diff --git a/game.cpp b/game.cpp index 049763e0..3dac708b 100644 --- a/game.cpp +++ b/game.cpp @@ -1420,7 +1420,8 @@ void Game::WriteReport() CountAllApprentices(); if (Globals->TRANSPORT & GameDefs::ALLOW_TRANSPORT) CountAllQuarterMasters(); - + if (Globals->TACTICS_NEEDS_WAR) + CountAllTacticians(); forlist(&factions) { Faction *fac = (Faction *) elem; AString str = "report."; @@ -1635,6 +1636,29 @@ void Game::CountAllQuarterMasters() } } +// This, along with counting apprentices, mages and quartermasters, +// should all be in the one function (CountSpecialists?) +void Game::CountAllTacticians() +{ + forlist(&factions) { + ((Faction *) elem)->numtacts = 0; + } + + { + forlist(®ions) { + ARegion *r = (ARegion *) elem; + forlist(&r->objects) { + Object *o = (Object *) elem; + forlist(&o->units) { + Unit *u = (Unit *) elem; + if (u->GetSkill(S_TACTICS) == 5) + u->faction->numtacts++; + } + } + } + } +} + // LLS void Game::UnitFactionMap() { @@ -1715,6 +1739,22 @@ int Game::CountQuarterMasters(Faction *pFac) return i; } +int Game::CountTacticians(Faction *pFac) +{ + int i = 0; + forlist(®ions) { + ARegion *r = (ARegion *)elem; + forlist(&r->objects) { + Object *o = (Object *)elem; + forlist(&o->units) { + Unit *u = (Unit *)elem; + if(u->faction == pFac && u->GetSkill(S_TACTICS) == 5) i++; + } + } + } + return i; +} + int Game::CountApprentices(Faction *pFac) { int i = 0; @@ -1752,6 +1792,17 @@ int Game::AllowedQuarterMasters(Faction *pFac) return allowedQuartermasters[points]; } +int Game::AllowedTacticians(Faction *pFac) +{ + int points = pFac->type[F_WAR]; + + if (points < 0) points = 0; + if (points > allowedTacticiansSize - 1) + points = allowedTacticiansSize - 1; + + return allowedTacticians[points]; +} + int Game::AllowedApprentices(Faction *pFac) { int points = pFac->type[F_MAGIC]; diff --git a/game.h b/game.h index 92103001..4b511490 100644 --- a/game.h +++ b/game.h @@ -50,6 +50,10 @@ class OrdersCheck void Error(const AString &error); }; +/// The main game class +/** Currently this doc is here to switch on the class so that +I can see what the modify.cpp docs look like. +*/ class Game { friend class Faction; @@ -133,6 +137,7 @@ class Game void CountAllMages(); void CountAllApprentices(); void CountAllQuarterMasters(); + void CountAllTacticians(); void WriteReport(); // LLS - write order templates void WriteTemplates(); @@ -371,6 +376,7 @@ class Game int CountMages(Faction *); int CountApprentices(Faction *); int CountQuarterMasters(Faction *); + int CountTacticians(Faction *); void FindDeadFactions(); void DeleteEmptyUnits(); void DeleteEmptyInRegion(ARegion *); @@ -385,12 +391,13 @@ class Game // // Faction limit functions. // - // The first 3 are game specific and can be found in extra.cpp. They + // The first 4 are game specific and can be found in extra.cpp. They // may return -1 to indicate no limit. // int AllowedMages(Faction *pFac); int AllowedApprentices(Faction *pFact); int AllowedQuarterMasters(Faction *pFact); + int AllowedTacticians(Faction *pFact); int AllowedTaxes(Faction *pFac); int AllowedTrades(Faction *pFac); int TaxCheck(ARegion *pReg, Faction *pFac); diff --git a/gamedefs.h b/gamedefs.h index c2813d5f..7764d52a 100644 --- a/gamedefs.h +++ b/gamedefs.h @@ -56,6 +56,8 @@ extern int *allowedTrades; extern int allowedTradesSize; extern int *allowedQuartermasters; extern int allowedQuartermastersSize; +extern int *allowedTacticians; +extern int allowedTacticiansSize; extern int NUMBATTLEITEMS; extern int NUMARMORS; @@ -672,6 +674,9 @@ class GameDefs { // How developed pre-existing towns are at the start of the game // (100 = standard). int TOWN_DEVELOPMENT; + + // Whether you need to be a war faction to have tact-5 leaders + int TACTICS_NEEDS_WAR; }; extern GameDefs *Globals; diff --git a/genrules.cpp b/genrules.cpp index 2a945ede..f4717008 100644 --- a/genrules.cpp +++ b/genrules.cpp @@ -484,7 +484,12 @@ int Game::GenRules(const AString &rules, const AString &css, "be changed at the beginning of each turn, so a faction can " "change and adapt to the conditions around it. Faction Points " "spent on War determine the number of regions in which factions " - "can obtain income by taxing or pillaging. Faction Points spent " + "can obtain income by taxing or pillaging"; + if (Globals->TACTICS_NEEDS_WAR) { + temp += ", and also determines the number of level 5 tactics " + "leaders (tacticians) that a faction can train"; + } + temp += ". Faction Points spent " "on Trade determine the number of regions in which a faction " "may conduct trade activity. Trade activity includes producing " "goods, building ships and buildings, and buying trade items. "; @@ -504,7 +509,11 @@ int Game::GenRules(const AString &rules, const AString &css, f.Enclose(1, "table border=\"1\""); f.Enclose(1, "tr"); f.TagText("th", "Faction Points"); - f.TagText("th", "War (max tax regions)"); + temp = "War (max tax regions"; + if(Globals->TACTICS_NEEDS_WAR) + temp += "/tacticians"; + temp += ")"; + f.TagText("th", temp); temp = "Trade (max trade regions"; if (qm_exist) temp += "/quartermasters"; @@ -526,7 +535,10 @@ int Game::GenRules(const AString &rules, const AString &css, f.PutStr(i); f.Enclose(0, "td"); f.Enclose(1, "td align=\"center\" nowrap"); - f.PutStr(AllowedTaxes(&fac)); + temp = AllowedTaxes(&fac); + if (Globals->TACTICS_NEEDS_WAR) + temp+= AString("/") + AllowedTacticians(&fac); + f.PutStr(temp); f.Enclose(0, "td"); f.Enclose(1, "td align=\"center\" nowrap"); temp = AllowedTrades(&fac); diff --git a/modify.cpp b/modify.cpp index e7ab7975..95e9c43c 100644 --- a/modify.cpp +++ b/modify.cpp @@ -96,7 +96,6 @@ void Game::ModifySkillFlags(int sk, int flags) /** \arg \c sk One of the values from the NSKILLS enum in gamedata.h \arg \c cost An amount of silver - */ void Game::ModifySkillCost(int sk, int cost) { @@ -107,10 +106,8 @@ void Game::ModifySkillCost(int sk, int cost) /// Modify the special effects associated with skills. /** Mostly associated with spells, eg. fireball, banish_demon, etc. - \arg \c sk One of the values from the NSKILLS enum in gamedata.h \arg \c special A special string, eg. "lightning", "clear_skies" - */ void Game::ModifySkillSpecial(int sk, char *special) { @@ -124,7 +121,6 @@ void Game::ModifySkillSpecial(int sk, char *special) See skills.h for the full list. \arg \c sk One of the values from the NSKILLS enum in gamedata.h \arg \c cost An amount of silver - */ void Game::ModifySkillRange(int sk, char *range) { @@ -133,30 +129,55 @@ void Game::ModifySkillRange(int sk, char *range) SkillDefs[sk].range = range; } +/// Switch an item on so it can be used in-game. +/** +\arg \c item One of the values from the NITEMS enum in gamedata.h +*/ void Game::EnableItem(int item) { if(item < 0 || item > (NITEMS-1)) return; ItemDefs[item].flags &= ~ItemType::DISABLED; } +/// Switch an item off so it cannot be used in-game. +/** +\arg \c item One of the values from the NITEMS enum in gamedata.h +*/ void Game::DisableItem(int item) { if(item < 0 || item > (NITEMS-1)) return; ItemDefs[item].flags |= ItemType::DISABLED; } +/// Modify some of the flags that affect an item's behavior. +/** The flags are things like ItemType::NOMARKET, ItemType::NOTRANSPORT, etc. +\arg \c it One of the values from the NITEMS enum in gamedata.h +\arg \c flags A series of flags as defined in the ItemType class in items.h +*/ void Game::ModifyItemFlags(int it, int flags) { if(it < 0 || it > (NITEMS-1)) return; ItemDefs[it].flags = flags; } +/// Set what type of Item this is. +/** The type is an enum, and can be things like IT_MAN | IT_LEADER, etc. +See the enum at line 46 of items.h for more details. +\arg \c it One of the values from the NITEMS enum in gamedata.h +\arg \c type The type of object as defined in the an enum in items.h +*/ void Game::ModifyItemType(int it, int type) { if(it < 0 || it > (NITEMS-1)) return; ItemDefs[it].type = type; } +/// Change the weight of an item +/** Weight 0 items may still have a fractional weight - see the +FRACTIONAL_WEIGHT gamedef in rules.cpp +\arg \c it One of the values from the NITEMS enum in gamedata.h +\arg \c type The weight of the object +*/ void Game::ModifyItemWeight(int it, int weight) { if(it < 0 || it > (NITEMS-1)) return; @@ -164,6 +185,12 @@ void Game::ModifyItemWeight(int it, int weight) ItemDefs[it].weight = weight; } +/// Change the base price of an item +/** The base price can go up or down depending on the economy of a hex. +Prices tend to go up in cities, and down in the boonies. +\arg \c it One of the values from the NITEMS enum in gamedata.h +\arg \c type The base price of the object +*/ void Game::ModifyItemBasePrice(int it, int price) { if(it < 0 || it > (NITEMS-1)) return; @@ -171,6 +198,16 @@ void Game::ModifyItemBasePrice(int it, int price) ItemDefs[it].baseprice = price; } +/// Change how much an item will let a unit carry +/** A unit can only move at a speed if it has enough capacity to carry +all of its weight + +\arg \c it One of the values from the NITEMS enum in gamedata.h +\arg \c wlk How much the item can carry at walking speed +\arg \c rid How much the item can carry at riding speed +\arg \c fly How much the item can carry when flying +\arg \c swm How much the item can carry when swimming +*/ void Game::ModifyItemCapacities(int it, int wlk, int rid, int fly, int swm) { if(it < 0 || it > (NITEMS-1)) return; @@ -184,6 +221,12 @@ void Game::ModifyItemCapacities(int it, int wlk, int rid, int fly, int swm) ItemDefs[it].swim = swm; } +/// Change the item that gives you a bonus when producing this item +/** eg. This item would be wood, and the other item might be an I_AXE +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_WOOD) +\arg \c item The tool, also one of the values from the NITEMS enum (eg. I_AXE) +\arg \c bonus How much is added to the production skill +*/ void Game::ModifyItemProductionBooster(int it, int item, int bonus) { if(it < 0 || it > (NITEMS-1)) return; @@ -192,6 +235,13 @@ void Game::ModifyItemProductionBooster(int it, int item, int bonus) ItemDefs[it].mult_val = bonus; } +/// Change the item that can be hitched to this item to pull it along +/** A hitched wagon (or other conveyance) will be pulled at walking speed, +unless of course you have enough horses to carry it. +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_WAGON) +\arg \c item The tool, also one of the values from the NITEMS enum (eg. I_HORS) +\arg \c capacity How much can be pulled along in the wagon +*/ void Game::ModifyItemHitch(int it, int item, int capacity) { if(it < 0 || it > (NITEMS-1)) return; @@ -201,6 +251,14 @@ void Game::ModifyItemHitch(int it, int item, int capacity) ItemDefs[it].hitchwalk = capacity; } +/// Change the skill required to produce this item +/** eg. This item would be wood, and the skill would be "LUMB" +Set this to NULL if the item cannot be produced through normal means. +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_WOOD) +\arg \c *sk The skill as a string, eg. "LUMB", "ARMO", etc. +\arg \c lev How much skill is needed to produce the item + (eg. PARM requires ARMO of level 3) +*/ void Game::ModifyItemProductionSkill(int it, char *sk, int lev) { if(it < 0 || it > (NITEMS-1)) return; @@ -209,6 +267,14 @@ void Game::ModifyItemProductionSkill(int it, char *sk, int lev) ItemDefs[it].pLevel = lev; } +/// Change the number of man hours required to produce 1 item +/** eg. PARM needs 3 man hours. This doesn't include the skill multiplier, +so a skill-3 unit will produce 3 times as much as this number. +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_WOOD) +\arg \c months The number of man months required to produce 1 item +\arg \c lev How much skill is needed to produce the item + (eg. PARM requires ARMO of level 3) +*/ void Game::ModifyItemProductionOutput(int it, int months, int count) { if(it < 0 || it > (NITEMS-1)) return; @@ -218,6 +284,15 @@ void Game::ModifyItemProductionOutput(int it, int months, int count) ItemDefs[it].pOut = count; } +/// Change the raw materials required to produce 1 item +/** eg. 1 SWOR needs 1 IRON, 1 PARM needs 3 IRON. +Set the variable 'it' to -1 to require no item. +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_WOOD) +\arg \c i There can be up to 4 raw materials needed. Set i to 0, 1, 2 or 3 for each slot +\arg \c input Which raw material is required. This is one of the values from + the NITEMS enum +\arg \c amount How much of the raw material is needed to produce the item +*/ void Game::ModifyItemProductionInput(int it, int i, int input, int amount) { if(it < 0 || it > (NITEMS-1)) return; @@ -229,6 +304,15 @@ void Game::ModifyItemProductionInput(int it, int i, int input, int amount) ItemDefs[it].pInput[i].amt = amount; } +/// Change the magical skill required to produce this item +/** eg. This item would be CARP, and the skill would be "CRMA" +If you have normal skills and magical skills, they are an either-or proposition +eg. you don't need both WEAP-3 and ESWO to create MSWO. Set this to NULL if +no magical skill can produce this item. +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_CARP) +\arg \c *sk The skill as a string, eg. "CRMA", "CRRI", etc. +\arg \c lev How much skill is needed to produce the item +*/ void Game::ModifyItemMagicSkill(int it, char *sk, int lev) { if(it < 0 || it > (NITEMS-1)) return; @@ -237,6 +321,12 @@ void Game::ModifyItemMagicSkill(int it, char *sk, int lev) ItemDefs[it].mLevel = lev; } +/// Change the number of items produced per spell +/** eg. ESWO produces 5 MSWO per casting. Note that this is the opposite way +around to mundane items. +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_WOOD) +\arg \c count The number of items produced per casting +*/ void Game::ModifyItemMagicOutput(int it, int count) { if(it < 0 || it > (NITEMS-1)) return; @@ -244,6 +334,15 @@ void Game::ModifyItemMagicOutput(int it, int count) ItemDefs[it].mOut = count; } +/// Change the raw materials required to produce 1 item via magical means +/** eg. 1 MSWO needs 1 SWOR, 1 MARM needs 1 PARM. +Set the variable 'it' to -1 to require no item. +\arg \c it One of the values from the NITEMS enum in gamedata.h (eg. I_WOOD) +\arg \c i There can be up to 4 raw materials needed. Set i to 0, 1, 2 or 3 for each slot +\arg \c input Which raw material is required. This is one of the values from + the NITEMS enum +\arg \c amount How much of the raw material is needed to produce the item +*/ void Game::ModifyItemMagicInput(int it, int i, int input, int amount) { if(it < 0 || it > (NITEMS-1)) return; @@ -255,6 +354,13 @@ void Game::ModifyItemMagicInput(int it, int i, int input, int amount) ItemDefs[it].mInput[i].amt = amount; } +/// Change the base skill levels for specialised and non-specialised skills. +/** For most races, this will be 3 for special skills, and 2 for non-special +For orcs, it's 4 and 1; for leaders it's 5 and 5 (although it could be 0 and 5) +\arg \c *r One of the races, eg. "ORC", "HELF", "LEAD" +\arg \c spec The level of any specialised skills that the race knows. +\arg \c def The default maximum level of any skill +*/ void Game::ModifyRaceSkillLevels(char *r, int spec, int def) { ManType *mt = FindRace(r); @@ -265,6 +371,12 @@ void Game::ModifyRaceSkillLevels(char *r, int spec, int def) mt->defaultlevel = def; } +/// Change the specialised skills that a race knows. +/** +\arg \c *r One of the races, eg. "ORC", "HELF", "LEAD" +\arg \c i Which slot is being changed (there are six, from 0-5) +\arg \c *sk The skill to be added to the race's specialised skill list, eg. "LUMB" +*/ void Game::ModifyRaceSkills(char *r, int i, char *sk) { ManType *mt = FindRace(r); @@ -274,6 +386,11 @@ void Game::ModifyRaceSkills(char *r, int i, char *sk) mt->skills[i] = sk; } +/// Change the attacking skill level for a monster (ie it's COMB skill) +/** +\arg \c *mon The monster being changed (eg. "BALR") +\arg \c lev The attacking level of the monster. +*/ void Game::ModifyMonsterAttackLevel(char *mon, int lev) { MonType *pM = FindMonster(mon, 0); @@ -282,6 +399,12 @@ void Game::ModifyMonsterAttackLevel(char *mon, int lev) pM->attackLevel = lev; } +/// Change the defensive level for a monster +/** defenseType can either be a number from 0-5, or an enum from items.h (line 36) +\arg \c *mon The monster being changed (eg. "BALR") +\arg \c defenseType The type of attack being defended against (eg. ATTACK_COMBAT) +\arg \c level The new defense level of the monster +*/ void Game::ModifyMonsterDefense(char *mon, int defenseType, int level) { MonType *pM = FindMonster(mon, 0); @@ -290,6 +413,13 @@ void Game::ModifyMonsterDefense(char *mon, int defenseType, int level) pM->defense[defenseType] = level; } +/// Change a monster's number of attacks, number of hits, and rate of regeneration +/** +\arg \c *mon The monster being changed (eg. "BALR") +\arg \c num The number of attacks +\arg \c hits The number of hits that the monster can take before dying +\arg \c regen The number of hits that the monster gets back per round of combat +*/ void Game::ModifyMonsterAttacksAndHits(char *mon, int num, int hits, int regen) { MonType *pM = FindMonster(mon, 0); @@ -302,6 +432,14 @@ void Game::ModifyMonsterAttacksAndHits(char *mon, int num, int hits, int regen) pM->regen = regen; } +/// Change the offensive skills that a monster knows +/** Monsters can give their unit a stea, tact and obse score, although this is not +cumulative with the unit's current score. +\arg \c *mon The monster being changed (eg. "BALR") +\arg \c tact The monster's tactics score +\arg \c stealth The monster's stealth score +\arg \c obs The monster's observation score +*/ void Game::ModifyMonsterSkills(char *mon, int tact, int stealth, int obs) { MonType *pM = FindMonster(mon, 0); @@ -314,6 +452,12 @@ void Game::ModifyMonsterSkills(char *mon, int tact, int stealth, int obs) pM->obs = obs; } +/// Change the type or effectiveness of a monster's special attack +/** eg. Dragon's breath, balrog's hellfire spell. +\arg \c *mon The monster being changed (eg. "BALR") +\arg \c *special The name of the special attack (eg. "hellfire", "black_wind") +\arg \c lev The level that the special is cast at +*/ void Game::ModifyMonsterSpecial(char *mon, char *special, int lev) { MonType *pM = FindMonster(mon, 0); @@ -324,6 +468,13 @@ void Game::ModifyMonsterSpecial(char *mon, char *special, int lev) pM->specialLevel = lev; } +/// Change the type or amount of spoils that a monster gives out +/** eg. balrogs give out magical items, wolves give silver, kobolds give normal items +Set the item type to -1 if you don't want items given out. +\arg \c *mon The monster being changed (eg. "BALR") +\arg \c silver The base value of the silver and items that are given out +\arg \c spoilType The type of items that are given out as spoils +*/ void Game::ModifyMonsterSpoils(char *mon, int silver, int spoilType) { MonType *pM = FindMonster(mon, 0); @@ -334,6 +485,12 @@ void Game::ModifyMonsterSpoils(char *mon, int silver, int spoilType) pM->spoiltype = spoilType; } +/// Change how likely the monster is to beat things up, and how many will appear +/** This is expressed as a percentage chance of an attack (per turn?) +\arg \c *mon The monster being changed (eg. "BALR") +\arg \c num The maximum number of monsters that will appear +\arg \c hostileChance The percentage chance that a monster will attack someone +*/ void Game::ModifyMonsterThreat(char *mon, int num, int hostileChance) { MonType *pM = FindMonster(mon, 0); @@ -344,6 +501,13 @@ void Game::ModifyMonsterThreat(char *mon, int num, int hostileChance) pM->number = num; } +/// Modify the skills required to wield a weapon +/** There's no difference between baseskill or orskill - you can +wield it if you have either of them. +\arg \c *weap The name of the weapon, eg SWOR +\arg \c *baseSkill The primary skill required to wield the weapon +\arg \c *orSkill Another skill that can be used to wield the weapon +*/ void Game::ModifyWeaponSkills(char *weap, char *baseSkill, char *orSkill) { WeaponType *pw = FindWeapon(weap); @@ -354,6 +518,13 @@ void Game::ModifyWeaponSkills(char *weap, char *baseSkill, char *orSkill) pw->orSkill = orSkill; } +/// Modify the flags that alter a weapon's behavior +/** The flags are things like WeaponType::NEEDSKILL, WeaponType::RANGED, etc. +There's a full list in items.h, line 200 on +\arg \c *weap The name of the weapon, eg SWOR +\arg \c *baseSkill The primary skill required to wield the weapon +\arg \c *orSkill Another skill that can be used to wield the weapon +*/ void Game::ModifyWeaponFlags(char *weap, int flags) { WeaponType *pw = FindWeapon(weap); @@ -361,6 +532,12 @@ void Game::ModifyWeaponFlags(char *weap, int flags) pw->flags = flags; } +/// Modify the class and type of a weapon's attack +/** +\arg \c *weap The name of the weapon, eg "SWOR" +\arg \c wclass The class of the weapon, eg. ARMOR_PIERCING, SLASHING +\arg \c attackType The type of attack, eg. ATTACK_RANGED, ATTACK_COMBAT +*/ void Game::ModifyWeaponAttack(char *weap, int wclass, int attackType, int numAtt) { @@ -373,6 +550,14 @@ void Game::ModifyWeaponAttack(char *weap, int wclass, int attackType, pw->numAttacks = numAtt; } +/// Modify the bonus that a weapon gets in attack, defense and +///when fighting mounted opponents +/** +\arg \c *weap The name of the weapon, eg "SWOR" +\arg \c attack The weapon's bonus to attack +\arg \c defense The weapon's bonus in defense +\arg \c vsMount The weapon's bonus against mounted opponents +*/ void Game::ModifyWeaponBonuses(char *weap, int attack, int defense, int vsMount) { WeaponType *pw = FindWeapon(weap); @@ -382,6 +567,11 @@ void Game::ModifyWeaponBonuses(char *weap, int attack, int defense, int vsMount) pw->mountBonus = vsMount; } +/// Modify the flags that govern an armor's behavior +/** Currently there's only one flag: ArmorType::USEINASSASSINATE +\arg \c *armor The armor's name, eg. "CLAR" +\arg \c flags The flags to apply to the armor. +*/ void Game::ModifyArmorFlags(char *armor, int flags) { ArmorType *pa = FindArmor(armor); @@ -389,6 +579,12 @@ void Game::ModifyArmorFlags(char *armor, int flags) pa->flags = flags; } +/// Modify the divisor for the save chances in ModifyArmorSaveValue +/** eg. If this is 300, and the save for COMBAT is 100, then the armor +has 100 in 300 chances of protecting it's wearer vs. COMBAT attacks. +\arg \c *armor The armor's name, eg. "CLAR" +\arg \c from The saving throw's divisor +*/ void Game::ModifyArmorSaveFrom(char *armor, int from) { ArmorType *pa = FindArmor(armor); @@ -397,6 +593,13 @@ void Game::ModifyArmorSaveFrom(char *armor, int from) pa->from = from; } +/// Modify the numerator for the armor's save chances +/** eg. If this is 100 for COMBAT, and the savefrom is 300, then the armor +has 100 in 300 chances of protecting it's wearer vs. COMBAT attacks. +\arg \c *armor The armor's name, eg. "CLAR" +\arg \c wclass The saving throw vs. a particular type of attack (eg. SLASHING) +\arg \c val The numerator in the saving throw. (eg. 100) +*/ void Game::ModifyArmorSaveValue(char *armor, int wclass, int val) { ArmorType *pa = FindArmor(armor); @@ -406,6 +609,11 @@ void Game::ModifyArmorSaveValue(char *armor, int wclass, int val) pa->saves[wclass] = val; } +/// Modify the skill required to ride a mount +/** see line 2488 in gamedata.cpp +\arg \c *mount The mount name, eg. "HORS" +\arg \c *skill The skill's name eg. "RIDI" +*/ void Game::ModifyMountSkill(char *mount, char *skill) { MountType *pm = FindMount(mount); @@ -414,6 +622,14 @@ void Game::ModifyMountSkill(char *mount, char *skill) pm->skill = skill; } +/// Modify the bonuses given when mounts are ridden into combat +/** +\arg \c *mount The mount name, eg. "HORS" +\arg \c min The minimum bonus given +\arg \c max The maximum bonus given +\arg \c hampered The bonus given when a mount is hampered + (eg. WING horses underground/in tunnels?) +*/ void Game::ModifyMountBonuses(char *mount, int min, int max, int hampered) { MountType *pm = FindMount(mount); @@ -426,6 +642,13 @@ void Game::ModifyMountBonuses(char *mount, int min, int max, int hampered) pm->maxHamperedBonus = hampered; } +/// Modify the special attacks that a mount has +/** The only mount this is used for atm is the fear attacks + vs. mounted troops that camels get +\arg \c *mount The mount name, eg. "HORS" +\arg \c *special The special attack (eg. "spook_horses") +\arg \c level The level of the attack +*/ void Game::ModifyMountSpecial(char *mount, char *special, int level) { MountType *pm = FindMount(mount); diff --git a/monthorders.cpp b/monthorders.cpp index d092a6d6..0b0d78fb 100644 --- a/monthorders.cpp +++ b/monthorders.cpp @@ -997,6 +997,24 @@ void Game::Do1StudyOrder(Unit *u,Object *obj) } } + // If TACTICS_NEEDS_WAR is enabled, and the unit is trying to study to tact-5, + // check that there's still space... + if (Globals->TACTICS_NEEDS_WAR && sk == S_TACTICS && + u->GetSkill(sk) == 4 && u->skills.GetDays(sk)/u->GetMen() >= 390) { + + if (CountTacticians(u->faction) >= + AllowedTacticians(u->faction)) { + u->Error("STUDY: Can't have another level 5 tactics leader."); + return; + } + + if (u->GetMen() != 1) { + u->Error("STUDY: Only 1-man units can study to level 5 in tactics."); + return; + } + + } // end tactics check + int days = 30 * u->GetMen() + o->days; if((SkillDefs[sk].flags & SkillType::MAGIC) && u->GetSkill(sk) >= 2) { diff --git a/realms/rules.cpp b/realms/rules.cpp index d24ebea3..c3c12005 100644 --- a/realms/rules.cpp +++ b/realms/rules.cpp @@ -53,6 +53,11 @@ static int aq[] = { 0, 2, 4, 8, 12, 20 }; int *allowedQuartermasters = aq; int allowedQuartermastersSize = sizeof(aq) / sizeof(aq[0]); +// at is already taken up for allowedtaxes, so I'll use ag (allowedgenghises) ;) +static int ag[] = { 0, 1, 2, 4, 6, 10 }; +int *allowedTacticians = ag; +int allowedTacticiansSize = sizeof(ag) / sizeof(ag[0]); + static GameDefs g = { "Realms of the Arcane", // RULESET_NAME MAKE_ATL_VER( 5, 0, 0 ), // RULESET_VERSION @@ -212,6 +217,7 @@ static GameDefs g = { 3, // DELAY_MORTALITY 6, // DELAY_GROWTH 100, // TOWN_DEVELOPMENT + 0, //TACTICS_NEEDS_WAR }; GameDefs *Globals = &g; diff --git a/runorders.cpp b/runorders.cpp index 8f9e376f..8f3906e0 100644 --- a/runorders.cpp +++ b/runorders.cpp @@ -1446,6 +1446,11 @@ int Game::GetBuyAmount(ARegion *r, Market *m) "men."); o->num = 0; } + if (u->GetSkill(S_TACTICS) == 5) { + u->Error("BUY: Tacticians can't recruit more " + "men."); + o->num = 0; + } if (((ItemDefs[o->item].type & IT_LEADER) && u->IsNormal()) || (!(ItemDefs[o->item].type & IT_LEADER) && @@ -2508,6 +2513,18 @@ int Game::DoGiveOrder(ARegion *r, Unit *u, GiveOrder *o) } } + if (u->GetSkill(S_TACTICS) == 5) { + if (Globals->FACTION_LIMIT_TYPE == GameDefs::FACLIM_FACTION_TYPES) { + if (Globals->TACTICS_NEEDS_WAR) { + if (CountTacticians(t->faction) >= + AllowedTacticians(t->faction)) { + u->Error("GIVE: Faction has too many tacticians."); + return 0; + } + } + } + } + int notallied = 1; if (t->faction->GetAttitude(u->faction->num) == A_ALLY) { notallied = 0; diff --git a/standard/rules.cpp b/standard/rules.cpp index 230cb0da..a17bf6da 100644 --- a/standard/rules.cpp +++ b/standard/rules.cpp @@ -53,6 +53,11 @@ static int aq[] = { 0, 2, 4, 8, 12, 20 }; int *allowedQuartermasters = aq; int allowedQuartermastersSize = sizeof(aq) / sizeof(aq[0]); +// at is already taken up for allowedtaxes, so I'll use ag (allowedgenghises) ;) +static int ag[] = { 0, 1, 2, 4, 6, 10 }; +int *allowedTacticians = ag; +int allowedTacticiansSize = sizeof(ag) / sizeof(ag[0]); + static GameDefs g = { "Standard Atlantis", // RULESET_NAME MAKE_ATL_VER( 5, 0, 0 ), // RULESET_VERSION @@ -212,6 +217,7 @@ static GameDefs g = { 3, // DELAY_MORTALITY 6, // DELAY_GROWTH 100, // TOWN_DEVELOPMENT + 0, //TACTICS_NEEDS_WAR }; GameDefs *Globals = &g; diff --git a/wyreth/rules.cpp b/wyreth/rules.cpp index 412722d2..52edd717 100644 --- a/wyreth/rules.cpp +++ b/wyreth/rules.cpp @@ -53,6 +53,11 @@ static int aq[] = { 0, 2, 4, 8, 12, 20 }; int *allowedQuartermasters = aq; int allowedQuartermastersSize = sizeof(aq) / sizeof(aq[0]); +// at is already taken up for allowedtaxes, so I'll use ag (allowedgenghises) ;) +static int ag[] = { 0, 1, 2, 4, 6, 10 }; +int *allowedTacticians = ag; +int allowedTacticiansSize = sizeof(ag) / sizeof(ag[0]); + static GameDefs g = { "Wyreth", // RULESET_NAME MAKE_ATL_VER( 2, 0, 0 ), // RULESET_VERSION @@ -206,11 +211,12 @@ static GameDefs g = { 5, // SHIPPING_COST 0, // FRACTIONAL_WEIGHT 0, // GROW_RACES - 0, // PLAYER_ECONOMY + 1, // PLAYER_ECONOMY 100, // POP_GROWTH 3, // DELAY_MORTALITY 6, // DELAY_GROWTH 100, // TOWN_DEVELOPMENT + 0, //TACTICS_NEEDS_WAR }; GameDefs *Globals = &g;