mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
Heroes placed on water in map will be automatically given boat
This commit is contained in:
parent
738ace99cb
commit
3913b8e98c
@ -9,6 +9,7 @@
|
||||
"120px" : "TPCASCAS",
|
||||
"130px" : "CRBKGCAS"
|
||||
},
|
||||
"boat" : "boatCastle",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZCAS",
|
||||
@ -148,7 +149,6 @@
|
||||
"mageGuild" : 4,
|
||||
"warMachine" : "ballista",
|
||||
"moatAbility" : "castleMoat",
|
||||
"boat" : "boatCastle",
|
||||
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
||||
|
||||
"buildings" :
|
||||
|
@ -9,6 +9,7 @@
|
||||
"120px" : "TPCASELE",
|
||||
"130px" : "CRBKGELE"
|
||||
},
|
||||
"boat" : "boatNecropolis",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZELE",
|
||||
@ -153,7 +154,6 @@
|
||||
"primaryResource" : "mercury",
|
||||
"warMachine" : "ballista",
|
||||
"moatAbility" : "castleMoat",
|
||||
"boat" : "boatNecropolis",
|
||||
|
||||
"buildings" :
|
||||
{
|
||||
|
@ -10,6 +10,7 @@
|
||||
"120px" : "TPCASDUN",
|
||||
"130px" : "CRBKGDUN"
|
||||
},
|
||||
"boat" : "boatCastle",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZDUN",
|
||||
|
@ -9,6 +9,7 @@
|
||||
"120px" : "TPCASFOR",
|
||||
"130px" : "CRBKGFOR"
|
||||
},
|
||||
"boat" : "boatFortress",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZFOR",
|
||||
@ -148,7 +149,6 @@
|
||||
"mageGuild" : 3,
|
||||
"warMachine" : "firstAidTent",
|
||||
"moatAbility" : "fortressMoat",
|
||||
"boat" : "boatFortress",
|
||||
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
||||
|
||||
"buildings" :
|
||||
|
@ -10,6 +10,7 @@
|
||||
"120px" : "TPCASINF",
|
||||
"130px" : "CRBKGINF"
|
||||
},
|
||||
"boat" : "boatCastle",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZINF",
|
||||
|
@ -10,6 +10,7 @@
|
||||
"120px" : "TPCASNEC",
|
||||
"130px" : "CRBKGNEC"
|
||||
},
|
||||
"boat" : "boatNecropolis",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZNEC",
|
||||
@ -153,7 +154,6 @@
|
||||
"mageGuild" : 5,
|
||||
"warMachine" : "firstAidTent",
|
||||
"moatAbility" : "necropolisMoat",
|
||||
"boat" : "boatNecropolis",
|
||||
// primaryResource not specified so town get both Wood and Ore for resource bonus
|
||||
|
||||
"buildings" :
|
||||
|
@ -9,6 +9,7 @@
|
||||
"120px" : "TPCASRAM",
|
||||
"130px" : "CRBKGRAM"
|
||||
},
|
||||
"boat" : "boatCastle",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZRAM",
|
||||
|
@ -9,6 +9,7 @@
|
||||
"120px" : "TPCASSTR",
|
||||
"130px" : "CRBKGSTR"
|
||||
},
|
||||
"boat" : "boatCastle",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZSTR",
|
||||
|
@ -9,6 +9,7 @@
|
||||
"120px" : "TPCASTOW",
|
||||
"130px" : "CRBKGTOW"
|
||||
},
|
||||
"boat" : "boatCastle",
|
||||
"puzzleMap" :
|
||||
{
|
||||
"prefix" : "PUZTOW",
|
||||
|
@ -16,12 +16,14 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class FactionID;
|
||||
enum class EAlignment : uint8_t;
|
||||
enum class EBoatId : int32_t;
|
||||
|
||||
class DLL_LINKAGE Faction : public EntityT<FactionID>, public INativeTerrainProvider
|
||||
{
|
||||
public:
|
||||
virtual bool hasTown() const = 0;
|
||||
virtual EAlignment getAlignment() const = 0;
|
||||
virtual EBoatId getBoatType() const = 0;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
@ -1250,6 +1250,31 @@ void CGameState::initHeroes()
|
||||
map->allHeroes[hero->type->getIndex()] = hero;
|
||||
}
|
||||
|
||||
// generate boats for all heroes on water
|
||||
for(auto hero : map->heroesOnMap)
|
||||
{
|
||||
assert(map->isInTheMap(hero->visitablePos()));
|
||||
const auto & tile = map->getTile(hero->visitablePos());
|
||||
if (tile.terType->isWater())
|
||||
{
|
||||
auto handler = VLC->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum());
|
||||
CGBoat * boat = dynamic_cast<CGBoat*>(handler->create());
|
||||
handler->configureObject(boat, gs->getRandomGenerator());
|
||||
|
||||
boat->ID = Obj::BOAT;
|
||||
boat->subID = hero->getBoatType().getNum();
|
||||
boat->pos = hero->pos;
|
||||
boat->appearance = handler->getTemplates().front();
|
||||
boat->id = ObjectInstanceID(static_cast<si32>(gs->map->objects.size()));
|
||||
|
||||
map->objects.emplace_back(boat);
|
||||
map->addBlockVisTiles(boat);
|
||||
|
||||
boat->hero = hero;
|
||||
hero->boat = boat;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto obj : map->objects) //prisons
|
||||
{
|
||||
if(obj && obj->ID == Obj::PRISON)
|
||||
@ -2535,6 +2560,10 @@ void CGameState::buildBonusSystemTree()
|
||||
}
|
||||
// CStackInstance <-> CCreature, CStackInstance <-> CArmedInstance, CArtifactInstance <-> CArtifact
|
||||
// are provided on initializing / deserializing
|
||||
|
||||
// NOTE: calling deserializationFix() might be more correct option, but might lead to side effects
|
||||
for (auto hero : map->heroesOnMap)
|
||||
hero->boatDeserializationFix();
|
||||
}
|
||||
|
||||
void CGameState::deserializationFix()
|
||||
|
@ -174,6 +174,11 @@ EAlignment CFaction::getAlignment() const
|
||||
return alignment;
|
||||
}
|
||||
|
||||
EBoatId CFaction::getBoatType() const
|
||||
{
|
||||
return boatType.toEnum();
|
||||
}
|
||||
|
||||
TerrainId CFaction::getNativeTerrain() const
|
||||
{
|
||||
return nativeTerrain;
|
||||
@ -893,16 +898,6 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source)
|
||||
|
||||
warMachinesToLoad[town] = source["warMachine"];
|
||||
|
||||
|
||||
town->shipyardBoat = EBoatId::NONE;
|
||||
if (!source["boat"].isNull())
|
||||
{
|
||||
VLC->modh->identifiers.requestIdentifier("core:boat", source["boat"], [=](int32_t boatTypeID)
|
||||
{
|
||||
town->shipyardBoat = BoatId(boatTypeID);
|
||||
});
|
||||
}
|
||||
|
||||
town->mageLevel = static_cast<ui32>(source["mageGuild"].Float());
|
||||
|
||||
town->namesCount = 0;
|
||||
@ -1028,6 +1023,15 @@ CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode
|
||||
faction->creatureBg120 = source["creatureBackground"]["120px"].String();
|
||||
faction->creatureBg130 = source["creatureBackground"]["130px"].String();
|
||||
|
||||
faction->boatType = EBoatId::NONE;
|
||||
if (!source["boat"].isNull())
|
||||
{
|
||||
VLC->modh->identifiers.requestIdentifier("core:boat", source["boat"], [=](int32_t boatTypeID)
|
||||
{
|
||||
faction->boatType = BoatId(boatTypeID);
|
||||
});
|
||||
}
|
||||
|
||||
int alignment = vstd::find_pos(GameConstants::ALIGNMENT_NAMES, source["alignment"].String());
|
||||
if (alignment == -1)
|
||||
faction->alignment = EAlignment::NEUTRAL;
|
||||
@ -1158,25 +1162,6 @@ void CTownHandler::afterLoadFinalization()
|
||||
initializeRequirements();
|
||||
initializeOverridden();
|
||||
initializeWarMachines();
|
||||
|
||||
for(auto & faction : objects)
|
||||
{
|
||||
if (!faction->town)
|
||||
continue;
|
||||
|
||||
bool hasBoat = faction->town->shipyardBoat != EBoatId::NONE;
|
||||
bool hasShipyard = faction->town->buildings.count(BuildingID::SHIPYARD);
|
||||
|
||||
if ( hasBoat && !hasShipyard )
|
||||
logMod->warn("Town %s has boat but has no shipyard!", faction->getJsonKey());
|
||||
|
||||
if ( !hasBoat && hasShipyard )
|
||||
{
|
||||
logMod->warn("Town %s has shipyard but has no boat set!", faction->getJsonKey());
|
||||
// Mod compatibility for 1.3
|
||||
faction->town->shipyardBoat = EBoatId::CASTLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTownHandler::initializeRequirements()
|
||||
|
@ -204,6 +204,11 @@ public:
|
||||
EAlignment alignment = EAlignment::NEUTRAL;
|
||||
bool preferUndergroundPlacement = false;
|
||||
|
||||
/// Boat that will be used by town shipyard (if any)
|
||||
/// and for placing heroes directly on boat (in map editor, water prisons & taverns)
|
||||
BoatId boatType;
|
||||
|
||||
|
||||
CTown * town = nullptr; //NOTE: can be null
|
||||
|
||||
std::string creatureBg120;
|
||||
@ -226,6 +231,7 @@ public:
|
||||
bool hasTown() const override;
|
||||
TerrainId getNativeTerrain() const override;
|
||||
EAlignment getAlignment() const override;
|
||||
EBoatId getBoatType() const override;
|
||||
|
||||
void updateFrom(const JsonNode & data);
|
||||
void serializeJson(JsonSerializeFormat & handler);
|
||||
@ -236,6 +242,7 @@ public:
|
||||
h & identifier;
|
||||
h & index;
|
||||
h & nativeTerrain;
|
||||
h & boatType;
|
||||
h & alignment;
|
||||
h & town;
|
||||
h & creatureBg120;
|
||||
@ -282,8 +289,6 @@ public:
|
||||
ArtifactID warMachine;
|
||||
SpellID moatAbility;
|
||||
|
||||
/// boat that will be built by town shipyard, if exists
|
||||
BoatId shipyardBoat;
|
||||
// default chance for hero of specific class to appear in tavern, if field "tavern" was not set
|
||||
// resulting chance = sqrt(town.chance * heroClass.chance)
|
||||
ui32 defaultTavernChance;
|
||||
@ -349,7 +354,6 @@ public:
|
||||
h & mageLevel;
|
||||
h & primaryRes;
|
||||
h & warMachine;
|
||||
h & shipyardBoat;
|
||||
h & clientInfo;
|
||||
h & moatAbility;
|
||||
h & defaultTavernChance;
|
||||
|
@ -1282,7 +1282,7 @@ class BattleField : public BaseForID<BattleField, si32>
|
||||
DLL_LINKAGE static BattleField fromString(const std::string & identifier);
|
||||
};
|
||||
|
||||
enum class EBoatId
|
||||
enum class EBoatId : int32_t
|
||||
{
|
||||
NONE = -1,
|
||||
NECROPOLIS = 0,
|
||||
|
@ -323,7 +323,7 @@ void MetaString::jsonSerialize(JsonNode & dest) const
|
||||
for (const auto & entry : localStrings )
|
||||
{
|
||||
JsonNode value;
|
||||
value.Float() = static_cast<int>(entry.first) * 10000 + entry.second;
|
||||
value.Integer() = static_cast<int>(entry.first) * 10000 + entry.second;
|
||||
jsonLocalStrings.Vector().push_back(value);
|
||||
}
|
||||
|
||||
@ -344,7 +344,7 @@ void MetaString::jsonSerialize(JsonNode & dest) const
|
||||
for (const auto & entry : numbers )
|
||||
{
|
||||
JsonNode value;
|
||||
value.Float() = entry;
|
||||
value.Integer() = entry;
|
||||
jsonNumbers.Vector().push_back(value);
|
||||
}
|
||||
|
||||
|
@ -452,9 +452,8 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
|
||||
//Create a new boat for hero
|
||||
NewObject no;
|
||||
no.ID = Obj::BOAT;
|
||||
no.subID = BoatId(EBoatId::CASTLE);
|
||||
no.pos = CGBoat::translatePos(boatPos);
|
||||
|
||||
no.subID = getBoatType().getNum();
|
||||
|
||||
cb->sendAndApply(&no);
|
||||
|
||||
boatId = cb->getTopObj(boatPos)->id;
|
||||
@ -953,8 +952,7 @@ si32 CGHeroInstance::getManaNewTurn() const
|
||||
|
||||
BoatId CGHeroInstance::getBoatType() const
|
||||
{
|
||||
// hero can only generate boat via "Summon Boat" spell which always create same boat as in Necropolis shipyard
|
||||
return EBoatId::NECROPOLIS;
|
||||
return BoatId(VLC->townh->getById(type->heroClass->faction)->getBoatType());
|
||||
}
|
||||
|
||||
void CGHeroInstance::getOutOffsets(std::vector<int3> &offsets) const
|
||||
@ -1105,6 +1103,13 @@ int CGHeroInstance::maxSpellLevel() const
|
||||
void CGHeroInstance::deserializationFix()
|
||||
{
|
||||
artDeserializationFix(this);
|
||||
boatDeserializationFix();
|
||||
}
|
||||
|
||||
void CGHeroInstance::boatDeserializationFix()
|
||||
{
|
||||
if (boat)
|
||||
attachTo(const_cast<CGBoat&>(*boat));
|
||||
}
|
||||
|
||||
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const
|
||||
|
@ -274,6 +274,7 @@ public:
|
||||
void getCastDescription(const spells::Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override;
|
||||
void spendMana(ServerCallback * server, const int spellCost) const override;
|
||||
|
||||
void boatDeserializationFix();
|
||||
void deserializationFix();
|
||||
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
@ -682,7 +682,7 @@ void CGTownInstance::clearArmy() const
|
||||
|
||||
BoatId CGTownInstance::getBoatType() const
|
||||
{
|
||||
return town->shipyardBoat;
|
||||
return town->faction->boatType;
|
||||
}
|
||||
|
||||
int CGTownInstance::getMarketEfficiency() const
|
||||
|
@ -1294,11 +1294,6 @@ CGBoat::CGBoat()
|
||||
layer = EPathfindingLayer::EEPathfindingLayer::SAIL;
|
||||
}
|
||||
|
||||
void CGBoat::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
hero = nullptr;
|
||||
}
|
||||
|
||||
int3 CGBoat::translatePos(const int3& pos, bool reverse /* = false */)
|
||||
{
|
||||
//pos - offset we want to place the boat at the map
|
||||
|
@ -359,7 +359,6 @@ public:
|
||||
std::array<std::string, PlayerColor::PLAYER_LIMIT_I> flagAnimations;
|
||||
|
||||
CGBoat();
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
static int3 translatePos(const int3 &pos, bool reverse = false);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
|
@ -4428,7 +4428,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
|
||||
//Create a new boat for hero
|
||||
NewObject no;
|
||||
no.ID = Obj::BOAT;
|
||||
no.subID = BoatId(EBoatId::CASTLE);
|
||||
no.subID = nh->getBoatType().getNum();
|
||||
no.pos = hr.tile + int3(1,0,0);
|
||||
sendAndApply(&no);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user