本文整理汇总了C++中MathEnvironment类的典型用法代码示例。如果您正苦于以下问题:C++ MathEnvironment类的具体用法?C++ MathEnvironment怎么用?C++ MathEnvironment使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了MathEnvironment类的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: WriteStats
void psNPCLoader::WriteStats()
{
csRef<iDocumentNode> statsNode = npcRoot->CreateNodeBefore(CS_NODE_ELEMENT);
statsNode->SetValue("stats");
MathEnvironment baseSkillVal;
npc->GetSkillBaseValues(&baseSkillVal);
statsNode->SetAttributeAsInt("agi", baseSkillVal.Lookup("AGI")->GetRoundValue());
statsNode->SetAttributeAsInt("cha", baseSkillVal.Lookup("CHA")->GetRoundValue());
statsNode->SetAttributeAsInt("end", baseSkillVal.Lookup("END")->GetRoundValue());
statsNode->SetAttributeAsInt("int", baseSkillVal.Lookup("INT")->GetRoundValue());
statsNode->SetAttributeAsInt("str", baseSkillVal.Lookup("STR")->GetRoundValue());
statsNode->SetAttributeAsInt("wil", baseSkillVal.Lookup("WIL")->GetRoundValue());
}
示例2: TEST
TEST(MathScriptTest, StringTest2)
{
Foo foo;
MathScript *script = MathScript::Create("StringTest2", "\
HasWeapon = 0;\
SkillName = if(HasWeapon, 'Sword', \"Lah'ar\");\
Rank = Quux:GetSkillRank(SkillName);\
");
ASSERT_NE(script, NULL);
MathEnvironment env;
env.Define("Quux", &foo);
ASSERT_NE(env.Lookup("Quux"), NULL);
script->Evaluate(&env);
MathVar *rank = env.Lookup("Rank");
EXPECT_EQ(77, rank->GetValue());
MathScript::Destroy(script);
};
示例3: DebugOutput
void CombatManager::DebugOutput(psCombatGameEvent *event, const MathEnvironment & env)
{
MathVar *missed = env.Lookup("Missed"); // Missed = Attack missed the enemy
MathVar *dodged = env.Lookup("Dodged"); // Dodged = Attack dodged by enemy
MathVar *blocked = env.Lookup("Blocked"); // Blocked = Attack blocked by enemy
MathVar *damage = env.Lookup("FinalDamage"); // Actual damage done, if any
psItem* item = event->GetAttackerData()->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot() );
csString debug;
debug.Append( "-----Debug Combat Summary--------\n");
debug.AppendFmt( "%s attacks %s with slot %d , weapon %s, quality %1.2f, basedmg %1.2f/%1.2f/%1.2f\n",
event->attacker->GetName(),event->target->GetName(), event->GetWeaponSlot(),item->GetName(),item->GetItemQuality(),
item->GetDamage(PSITEMSTATS_DAMAGETYPE_SLASH),item->GetDamage(PSITEMSTATS_DAMAGETYPE_BLUNT),item->GetDamage(PSITEMSTATS_DAMAGETYPE_PIERCE));
debug.AppendFmt( "Missed: %1.6f Dodged: %1.6f Blocked: %1.6f", missed->GetValue(), dodged->GetValue(), blocked->GetValue());
debug.AppendFmt( "Damage: %1.1f\n", damage->GetValue());
Debug2(LOG_COMBAT, event->attacker->GetClientID(), "%s", debug.GetData());
}
示例4: TEST
TEST(MathScriptTest, BasicScript)
{
// Basic conversion from Fahrenheit to Celsius and Kelvin.
MathScript *script = MathScript::Create("TemperatureConv", "C = (F - 32) * 5/9; K = C + 273.15");
ASSERT_NE(script, NULL);
MathEnvironment env;
env.Define("F", 212.0);
script->Evaluate(&env);
MathVar *F = env.Lookup("F");
MathVar *C = env.Lookup("C");
MathVar *K = env.Lookup("K");
EXPECT_NE(F, NULL);
EXPECT_NE(C, NULL);
EXPECT_NE(K, NULL);
EXPECT_EQ(212.0, F->GetValue());
EXPECT_EQ(100.0, C->GetValue());
EXPECT_EQ(373.15, K->GetValue());
EXPECT_STREQ("373.15", K->ToString());
}
示例5: CalcModifierCostCap
float LootRandomizer::CalcModifierCostCap(psCharacter* chr)
{
float result = 1000.0;
if(modifierCostCalc)
{
// Use the mob's attributes to calculate modifier cost cap
MathEnvironment env;
env.Define("Actor", chr);
env.Define("MaxHP", chr->GetMaxHP().Current());
env.Define("MaxMana", chr->GetMaxMana().Current());
(void) modifierCostCalc->Evaluate(&env);
MathVar* modcap = env.Lookup("ModCap");
result = modcap->GetValue();
}
Debug2(LOG_LOOT,0,"DEBUG: Calculated cost cap %f\n", result);
return result;
}
示例6: randomgentest
void randomgentest(int limit)
{
csString scriptstr;
if (limit<0)
{
scriptstr = "Roll = rnd();";
limit=1;
}
else
{
scriptstr.Format("Roll = rnd(%d);",limit);
}
MathScript *script = MathScript::Create("randomgen test", scriptstr.GetData());
MathEnvironment env;
ASSERT_NE(script, NULL) << scriptstr.GetData() << " did not create script";
bool above1=false, abovehalflimit=false;
for (int i=0; i<100; i++) //try 100 times, since this is random
{
script->Evaluate(&env);
MathVar *roll = env.Lookup("Roll");
EXPECT_GE(roll->GetValue(), 0);
EXPECT_LE(roll->GetValue(), limit);
if (roll->GetValue()>1)
{
above1 = true;
}
if (2*roll->GetValue()>limit)
{
abovehalflimit = true;
}
}
if (limit>1)
{
EXPECT_TRUE(above1) << scriptstr << "never exceeds 1";
}
if (limit>0)
{
EXPECT_TRUE(abovehalflimit) << scriptstr << "never exceeds half of limit";
}
delete script;
}
示例7: CS_ASSERT
int EntityManager::CalculateFamiliarAffinity( psCharacter * chardata, size_t type, size_t lifecycle, size_t attacktool, size_t attacktype )
{
static MathScript *msAffinity;
int affinityValue = 0;
if (!msAffinity)
{
msAffinity = psserver->GetMathScriptEngine()->FindScript("CalculateFamiliarAffinity");
CS_ASSERT(msAffinity != NULL);
}
// Determine Familiar Type using Affinity Values
if ( msAffinity )
{
MathEnvironment env;
env.Define("Actor", chardata);
env.Define("Type", type);
env.Define("Lifecycle", lifecycle);
env.Define("AttackTool", attacktool);
env.Define("AttackType", attacktype);
msAffinity->Evaluate(&env);
MathVar *affinity = env.Lookup("Affinity");
affinityValue = affinity->GetRoundValue();
}
return affinityValue;
}
示例8: CPrintf
void psNPCLoader::ReadStats()
{
csRef<iDocumentNode> xmlnode = npcRoot->GetNode("stats");
if(!xmlnode)
{
CPrintf(CON_WARNING, "Warning: no <stats> tag found\n");
return;
}
MathEnvironment env;
env.Define("Actor", npc);
env.Define("STR", xmlnode->GetAttributeValueAsFloat("agi"));
env.Define("AGI", xmlnode->GetAttributeValueAsFloat("cha"));
env.Define("END", xmlnode->GetAttributeValueAsFloat("end"));
env.Define("INT", xmlnode->GetAttributeValueAsFloat("int"));
env.Define("WILL", xmlnode->GetAttributeValueAsFloat("str"));
env.Define("CHA", xmlnode->GetAttributeValueAsFloat("wil"));
psserver->GetCacheManager()->GetSetBaseSkillsScript()->Evaluate(&env);
}
示例9: Debug1
void ProgressionManager::AllocateKillDamage(gemActor *deadActor, int exp)
{
csArray<gemActor*> attackers;
// Last timestamp, used for breaking the loop when > 10 secs had gone
unsigned int lastTimestamp = 0;
float totalDamage = 0; // The denominator for the percentages
int i;
// First build list of attackers and determine how far to go back and what total dmg was.
for (i = (int) deadActor->GetDamageHistoryCount(); i > 0; i--)
{
AttackerHistory* history = deadActor->GetDamageHistory(i-1);
// 15 secs passed
if (lastTimestamp - history->TimeOfAttack() > 15000 && lastTimestamp != 0)
{
Debug1(LOG_COMBAT, 0, "15 secs passed between hits, breaking loop\n");
break;
}
lastTimestamp = history->TimeOfAttack();
totalDamage += history->Damage();
bool found = false;
gemActor* attacker = history->Attacker();
if (!attacker)
continue; // This attacker has disconnected since he did this damage.
// Have we already added that player?
for (size_t j = 0; j < attackers.GetSize(); j++)
{
if (attackers[j] == attacker)
{
found = true;
break;
}
}
// New player, add to list
if (!found)
{
attackers.Push(attacker);
}
}
int lastHistory = i;
for(size_t i = 0; i < attackers.GetSize(); i++)
{
gemActor* attacker = attackers[i];
float dmgMade = 0;
float mod = 0;
for (int j = (int) deadActor->GetDamageHistoryCount(); j > lastHistory; j--)
{
AttackerHistory* history = deadActor->GetDamageHistory(j-1);
if (history->Attacker() == attacker)
{
dmgMade += history->Damage();
}
}
if (!totalDamage)
{
Error2("%s was found to have zero totalDamage in damagehistory!", deadActor->GetName());
continue;
}
// Use the latest HP (needs to be redesigned when NPCs can cast heal spells on eachoter)
mod = dmgMade / totalDamage; // Get a 0.something value or 1 if we did all dmg
if (mod > 1.0)
mod = 1.0;
int final;
if(exp <= 0) //use automatically generated experience if exp doesn't have a valid value
{
MathEnvironment env;
env.Define("Killer", attacker);
env.Define("DeadActor", deadActor);
calc_dynamic_experience->Evaluate(&env);
final = env.Lookup("Exp")->GetValue();
}
示例10: Error2
void SpellManager::HandleAssembler(MsgEntry* me, Client* client)
{
psGlyphAssembleMessage mesg;
mesg.FromClient(me);
csArray<psItemStats*> assembler;
for(size_t i = 0; i < GLYPH_ASSEMBLER_SLOTS; i++)
{
if(mesg.glyphs[i] != 0)
{
psItemStats* stats = cacheManager->GetBasicItemStatsByID(mesg.glyphs[i]);
if(stats)
assembler.Push(stats);
}
}
if(assembler.GetSize() == 0)
{
psserver->SendSystemError(client->GetClientNum(), "There are no glyphs in the research slots.");
return;
}
if(!client->GetCharacterData()->Inventory().HasPurifiedGlyphs(assembler))
{
Error2("Client %i tried to research spell with glyphs he actually doesn't have", client->GetClientNum());
SendGlyphs(NULL,client);
return;
}
// Is the Glyph Sequence a Valid one?
psSpell* spell = FindSpell(client, assembler);
csString description("Your research didn't result in a valid spell.");
if(spell)
{
// Is this spell already in our spellbook?
psSpell* knownSpell = client->GetCharacterData()->GetSpellByName(spell->GetName());
if(knownSpell)
{
if(mesg.info)
{
psGlyphAssembleMessage newmsginfo(client->GetClientNum(), knownSpell->GetName(), knownSpell->GetImage(), knownSpell->GetDescription());
newmsginfo.SendMessage();
}
else
{
psserver->SendSystemInfo(client->GetClientNum(), "You know this spell already.");
}
return;
}
description = "A spell materializes for a second, but you then lose focus. Try again or increase your magic knowledge.";
}
if(mesg.info)
return;
csString name(" ");
csString image(" ");
const bool success = spell && psserver->GetRandom() * 100.0 < spell->ChanceOfResearchSuccess(client->GetCharacterData());
ProgressionScript* outcome = psserver->GetProgressionManager()->FindScript(success ? "ResearchSpellSuccess" : "ResearchSpellFailure");
if(outcome)
{
MathEnvironment env;
env.Define("Actor", client->GetActor());
outcome->Run(&env);
}
if(success)
{
description = spell->GetDescription();
name = spell->GetName();
image = spell->GetImage();
SaveSpell(client, name);
}
// Clear the description, if this is not valid glyph sequence for our player:
psGlyphAssembleMessage newmsg(client->GetClientNum(), name, image, description);
newmsg.SendMessage();
}
示例11: Debug1
//.........这里部分代码省略.........
gemActor* actor = new gemActor(gemSupervisor, cacheManager, entityManager, chardata,
raceinfo->mesh_name,
newinstance,
EntityManager::GetSingleton().FindSector(sectorinfo->name),
csVector3(x,y,z),yrot,
client->GetClientNum());
actor->SetupCharData();
if(!upload.verify)
{
if(!psServer::CharacterLoader.NewCharacterData(acctID,chardata))
{
Error1("Character could not be created.");
psCharRejectedMessage reject(me->clientnum);
psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET);
psserver->RemovePlayer(me->clientnum,"Your character could not be created in the database.");
delete chardata;
return;
}
}
// Check to see if a path name was set. If so we will use that to generate
// the character starting stats and skills.
if(upload.path != "None")
{
// Progression Event name is PATH_PathName
csString name("PATH_");
name.Append(upload.path);
ProgressionScript* script = psserver->GetProgressionManager()->FindScript(name.GetData());
if(script)
{
// The script uses the race base character points to calculate starting stats.
MathEnvironment env;
env.Define("CharPoints", raceinfo->initialCP);
env.Define("Actor", actor);
script->Run(&env);
}
}
else
{
//int cpUsage = psserver->charCreationManager->CalculateCPChoice( upload.choices ) +
// psserver->charCreationManager->CalculateCPLife(upload.lifeEvents );
for(size_t ci = 0; ci < upload.choices.GetSize(); ci++)
{
CharCreationManager::CreationChoice* choice = psserver->charCreationManager->FindChoice(upload.choices[ci]);
if(choice)
{
csString name(psserver->charCreationManager->FindChoice(upload.choices[ci])->name.GetData());
Debug3(LOG_NEWCHAR, me->clientnum,"Choice: %s Creation Script: %s", name.GetData(), choice->eventScript.GetData());
MathEnvironment env;
env.Define("Actor", actor);
if(choice->choiceArea == FATHER_JOB || choice->choiceArea == MOTHER_JOB)
{
int modifier = (choice->choiceArea == FATHER_JOB) ? upload.fatherMod : upload.motherMod;
if(modifier > 3 || modifier < 1)
modifier = 1;
env.Define("ParentStatus", modifier);
}
ProgressionScript* script = psserver->GetProgressionManager()->FindScript(choice->eventScript);
if(script)
script->Run(&env);
}
else
示例12: Debug2
void CombatManager::HandleCombatEvent(psCombatGameEvent *event)
{
psCharacter *attacker_data,*target_data;
int attack_result;
bool skipThisRound = false;
if (!event->GetAttacker() || !event->GetTarget()) // disconnected and deleted
{
#ifdef COMBAT_DEBUG
psserver->SendSystemError(event->AttackerCID, "Combat stopped as one participant logged of.");
#endif
return;
}
gemActor *gemAttacker = dynamic_cast<gemActor*> ((gemObject *) event->attacker);
gemActor *gemTarget = dynamic_cast<gemActor*> ((gemObject *) event->target);
attacker_data=event->GetAttackerData();
target_data=event->GetTargetData();
// If the attacker is no longer in attack mode abort.
if (gemAttacker->GetMode() != PSCHARACTER_MODE_COMBAT)
{
#ifdef COMBAT_DEBUG
psserver->SendSystemError(event->AttackerCID,
"Combat stopped as you left combat mode.");
#endif
return;
}
// If target is dead, abort.
if (!gemTarget->IsAlive() )
{
#ifdef COMBAT_DEBUG
psserver->SendSystemResult(event->AttackerCID, "Combat stopped as one participant logged of.");
#endif
return;
}
// If the slot is no longer attackable, abort
if (!attacker_data->Inventory().CanItemAttack(event->GetWeaponSlot()))
{
#ifdef COMBAT_DEBUG
psserver->SendSystemError(event->AttackerCID, "Combat stopped as you have no longer an attackable item equipped.");
#endif
return;
}
if (attacker_data->Inventory().GetEquipmentObject(event->GetWeaponSlot()).eventId != event->id)
{
#ifdef COMBAT_DEBUG
psserver->SendSystemError(event->AttackerCID, "Ignored combat event as newer is in.");
#endif
return;
}
psItem* weapon = attacker_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot());
// weapon became unwieldable
csString response;
if(weapon!=NULL && !weapon->CheckRequirements(attacker_data,response))
{
Debug2(LOG_COMBAT, gemAttacker->GetClientID(),"%s has lost use of weapon", gemAttacker->GetName() );
psserver->SendSystemError(event->AttackerCID, "You can't use your %s any more.", weapon->GetName() );
return;
}
// If the weapon in the slot has been changed, skip a turn (latency for this slot may also have changed)
if (event->WeaponID != weapon->GetUID())
{
Debug2(LOG_COMBAT, gemAttacker->GetClientID(),"%s has changed weapons mid battle", gemAttacker->GetName() );
#ifdef COMBAT_DEBUG
psserver->SendSystemError(event->AttackerCID, "Weapon changed. Skipping");
#endif
skipThisRound = true;
}
Client * attacker_client = psserver->GetNetManager()->GetClient(event->AttackerCID);
if (attacker_client)
{
// Input the stamina data
MathEnvironment env;
env.Define("Actor", event->GetAttacker());
env.Define("Weapon", weapon);
staminacombat->Evaluate(&env);
MathVar *PhyDrain = env.Lookup("PhyDrain");
MathVar *MntDrain = env.Lookup("MntDrain");
if ( (attacker_client->GetCharacterData()->GetStamina(true) < PhyDrain->GetValue())
|| (attacker_client->GetCharacterData()->GetStamina(false) < MntDrain->GetValue()) )
{
StopAttack(attacker_data->GetActor());
psserver->SendSystemError(event->AttackerCID, "You are too tired to attack.");
return;
}
// If the target has become impervious, abort and give up attacking
if (!attacker_client->IsAllowedToAttack(gemTarget))
{
StopAttack(attacker_data->GetActor());
//.........这里部分代码省略.........
示例13: ApplyCombatEvent
void CombatManager::ApplyCombatEvent(psCombatGameEvent *event, int attack_result)
{
psCharacter *attacker_data = event->GetAttackerData();
psCharacter *target_data=event->GetTargetData();
MathVar *weaponDecay = NULL;
MathVar *blockDecay = NULL;
MathVar *armorDecay = NULL;
MathEnvironment env;
psItem *weapon = attacker_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot());
psItem *blockingWeapon = target_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot(),true);
psItem *struckArmor = target_data->Inventory().GetEffectiveArmorInSlot(event->AttackLocation);
// there may only be a decay if you actually hit your target by some means
if(attack_result == ATTACK_DAMAGE || attack_result == ATTACK_BLOCKED)
{
// we are guaranteed some armor is present - real one, race one or base one
CS_ASSERT(struckArmor);
float ArmorVsWeapon = weapon->GetArmorVSWeaponResistance(struckArmor->GetBaseStats());
// clamp value between 0 and 1
ArmorVsWeapon = ArmorVsWeapon > 1.0F ? 1.0F : ArmorVsWeapon < 0.0F ? 0.0F : ArmorVsWeapon;
env.Define("Weapon", weapon); // weapon that was used to attack
env.Define("BlockingWeapon", blockingWeapon); // weapon that blocked the attack
env.Define("Armor", struckArmor); // armor hit
env.Define("ArmorVsWeapon", ArmorVsWeapon); // armor vs weapon effectiveness
env.Define("Damage", event->FinalDamage); // actual damage dealt
env.Define("Blocked", (attack_result == ATTACK_BLOCKED)); // identifies whether this attack was blocked
calc_decay->Evaluate(&env);
weaponDecay = env.Lookup("WeaponDecay");
blockDecay = env.Lookup("BlockingDecay");
armorDecay = env.Lookup("ArmorDecay");
}
gemActor *gemAttacker = dynamic_cast<gemActor*> ((gemObject *) event->attacker);
gemActor *gemTarget = dynamic_cast<gemActor*> ((gemObject *) event->target);
switch (attack_result)
{
case ATTACK_DAMAGE:
{
bool isNearlyDead = false;
if (target_data->GetMaxHP().Current() > 0.0 && target_data->GetHP()/target_data->GetMaxHP().Current() > 0.2)
{
if ((target_data->GetHP() - event->FinalDamage) / target_data->GetMaxHP().Current() <= 0.2)
isNearlyDead = true;
}
psCombatEventMessage ev(event->AttackerCID,
isNearlyDead ? psCombatEventMessage::COMBAT_DAMAGE_NEARLY_DEAD : psCombatEventMessage::COMBAT_DAMAGE,
gemAttacker->GetEID(),
gemTarget->GetEID(),
event->AttackLocation,
event->FinalDamage,
weapon->GetAttackAnimID(gemAttacker->GetCharacterData()),
gemTarget->FindAnimIndex("hit"));
ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE);
// Apply final damage
if (target_data!=NULL)
{
gemTarget->DoDamage(gemAttacker,event->FinalDamage);
if (gemAttacker)
{
gemAttacker->InvokeAttackScripts(gemTarget, weapon);
}
if (gemTarget)
{
gemTarget->InvokeDefenseScripts(gemAttacker, weapon);
if(isNearlyDead)
{
gemTarget->InvokeNearlyDeadScripts(gemAttacker, weapon);
}
}
}
// If the target wasn't in combat, it is now...
// Note that other modes shouldn't be interrupted automatically
if (gemTarget->GetMode() == PSCHARACTER_MODE_PEACE || gemTarget->GetMode() == PSCHARACTER_MODE_WORK)
{
if (gemTarget->GetClient()) // Set reciprocal target
gemTarget->GetClient()->SetTargetObject(gemAttacker,true);
// The default stance is 'Fully Defensive'.
Stance initialStance = GetStance(cacheManager, "FullyDefensive");
AttackSomeone(gemTarget,gemAttacker,initialStance);
}
if (weapon)
{
weapon->AddDecay(weaponDecay->GetValue());
}
if (struckArmor)
//.........这里部分代码省略.........
示例14: diff
/**
* This is the meat and potatoes of the combat engine here.
*/
int CombatManager::CalculateAttack(psCombatGameEvent *event, psItem* subWeapon)
{
INVENTORY_SLOT_NUMBER otherHand = event->GetWeaponSlot() == PSCHARACTER_SLOT_LEFTHAND ? PSCHARACTER_SLOT_RIGHTHAND : PSCHARACTER_SLOT_LEFTHAND;
event->AttackLocation = (INVENTORY_SLOT_NUMBER) targetLocations[randomgen->Get((int) targetLocations.GetSize())];
gemObject *attacker = event->GetAttacker();
gemObject *target = event->GetTarget();
// calculate difference between target and attacker location - to be used for angle validation
csVector3 diff(0); // initialize to some big value that shows an error
{
csVector3 attackPos, targetPos;
iSector *attackSector, *targetSector;
attacker->GetPosition(attackPos, attackSector);
target->GetPosition(targetPos, targetSector);
if((attacker->GetInstance() != target->GetInstance() &&
attacker->GetInstance() != INSTANCE_ALL && target->GetInstance() != INSTANCE_ALL) ||
!(entityManager->GetWorld()->WarpSpace(targetSector, attackSector, targetPos)))
{
return ATTACK_OUTOFRANGE;
}
diff = targetPos - attackPos;
}
MathEnvironment env;
env.Define("Attacker", attacker);
env.Define("Target", target);
env.Define("AttackWeapon", event->GetAttackerData()->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot()));
env.Define("AttackWeaponSecondary", subWeapon);
env.Define("TargetWeapon", event->GetTargetData()->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot(), true));
env.Define("TargetWeaponSecondary", event->GetTargetData()->Inventory().GetEffectiveWeaponInSlot(otherHand,true));
env.Define("AttackLocationItem", event->GetTargetData()->Inventory().GetEffectiveArmorInSlot(event->AttackLocation));
env.Define("DiffX", diff.x ? diff.x : 0.00001F); // force minimal value
env.Define("DiffY", diff.y ? diff.y : 0.00001F); // force minimal value
env.Define("DiffZ", diff.z ? diff.z : 0.00001F); // force minimal value
calc_damage->Evaluate(&env);
if (DoLogDebug2(LOG_COMBAT, event->GetAttackerData()->GetPID().Unbox()))
{
CPrintf(CON_DEBUG, "Variables for Calculate Damage:\n");
env.DumpAllVars();
}
MathVar *badrange = env.Lookup("BadRange"); // BadRange = Target is too far away
MathVar *badangle = env.Lookup("BadAngle"); // BadAngle = Attacker doesn't aim at enemy
MathVar *missed = env.Lookup("Missed"); // Missed = Attack missed the enemy
MathVar *dodged = env.Lookup("Dodged"); // Dodged = Attack dodged by enemy
MathVar *blocked = env.Lookup("Blocked"); // Blocked = Attack blocked by enemy
MathVar *damage = env.Lookup("FinalDamage"); // Actual damage done, if any
if (badrange && badrange->GetValue() < 0.0)
return ATTACK_OUTOFRANGE;
else if (badangle && badangle->GetValue() < 0.0)
return ATTACK_BADANGLE;
else if (missed && missed->GetValue() < 0.0)
return ATTACK_MISSED;
else if (dodged && dodged->GetValue() < 0.0)
return ATTACK_DODGED;
else if (blocked && blocked->GetValue() < 0.0)
return ATTACK_BLOCKED;
event->FinalDamage = damage->GetValue();
DebugOutput(event, env);
return ATTACK_DAMAGE;
}