1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Entities redesign and a few ERM features

* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
This commit is contained in:
AlexVinS
2018-03-17 17:58:30 +03:00
committed by AlexVinS
parent 11bb46780a
commit ecaa9f5d0b
475 changed files with 22491 additions and 7123 deletions

View File

@@ -27,9 +27,9 @@ AdventureSpellMechanics::AdventureSpellMechanics(const CSpell * s):
{
}
bool AdventureSpellMechanics::adventureCast(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
bool AdventureSpellMechanics::adventureCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
if(!owner->isAdventureSpell())
if(!owner->isAdventure())
{
env->complain("Attempt to cast non adventure spell in adventure mode");
return false;
@@ -43,7 +43,8 @@ bool AdventureSpellMechanics::adventureCast(const SpellCastEnvironment * env, co
return false;
}
const int cost = caster->getSpellCost(owner);
const auto level = caster->getSpellSchoolLevel(owner);
const auto cost = owner->getCost(level);
if(!caster->canCastThisSpell(owner))
{
@@ -65,12 +66,12 @@ bool AdventureSpellMechanics::adventureCast(const SpellCastEnvironment * env, co
return result != ESpellCastResult::ERROR;
}
ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
if(owner->hasEffects())
{
//todo: cumulative effects support
const int schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
std::vector<Bonus> bonuses;
@@ -81,7 +82,7 @@ ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(const SpellCastE
GiveBonus gb;
gb.id = parameters.caster->id.getNum();
gb.bonus = b;
env->sendAndApply(&gb);
env->apply(&gb);
}
return ESpellCastResult::OK;
@@ -94,25 +95,26 @@ ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(const SpellCastE
}
}
ESpellCastResult AdventureSpellMechanics::beginCast(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult AdventureSpellMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
return ESpellCastResult::OK;
}
void AdventureSpellMechanics::performCast(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
void AdventureSpellMechanics::performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
AdvmapSpellCast asc;
asc.casterID = parameters.caster->id;
asc.spellID = owner->id;
env->sendAndApply(&asc);
env->apply(&asc);
ESpellCastResult result = applyAdventureEffects(env, parameters);
endCast(env, parameters, result);
}
void AdventureSpellMechanics::endCast(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const ESpellCastResult result) const
void AdventureSpellMechanics::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const ESpellCastResult result) const
{
const int cost = parameters.caster->getSpellCost(owner);
const auto level = parameters.caster->getSpellSchoolLevel(owner);
const auto cost = owner->getCost(level);
switch(result)
{
@@ -122,7 +124,7 @@ void AdventureSpellMechanics::endCast(const SpellCastEnvironment * env, const Ad
sm.hid = parameters.caster->id;
sm.absolute = false;
sm.val = -cost;
env->sendAndApply(&sm);
env->apply(&sm);
}
break;
default:
@@ -136,7 +138,7 @@ SummonBoatMechanics::SummonBoatMechanics(const CSpell * s):
{
}
ESpellCastResult SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
if(parameters.caster->boat)
{
@@ -144,7 +146,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvir
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 333);//%s is already in boat
iw.text.addReplacement(parameters.caster->name);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::CANCEL;
}
@@ -154,20 +156,20 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvir
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 334);//There is no place to put the boat.
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::CANCEL;
}
const int schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
//check if spell works at all
if(env->getRandomGenerator().nextInt(99) >= owner->getPower(schoolLevel)) //power is % chance of success
if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success
{
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
iw.text.addReplacement(parameters.caster->name);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::OK;
}
@@ -197,14 +199,14 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvir
cop.objid = nearest->id;
cop.nPos = summonPos + int3(1,0,0);
cop.flags = 1;
env->sendAndApply(&cop);
env->apply(&cop);
}
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
{
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 335); //There are no boats to summon.
env->sendAndApply(&iw);
env->apply(&iw);
}
else //create boat
{
@@ -212,7 +214,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(const SpellCastEnvir
no.ID = Obj::BOAT;
no.subID = parameters.caster->getBoatType();
no.pos = summonPos + int3(1,0,0);
env->sendAndApply(&no);
env->apply(&no);
}
return ESpellCastResult::OK;
}
@@ -223,17 +225,17 @@ ScuttleBoatMechanics::ScuttleBoatMechanics(const CSpell * s):
{
}
ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
const int schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
//check if spell works at all
if(env->getRandomGenerator().nextInt(99) >= owner->getPower(schoolLevel)) //power is % chance of success
if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success
{
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
iw.text.addReplacement(parameters.caster->name);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::OK;
}
@@ -253,7 +255,7 @@ ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(const SpellCastEnvi
RemoveObject ro;
ro.id = t->visitableObjects.back()->id;
env->sendAndApply(&ro);
env->apply(&ro);
return ESpellCastResult::OK;
}
@@ -263,7 +265,7 @@ DimensionDoorMechanics::DimensionDoorMechanics(const CSpell * s):
{
}
ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
if(!env->getMap()->isInTheMap(parameters.pos))
{
@@ -292,33 +294,33 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(const SpellCastEn
return ESpellCastResult::ERROR;
}
const int schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
const int movementCost = GameConstants::BASE_MOVEMENT_COST * ((schoolLevel >= 3) ? 2 : 3);
std::stringstream cachingStr;
cachingStr << "source_" << Bonus::SPELL_EFFECT << "id_" << owner->id.num;
if(parameters.caster->getBonuses(Selector::source(Bonus::SPELL_EFFECT, owner->id), Selector::all, cachingStr.str())->size() >= owner->getPower(schoolLevel)) //limit casts per turn
if(parameters.caster->getBonuses(Selector::source(Bonus::SPELL_EFFECT, owner->id), Selector::all, cachingStr.str())->size() >= owner->getLevelPower(schoolLevel)) //limit casts per turn
{
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today.
iw.text.addReplacement(parameters.caster->name);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::CANCEL;
}
GiveBonus gb;
gb.id = parameters.caster->id.getNum();
gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::SPELL_EFFECT, 0, owner->id);
env->sendAndApply(&gb);
env->apply(&gb);
if(!dest->isClear(curr)) //wrong dest tile
{
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 70); //Dimension Door failed!
env->sendAndApply(&iw);
env->apply(&iw);
}
else if(env->moveHero(parameters.caster->id, parameters.pos + parameters.caster->getVisitableOffset(), true))
{
@@ -328,7 +330,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(const SpellCastEn
smp.val = parameters.caster->movement - movementCost;
else
smp.val = 0;
env->sendAndApply(&smp);
env->apply(&smp);
}
return ESpellCastResult::OK;
}
@@ -339,13 +341,13 @@ TownPortalMechanics::TownPortalMechanics(const CSpell * s):
{
}
ESpellCastResult TownPortalMechanics::applyAdventureEffects(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
const CGTownInstance * destination = nullptr;
const int moveCost = movementCost(parameters);
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
{
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
{
std::vector <const CGTownInstance*> pool = getPossibleTowns(env, parameters);
destination = findNearestTown(env, parameters, pool);
@@ -360,7 +362,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(const SpellCastEnvir
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 123);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::CANCEL;
}
}
@@ -425,12 +427,12 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(const SpellCastEnvir
SetMovePoints smp;
smp.hid = parameters.caster->id;
smp.val = std::max<ui32>(0, parameters.caster->movement - moveCost);
env->sendAndApply(&smp);
env->apply(&smp);
}
return ESpellCastResult::OK;
}
ESpellCastResult TownPortalMechanics::beginCast(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
std::vector<const CGTownInstance *> towns = getPossibleTowns(env, parameters);
@@ -439,7 +441,7 @@ ESpellCastResult TownPortalMechanics::beginCast(const SpellCastEnvironment * env
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 124);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::CANCEL;
}
@@ -450,7 +452,7 @@ ESpellCastResult TownPortalMechanics::beginCast(const SpellCastEnvironment * env
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 125);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::CANCEL;
}
@@ -495,7 +497,7 @@ ESpellCastResult TownPortalMechanics::beginCast(const SpellCastEnvironment * env
InfoWindow iw;
iw.player = parameters.caster->tempOwner;
iw.text.addTxt(MetaString::GENERAL_TXT, 124);
env->sendAndApply(&iw);
env->apply(&iw);
return ESpellCastResult::CANCEL;
}
@@ -513,7 +515,7 @@ ESpellCastResult TownPortalMechanics::beginCast(const SpellCastEnvironment * env
return ESpellCastResult::OK;
}
const CGTownInstance * TownPortalMechanics::findNearestTown(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector <const CGTownInstance *> & pool) const
const CGTownInstance * TownPortalMechanics::findNearestTown(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters, const std::vector <const CGTownInstance *> & pool) const
{
if(pool.empty())
return nullptr;
@@ -534,7 +536,7 @@ const CGTownInstance * TownPortalMechanics::findNearestTown(const SpellCastEnvir
return *nearest;
}
std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
std::vector <const CGTownInstance*> ret;
@@ -542,7 +544,7 @@ std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(const
for(const auto & color : team->players)
{
for(auto currTown : env->getCb()->getPlayer(color)->towns)
for(auto currTown : env->getCb()->getPlayerState(color)->towns)
{
ret.push_back(currTown.get());
}
@@ -550,7 +552,7 @@ std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(const
return ret;
}
int TownPortalMechanics::movementCost(const AdventureSpellCastParameters & parameters) const
int32_t TownPortalMechanics::movementCost(const AdventureSpellCastParameters & parameters) const
{
return GameConstants::BASE_MOVEMENT_COST * ((parameters.caster->getSpellSchoolLevel(owner) >= 3) ? 2 : 3);
}
@@ -561,13 +563,13 @@ ViewMechanics::ViewMechanics(const CSpell * s):
{
}
ESpellCastResult ViewMechanics::applyAdventureEffects(const SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
ShowWorldViewEx pack;
pack.player = parameters.caster->getOwner();
const int spellLevel = parameters.caster->getSpellSchoolLevel(owner);
const auto spellLevel = parameters.caster->getSpellSchoolLevel(owner);
const auto & fowMap = env->getCb()->getPlayerTeam(parameters.caster->getOwner())->fogOfWarMap;
@@ -583,7 +585,7 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(const SpellCastEnvironment
}
}
env->sendAndApply(&pack);
env->apply(&pack);
return ESpellCastResult::OK;
}
@@ -594,7 +596,7 @@ ViewAirMechanics::ViewAirMechanics(const CSpell * s):
{
}
bool ViewAirMechanics::filterObject(const CGObjectInstance * obj, const int spellLevel) const
bool ViewAirMechanics::filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const
{
return (obj->ID == Obj::ARTIFACT) || (spellLevel > 1 && obj->ID == Obj::HERO) || (spellLevel > 2 && obj->ID == Obj::TOWN);
}
@@ -605,7 +607,7 @@ ViewEarthMechanics::ViewEarthMechanics(const CSpell * s):
{
}
bool ViewEarthMechanics::filterObject(const CGObjectInstance * obj, const int spellLevel) const
bool ViewEarthMechanics::filterObject(const CGObjectInstance * obj, const int32_t spellLevel) const
{
return (obj->ID == Obj::RESOURCE) || (spellLevel > 1 && obj->ID == Obj::MINE);
}