Skip to content

Commit

Permalink
Fixed Monster Splitting property
Browse files Browse the repository at this point in the history
  • Loading branch information
DMD authored and DMD committed Oct 17, 2016
1 parent 8a4caa1 commit 842639c
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 5 deletions.
76 changes: 75 additions & 1 deletion TemplePlus/ability_fixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,26 @@
#include "d20.h"
#include "float_line.h"
#include "history.h"
#include "gamesystems/objects/objsystem.h"
#include "gamesystems/gamesystems.h"
#include "gamesystems/particlesystems.h"

// Ability Condition Fixes (for buggy abilities, including monster abilities)
class AbilityConditionFixes : public TempleFix {
public:
#define ABFIX(fname) static int fname ## (DispatcherCallbackArgs args);
#define HOOK_ORG(fname) static int (__cdecl* org ##fname)(DispatcherCallbackArgs) = replaceFunction<int(__cdecl)(DispatcherCallbackArgs)>
static int PoisonedOnBeginRound(DispatcherCallbackArgs args);;

static int MonsterSplittingHpChange(DispatcherCallbackArgs args);
static int MonsterOozeSplittingOnDamage(DispatcherCallbackArgs args);

void apply() override {

replaceFunction(0x100EA040, PoisonedOnBeginRound);

replaceFunction(0x100F7550, MonsterSplittingHpChange);
replaceFunction(0x100F7490, MonsterOozeSplittingOnDamage);

// fixes animal companion runoff crash (it didn't null the second part of the obj handle stored in args[1,2]
static void (__cdecl*orgCompanionRunoff)(SubDispNode*, objHndl , objHndl ) = replaceFunction<void(__cdecl)(SubDispNode*, objHndl, objHndl)>(0x100FC3D0, [](SubDispNode* sdn, objHndl owner, objHndl handle){
orgCompanionRunoff(sdn, owner, handle);
Expand Down Expand Up @@ -138,3 +145,70 @@ int AbilityConditionFixes::PoisonedOnBeginRound(DispatcherCallbackArgs args){
conds.ConditionRemove(args.objHndCaller, args.subDispNode->condNode);
return 0;
}

int AbilityConditionFixes::MonsterSplittingHpChange(DispatcherCallbackArgs args){
auto protoId = objSystem->GetProtoId(args.objHndCaller);
auto obj = objSystem->GetObject(args.objHndCaller);
auto loc = obj->GetLocationFull();
auto hpCur = objects.StatLevelGet(args.objHndCaller, stat_hp_current);
auto baseHp = obj->GetInt32(obj_f_hp_pts);
auto hpDam = obj->GetInt32(obj_f_hp_damage);

auto hpMod = (hpCur + hpDam) - baseHp;

if (hpCur <= 10)
return 0;

obj->SetInt32(obj_f_hp_pts, baseHp / 2);
obj->SetInt32(obj_f_hp_damage, (hpDam + hpMod) / 2);


auto protoHandle = objSystem->GetProtoHandle(protoId);
auto newMonster = objSystem->CreateObject(protoHandle, loc.location);
auto newMonObj = objSystem->GetObject(newMonster);
newMonObj->SetInt32(obj_f_hp_pts, baseHp / 2);
newMonObj->SetInt32(obj_f_hp_damage, (hpDam + hpMod) / 2);
newMonObj->SetInt32(obj_f_critter_flags, newMonObj->GetInt32(obj_f_critter_flags) | OCF_EXPERIENCE_AWARDED);

gameSystems->GetParticleSys().CreateAtObj("hit-Acid-medium", args.objHndCaller);
conds.ConditionRemove(args.objHndCaller, args.subDispNode->condNode);

return 0;
}

int AbilityConditionFixes::MonsterOozeSplittingOnDamage(DispatcherCallbackArgs args){

auto curHp = objects.StatLevelGet(args.objHndCaller, stat_hp_current);
if (curHp <= 10)
return 0;

GET_DISPIO(dispIOTypeDamage, DispIoDamage);
auto isSplitting = false;
auto protoId = objSystem->GetProtoId(args.objHndCaller);
if (protoId == 14142 && dispIo->damage.GetOverallDamageByType(DamageType::Electricity) > 0){
isSplitting = true;
dispIo->damage.AddModFactor(0.0f, DamageType::Electricity, 132);
}

if (dispIo->damage.GetOverallDamageByType(DamageType::Slashing) > 0) {
isSplitting = true;
dispIo->damage.AddModFactor(0.0f, DamageType::Slashing, 132);
}

if (dispIo->damage.GetOverallDamageByType(DamageType::Piercing) > 0) {
isSplitting = true;
dispIo->damage.AddModFactor(0.0f, DamageType::Piercing, 132);
}

if (dispIo->damage.GetOverallDamageByType(DamageType::PiercingAndSlashing) > 0) {
isSplitting = true;
dispIo->damage.AddModFactor(0.0f, DamageType::PiercingAndSlashing, 132);
}


if (isSplitting){
conds.AddTo(args.objHndCaller, "Monster Splitting", {});
}

return 0;
}
76 changes: 74 additions & 2 deletions TemplePlus/damage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,48 @@ void DamagePacket::CalcFinalDamage(){ // todo hook this

int DamagePacket::GetOverallDamageByType(DamageType damType)
{
// TODO
auto damTot = (double)0.0;

for (auto i=0u; i<this->diceCount; i++) {

if (damType == this->dice[i].type || damType == DamageType::Unspecified){
damTot += this->dice[i].rolledDamage;
if (i == 0) {
damTot += this->bonuses.GetEffectiveBonusSum();
}
}

}

for (auto i=0; i<this->damModCount; i++){
addresses.CalcDamageModFromFactor(this, &this->damageFactorModifiers[i], DamageType::Unspecified, DamageType::Unspecified);
}

for (auto i=0; i<this->damResCount; i++){
addresses.CalcDamageModFromDR(this, &this->damageResistances[i], DamageType::Unspecified, DamageType::Unspecified);
}

for (auto i=0; i<this->damResCount; i++){
if (damage.DamageTypeMatch(damType, this->damageResistances[i].type)){
damTot += this->damageResistances[i].damageReduced;
}
}

for (auto i = 0; i < this->damModCount; i++) {
if (damage.DamageTypeMatch(damType, this->damageResistances[i].type)){
damTot += this->damageFactorModifiers[i].damageReduced;
}
}

if (damTot < 0.0)
damTot = 0.0;

return damTot;
}

int DamagePacket::AddModFactor(float factor, DamageType damType, int damageMesLine){
return addresses.AddDamageModFactor(this, factor, damType, damageMesLine);
}

DamagePacket::DamagePacket(){
diceCount = 0;
damResCount = 0;
Expand Down Expand Up @@ -562,6 +594,46 @@ int Damage::AddDamageDiceWithDescr(DamagePacket* dmgPkt, int dicePacked, DamageT
return 0;
}

BOOL Damage::DamageTypeMatch(DamageType reduction, DamageType attackType){

if (attackType == DamageType::Subdual) {
if (reduction != DamageType::Subdual)
return FALSE;
}
else if (attackType == DamageType::Unspecified)
return TRUE;

if (reduction == DamageType::Unspecified || attackType == reduction)
return TRUE;

switch (attackType){
case DamageType::BludgeoningAndPiercing:
if (reduction == DamageType::Bludgeoning || reduction == DamageType::Piercing)
return TRUE;
break;
case DamageType::PiercingAndSlashing:
if (reduction == DamageType::Piercing || reduction == DamageType::Slashing)
return TRUE;
break;
case DamageType::SlashingAndBludgeoning:
if (reduction == DamageType::Slashing || reduction == DamageType::Bludgeoning)
return TRUE;
break;
case DamageType::SlashingAndBludgeoningAndPiercing:
if (reduction == DamageType::Bludgeoning || reduction == DamageType::Slashing
|| reduction == DamageType::Piercing || reduction == DamageType::BludgeoningAndPiercing
|| reduction == DamageType::PiercingAndSlashing || reduction == DamageType::SlashingAndBludgeoning
|| reduction == DamageType::Subdual)
return TRUE;
break;
default:
return FALSE;

}

return FALSE;
}

Damage::Damage(){
damageMes = 0;
// damageMes = addresses.damageMes;
Expand Down
3 changes: 2 additions & 1 deletion TemplePlus/damage.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct DamagePacket {
void AddAttackPower(int attackPower);
void CalcFinalDamage(); // calcualtes the finalDamage field
int GetOverallDamageByType(DamageType damType);

int AddModFactor(float factor, DamageType damType, int damageMesLine);
DamagePacket();
};

Expand Down Expand Up @@ -129,6 +129,7 @@ class Damage {
const char* GetMesline(unsigned damageMesLine);
int AddDamageDice(DamagePacket *dmgPkt, int dicePacked, DamageType damType, unsigned int damageMesLine);
int AddDamageDiceWithDescr(DamagePacket *dmgPkt, int dicePacked, DamageType damType, unsigned int damageMesLine, char* descr);
BOOL DamageTypeMatch(DamageType reduction, DamageType attackType);
Damage();
private:
void Init();
Expand Down
2 changes: 1 addition & 1 deletion TemplePlus/spell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2034,7 +2034,7 @@ uint32_t LegacySpellSystem::pickerArgsFromSpellEntry(SpellEntry* spEntry, Picker
if (spEntry->IsBaseModeTarget(UiPickerType::Area)
&& (spEntry->spellEnum == 133 // Dispel Magic
|| spEntry->spellEnum == 434) ){ // Silence
(*(uint64_t*)args->modeTarget ) |= (uint64_t)UiPickerType::AreaOrObj;
(*(uint64_t*)&args->modeTarget ) |= (uint64_t)UiPickerType::AreaOrObj;
}


Expand Down

0 comments on commit 842639c

Please sign in to comment.