From 189d40706feea796fe9307c915f29d2158769357 Mon Sep 17 00:00:00 2001 From: fusion32 Date: Sun, 1 Jun 2025 22:51:33 -0300 Subject: more work on spell primitives --- reference/game.c | 1646 ------------------------------------------------------ src/creature.cc | 4 +- src/creature.hh | 5 + src/enums.hh | 13 + src/magic.cc | 591 +++++++++++++++++--- src/player.hh | 2 + src/stubs.hh | 2 + 7 files changed, 552 insertions(+), 1711 deletions(-) diff --git a/reference/game.c b/reference/game.c index 10f5705..aee0dd9 100644 --- a/reference/game.c +++ b/reference/game.c @@ -20988,1612 +20988,6 @@ void __static_initialization_and_destruction_0(int __initialize_p,int __priority return; } - - -int Direction(int dx,int dy) - -{ - int iVar1; - int r; - uint uVar2; - - if ((dx != 0) || (((uVar2 = 0, dy != 0 && (uVar2 = 7, dy < 1)) && (uVar2 = 3, -1 < dy)))) { - iVar1 = (dy << 8) / dx; - uVar2 = 7; - if (iVar1 < -0x26a) { - uVar2 = 3; - } - else if (iVar1 < -0x6a) { - uVar2 = 2; - } - else if (iVar1 < 0x6a) { - uVar2 = 1; - } - else if (iVar1 < 0x26a) { - uVar2 = 8; - } - if (dx == -1 || SCARRY4(dx,1) != dx + 1 < 0) { - uVar2 = uVar2 + 4; - } - if (8 < uVar2) { - uVar2 = uVar2 - 8; - } - } - return uVar2; -} - - - -void CheckSpellbook(TCreature *cr,int SpellNr) - -{ - bool bVar1; - undefined4 *puVar2; - - if (cr == (TCreature *)0x0) { - error(&DAT_080fa3e0); - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; -LAB_0807e620: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); - } - if (cr->Type == PLAYER) { - // try { // try from 0807e5f2 to 0807e643 has its CatchHandler @ 0807e658 - bVar1 = CheckRight(cr->ID,ALL_SPELLS); - if (!bVar1) { - bVar1 = TPlayer::SpellKnown((TPlayer *)cr,SpellNr); - if (!bVar1) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0x20; - goto LAB_0807e620; - } - } - } - return; -} - - - -void CheckAccount(TCreature *cr,int SpellNr) - -{ - bool bVar1; - undefined4 *puVar2; - - if (cr == (TCreature *)0x0) { - error(&DAT_080fa460); - } - else { - if (SpellNr - 1U < 0xff) { - if ((cr->Type != PLAYER) || ((SpellList[SpellNr].Flags & 2) == 0)) { - return; - } - // try { // try from 0807e6c1 to 0807e723 has its CatchHandler @ 0807e726 - bVar1 = CheckRight(cr->ID,PREMIUM_ACCOUNT); - if (bVar1) { - return; - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0x33; - goto LAB_0807e6dc; - } - error(&DAT_080fa420,SpellNr); - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; -LAB_0807e6dc: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -void CheckLevel(TCreature *cr,int SpellNr) - -{ - ushort uVar1; - TSkill *this; - bool bVar2; - TSkill *sk; - int iVar3; - undefined4 *puVar4; - char *Text; - - if (cr == (TCreature *)0x0) { - Text = &DAT_080fa4c0; - } - else { - if (cr->Type != PLAYER) { - return; - } - // try { // try from 0807e781 to 0807e7dd has its CatchHandler @ 0807e800 - bVar2 = CheckRight(cr->ID,ALL_SPELLS); - if (bVar2) { - return; - } - this = (cr->super_TSkillBase).Skills[0]; - uVar1 = SpellList[SpellNr].Level; - if (this != (TSkill *)0x0) { - iVar3 = TSkill::Get(this); - if ((int)(uint)uVar1 <= iVar3) { - return; - } - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x3c; - goto LAB_0807e7ba; - } - Text = "CheckLevel: Kein Skill LEVEL.\n"; - } - error(Text); - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; -LAB_0807e7ba: - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -void CheckRuneLevel(TCreature *cr,int SpellNr) - -{ - ushort uVar1; - TSkill *this; - bool bVar2; - TSkill *sk; - int iVar3; - undefined4 *puVar4; - char *Text; - - if (cr == (TCreature *)0x0) { - Text = &DAT_080fa540; - } - else { - if (cr->Type != PLAYER) { - return; - } - // try { // try from 0807e861 to 0807e8bd has its CatchHandler @ 0807e8e0 - bVar2 = CheckRight(cr->ID,ALL_SPELLS); - if (bVar2) { - return; - } - this = (cr->super_TSkillBase).Skills[1]; - uVar1 = SpellList[SpellNr].RuneLevel; - if (this != (TSkill *)0x0) { - iVar3 = TSkill::Get(this); - if ((int)(uint)uVar1 <= iVar3) { - return; - } - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0x21; - goto LAB_0807e89a; - } - Text = "CheckLevel: Kein Skill MAGLEVEL.\n"; - } - error(Text); - puVar4 = (undefined4 *)__cxa_allocate_exception(4); - *puVar4 = 0xffffffff; -LAB_0807e89a: - // WARNING: Subroutine does not return - __cxa_throw(puVar4,&RESULT::typeinfo,0); -} - - - -void CheckMagicItem(TCreature *cr,ObjectType *Type) - -{ - bool bVar1; - int iVar2; - undefined4 *puVar3; - ObjectType local_1c [4]; - - if (cr == (TCreature *)0x0) { - error(&DAT_080fa580); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; -LAB_0807e98e: - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); - } - if (cr->Type == PLAYER) { - // try { // try from 0807e941 to 0807e9b1 has its CatchHandler @ 0807e9c6 - bVar1 = CheckRight(cr->ID,ALL_SPELLS); - if (!bVar1) { - ObjectType::setTypeID(local_1c,Type->TypeID); - iVar2 = CountInventoryObjects(cr->ID,local_1c,0); - if (iVar2 == 0) { - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0x22; - goto LAB_0807e98e; - } - } - } - return; -} - - - -void CheckRing(TCreature *cr,int param_2) - -{ - undefined4 *puVar1; - - if (cr != (TCreature *)0x0) { - if (cr->Type == PLAYER) { - // try { // try from 0807ea11 to 0807ea4d has its CatchHandler @ 0807ea50 - CheckRight(cr->ID,ALL_SPELLS); - } - return; - } - error(&DAT_080fa5c0); - puVar1 = (undefined4 *)__cxa_allocate_exception(4); - *puVar1 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar1,&RESULT::typeinfo,0); -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void CheckAffectedPlayers(void) - -{ - bool bVar1; - ulong uVar2; - undefined4 *puVar3; - TPlayer *in_stack_00000004; - Object local_4c [4]; - Object local_3c [4]; - Object local_2c; - Object Obj; - - if (in_stack_00000004 == (TPlayer *)0x0) { - error(&DAT_080fa600); - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0xffffffff; -LAB_0807eb78: - // WARNING: Subroutine does not return - __cxa_throw(puVar3,&RESULT::typeinfo,0); - } - if ((((in_stack_00000004->super_TCreature).Type == PLAYER) && - ((in_stack_00000004->super_TCreature).Combat.SecureMode != '\0')) && (WorldType == NORMAL)) - { - // try { // try from 0807eace to 0807eb9b has its CatchHandler @ 0807ebb0 - GetFirstObject(); - if (local_2c.ObjectID != NONE.ObjectID) { - do { - local_4c[0].ObjectID = NONE.ObjectID; - local_3c[0].ObjectID = NONE.ObjectID; - Object::getObjectType(local_4c); - if (local_4c[0].ObjectID == 99) { - uVar2 = Object::getCreatureID(&local_2c); - bVar1 = IsCreaturePlayer(uVar2); - if ((bVar1) && - (uVar2 = Object::getCreatureID(&local_2c), - uVar2 != (in_stack_00000004->super_TCreature).ID)) { - uVar2 = Object::getCreatureID(&local_2c); - bVar1 = TPlayer::IsAttackJustified(in_stack_00000004,uVar2); - if (!bVar1) { - puVar3 = (undefined4 *)__cxa_allocate_exception(4); - *puVar3 = 0x3a; - goto LAB_0807eb78; - } - } - } - Object::getNextObject(local_3c); - local_2c.ObjectID = local_3c[0].ObjectID; - } while (local_3c[0].ObjectID != NONE.ObjectID); - } - } - return; -} - -int ComputeDamage(TCreature *cr,int SpellNr,int Damage,int Variation) - -{ - int iVar1; - int iVar2; - long lVar3; - int proz; - - if (Variation != 0) { - lVar3 = random(); - Damage = Damage + lVar3; - } - if ((cr != (TCreature *)0x0) && (cr->Type == PLAYER)) { - iVar1 = TSkill::Get((cr->super_TSkillBase).Skills[0]); - iVar2 = TSkill::Get((cr->super_TSkillBase).Skills[1]); - iVar1 = iVar2 * 3 + iVar1 * 2; - if (SpellNr != 0) { - if (((SpellList[SpellNr].Flags & 4) != 0) && (100 < iVar1)) { - iVar1 = 100; - } - if (((SpellList[SpellNr].Flags & 8) != 0) && (iVar1 < 100)) { - iVar1 = 100; - } - } - Damage = (Damage * iVar1) / 100; - } - return Damage; -} - - - -bool IsAggressiveSpell(int SpellNr) - -{ - bool bVar1; - - if (SpellNr - 1U < 0xff) { - bVar1 = (bool)((byte)SpellList[SpellNr].Flags & 1); - } - else { - error(&DAT_080fa6c0,SpellNr); - bVar1 = false; - } - return bVar1; -} - - - -// DWARF original prototype: void TDamageImpact(TDamageImpact * this, TCreature * _Actor, int -// _DamageType, int _Power, bool _AllowDefense) - -void __thiscall -TDamageImpact::TDamageImpact - (TDamageImpact *this,TCreature *_Actor,int _DamageType,int _Power,bool _AllowDefense) - -{ - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b48; - if (_Actor == (TCreature *)0x0) { - error("TDamageImpact::TDamageImpact: Actor ist NULL.\n"); - } - this->Actor = _Actor; - this->DamageType = _DamageType; - this->AllowDefense = _AllowDefense; - this->Power = _Power; - return; -} - - - -// DWARF original prototype: void TDamageImpact(TDamageImpact * this, TCreature * _Actor, int -// _DamageType, int _Power, bool _AllowDefense) - -void __thiscall -TDamageImpact::TDamageImpact - (TDamageImpact *this,TCreature *_Actor,int _DamageType,int _Power,bool _AllowDefense) - -{ - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b48; - if (_Actor == (TCreature *)0x0) { - error("TDamageImpact::TDamageImpact: Actor ist NULL.\n"); - } - this->Actor = _Actor; - this->DamageType = _DamageType; - this->AllowDefense = _AllowDefense; - this->Power = _Power; - return; -} - - - -// DWARF original prototype: void handleCreature(TDamageImpact * this, TCreature * Victim) - -void __thiscall TDamageImpact::handleCreature(TDamageImpact *this,TCreature *Victim) - -{ - TCreature *pTVar1; - short sVar2; - int iVar3; - int Help; - int Damage; - - if (Victim != (TCreature *)0x0) { - pTVar1 = this->Actor; - if (((pTVar1 != (TCreature *)0x0) && (Victim != pTVar1)) && - ((WorldType != NON_PVP || - ((iVar3 = (*pTVar1->_vptr_TCreature[4])(pTVar1), (char)iVar3 == '\0' || - (iVar3 = (*Victim->_vptr_TCreature[4])(Victim), (char)iVar3 == '\0')))))) { - iVar3 = this->DamageType; - Damage = this->Power; - if ((iVar3 == 1) && (this->AllowDefense != false)) { - sVar2 = TCombat::GetDefendDamage(&Victim->Combat); - Damage = Damage - sVar2; - iVar3 = this->DamageType; - } - TCreature::Damage(Victim,this->Actor,Damage,iVar3); - } - return; - } - error("TDamageImpact::handleCreature: Opfer existiert nicht.\n"); - return; -} - - - -// DWARF original prototype: void TFieldImpact(TFieldImpact * this, TCreature * _Actor, int -// _FieldType) - -void __thiscall TFieldImpact::TFieldImpact(TFieldImpact *this,TCreature *_Actor,int _FieldType) - -{ - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b30; - if (_Actor == (TCreature *)0x0) { - error("TFieldImpact::TFieldImpact: Actor ist NULL.\n"); - } - this->Actor = _Actor; - this->FieldType = _FieldType; - return; -} - - - -// DWARF original prototype: void TFieldImpact(TFieldImpact * this, TCreature * _Actor, int -// _FieldType) - -void __thiscall TFieldImpact::TFieldImpact(TFieldImpact *this,TCreature *_Actor,int _FieldType) - -{ - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b30; - if (_Actor == (TCreature *)0x0) { - error("TFieldImpact::TFieldImpact: Actor ist NULL.\n"); - } - this->Actor = _Actor; - this->FieldType = _FieldType; - return; -} - - - -// DWARF original prototype: void handleField(TFieldImpact * this, int x, int y, int z) - -void __thiscall TFieldImpact::handleField(TFieldImpact *this) - -{ - int iVar1; - TCreature *pTVar2; - bool Peaceful; - int in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000010; - - pTVar2 = this->Actor; - if (pTVar2 != (TCreature *)0x0) { - Peaceful = false; - if (WorldType == NON_PVP) { - iVar1 = (*pTVar2->_vptr_TCreature[4])(pTVar2); - pTVar2 = this->Actor; - Peaceful = (char)iVar1 != '\0'; - } - // try { // try from 0807f0bf to 0807f0d8 has its CatchHandler @ 0807f0e3 - CreateField(in_stack_00000008,in_stack_0000000c,in_stack_00000010,this->FieldType,pTVar2->ID - ,Peaceful); - } - return; -} - - - -// DWARF original prototype: void THealingImpact(THealingImpact * this, TCreature * _Actor, int -// _Power) - -void __thiscall THealingImpact::THealingImpact(THealingImpact *this,TCreature *_Actor,int _Power) - -{ - char *pcVar1; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b18; - if (_Actor == (TCreature *)0x0) { - error("THealingImpact::THealingImpact: Actor ist NULL.\n"); - } - if (_Power < 0) { - pcVar1 = "(unknown)"; - if (_Actor != (TCreature *)0x0) { - pcVar1 = _Actor->Name; - } - error("THealingImpact::THealingImpact: Power ist negativ (Actor: %s).\n",pcVar1); - } - this->Actor = _Actor; - this->Power = _Power; - return; -} - - - -// DWARF original prototype: void THealingImpact(THealingImpact * this, TCreature * _Actor, int -// _Power) - -void __thiscall THealingImpact::THealingImpact(THealingImpact *this,TCreature *_Actor,int _Power) - -{ - char *pcVar1; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b18; - if (_Actor == (TCreature *)0x0) { - error("THealingImpact::THealingImpact: Actor ist NULL.\n"); - } - if (_Power < 0) { - pcVar1 = "(unknown)"; - if (_Actor != (TCreature *)0x0) { - pcVar1 = _Actor->Name; - } - error("THealingImpact::THealingImpact: Power ist negativ (Actor: %s).\n",pcVar1); - } - this->Actor = _Actor; - this->Power = _Power; - return; -} - - - -// DWARF original prototype: void handleCreature(THealingImpact * this, TCreature * Victim) - -void __thiscall THealingImpact::handleCreature(THealingImpact *this,TCreature *Victim) - -{ - int iVar1; - - if (Victim != (TCreature *)0x0) { - if ((this->Actor != (TCreature *)0x0) && (-1 < this->Power)) { - iVar1 = TSkill::Get((Victim->super_TSkillBase).Skills[2]); - if (0 < iVar1) { - TSkill::Change((Victim->super_TSkillBase).Skills[2],this->Power); - if ((Victim->super_TSkillBase).Skills[4]->MDAct < 0) { - TSkillBase::SetTimer(&Victim->super_TSkillBase); - } - } - } - return; - } - error("THealingImpact::handleCreature: Opfer existiert nicht.\n"); - return; -} - - - -// DWARF original prototype: void TSpeedImpact(TSpeedImpact * this, TCreature * _Actor, int -// _Percent, int _Duration) - -void __thiscall TSpeedImpact::TSpeedImpact(TSpeedImpact *this) - -{ - TCreature *in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000010; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b00; - if (in_stack_00000008 == (TCreature *)0x0) { - error("TSpeedImpact::TSpeedImpact: Actor ist NULL.\n"); - } - this->Actor = in_stack_00000008; - this->Percent = in_stack_0000000c; - this->Duration = in_stack_00000010; - return; -} - - - -// DWARF original prototype: void TSpeedImpact(TSpeedImpact * this, TCreature * _Actor, int -// _Percent, int _Duration) - -void __thiscall TSpeedImpact::TSpeedImpact(TSpeedImpact *this) - -{ - TCreature *in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000010; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b00; - if (in_stack_00000008 == (TCreature *)0x0) { - error("TSpeedImpact::TSpeedImpact: Actor ist NULL.\n"); - } - this->Actor = in_stack_00000008; - this->Percent = in_stack_0000000c; - this->Duration = in_stack_00000010; - return; -} - - - -// DWARF original prototype: void handleCreature(TSpeedImpact * this, TCreature * Victim) - -void __thiscall TSpeedImpact::handleCreature(TSpeedImpact *this,TCreature *Victim) - -{ - TCreature *pTVar1; - TSkill *this_00; - bool bVar2; - TSkill *sk; - int Modification; - int iVar3; - - if (Victim == (TCreature *)0x0) { - error("TSpeedImpact::handleCreature: Opfer existiert nicht.\n"); - return; - } - pTVar1 = this->Actor; - if (pTVar1 != (TCreature *)0x0) { - iVar3 = this->Percent; - if (iVar3 < 0) { - if (pTVar1 == Victim) { - return; - } - if (WorldType == NON_PVP) { - iVar3 = (*pTVar1->_vptr_TCreature[4])(pTVar1); - if (((char)iVar3 != '\0') && - (iVar3 = (*Victim->_vptr_TCreature[4])(Victim), (char)iVar3 != '\0')) { - return; - } - iVar3 = this->Percent; - } - if (iVar3 < 0) { - bVar2 = GetRaceNoParalyze(Victim->Race); - if (bVar2) { - return; - } - iVar3 = this->Percent; - if ((iVar3 < 0) && (Victim->Type == PLAYER)) { - bVar2 = CheckRight(Victim->ID,INVULNERABLE); - if (bVar2) { - return; - } - iVar3 = this->Percent; - } - } - } - this_00 = (Victim->super_TSkillBase).Skills[4]; - if (iVar3 < -100) { - iVar3 = -0x14 - this_00->Act; - } - else { - iVar3 = (iVar3 * this_00->Act) / 100; - } - TSkill::SetMDAct(this_00,iVar3); - TSkillBase::SetTimer(&Victim->super_TSkillBase); - } - return; -} - - - -// DWARF original prototype: void TDrunkenImpact(TDrunkenImpact * this, TCreature * _Actor, int -// _Power, int _Duration) - -void __thiscall -TDrunkenImpact::TDrunkenImpact(TDrunkenImpact *this,TCreature *_Actor,int _Power,int _Duration) - -{ - int iVar1; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127ae8; - if (_Actor == (TCreature *)0x0) { - error("TDrunkenImpact::TDrunkenImpact: Actor ist NULL.\n"); - } - iVar1 = _Power; - if (6 < _Power) { - iVar1 = 6; - error(&DAT_080fa900,_Power); - } - this->Actor = _Actor; - this->Power = iVar1; - this->Duration = _Duration; - return; -} - - - -// DWARF original prototype: void TDrunkenImpact(TDrunkenImpact * this, TCreature * _Actor, int -// _Power, int _Duration) - -void __thiscall -TDrunkenImpact::TDrunkenImpact(TDrunkenImpact *this,TCreature *_Actor,int _Power,int _Duration) - -{ - int iVar1; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127ae8; - if (_Actor == (TCreature *)0x0) { - error("TDrunkenImpact::TDrunkenImpact: Actor ist NULL.\n"); - } - iVar1 = _Power; - if (6 < _Power) { - iVar1 = 6; - error(&DAT_080fa900,_Power); - } - this->Actor = _Actor; - this->Power = iVar1; - this->Duration = _Duration; - return; -} - - - -// DWARF original prototype: void handleCreature(TDrunkenImpact * this, TCreature * Victim) - -void __thiscall TDrunkenImpact::handleCreature(TDrunkenImpact *this,TCreature *Victim) - -{ - TCreature *pTVar1; - TSkill *pTVar2; - bool bVar3; - int iVar4; - - if (Victim != (TCreature *)0x0) { - pTVar1 = this->Actor; - if (((((pTVar1 != (TCreature *)0x0) && (pTVar1 != Victim)) && - ((WorldType != NON_PVP || - ((iVar4 = (*pTVar1->_vptr_TCreature[4])(pTVar1), (char)iVar4 == '\0' || - (iVar4 = (*Victim->_vptr_TCreature[4])(Victim), (char)iVar4 == '\0')))))) && - (bVar3 = GetRaceNoParalyze(Victim->Race), !bVar3)) && - (((Victim->Type != PLAYER || (bVar3 = CheckRight(Victim->ID,INVULNERABLE), !bVar3)) && - (pTVar2 = (Victim->super_TSkillBase).Skills[0x14], - iVar4 = (*pTVar2->_vptr_TSkill[0xd])(pTVar2), iVar4 <= this->Power)))) { - TSkillBase::SetTimer(&Victim->super_TSkillBase); - } - return; - } - error("TDrunkenImpact::handleCreature: Opfer existiert nicht.\n"); - return; -} - - - -// DWARF original prototype: void TStrengthImpact(TStrengthImpact * this, TCreature * _Actor, int -// _Skills, int _Percent, int _Duration) - -void __thiscall TStrengthImpact::TStrengthImpact(TStrengthImpact *this) - -{ - TCreature *in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000010; - int in_stack_00000014; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127ad0; - if (in_stack_00000008 == (TCreature *)0x0) { - error("TStrengthImpact::TStrengthImpact: Actor ist NULL.\n"); - } - this->Actor = in_stack_00000008; - this->Skills = in_stack_0000000c; - this->Percent = in_stack_00000010; - this->Duration = in_stack_00000014; - return; -} - - - -// DWARF original prototype: void TStrengthImpact(TStrengthImpact * this, TCreature * _Actor, int -// _Skills, int _Percent, int _Duration) - -void __thiscall TStrengthImpact::TStrengthImpact(TStrengthImpact *this) - -{ - TCreature *in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000010; - int in_stack_00000014; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127ad0; - if (in_stack_00000008 == (TCreature *)0x0) { - error("TStrengthImpact::TStrengthImpact: Actor ist NULL.\n"); - } - this->Actor = in_stack_00000008; - this->Skills = in_stack_0000000c; - this->Percent = in_stack_00000010; - this->Duration = in_stack_00000014; - return; -} - - - -// DWARF original prototype: void handleCreature(TStrengthImpact * this, TCreature * Victim) - -void __thiscall TStrengthImpact::handleCreature(TStrengthImpact *this,TCreature *Victim) - -{ - TCreature *pTVar1; - uint uVar2; - TSkill *this_00; - bool bVar3; - TSkill *sk; - int Modification; - int value; - int Skill; - int iVar4; - - if (Victim == (TCreature *)0x0) { - error("TStrengthImpact::handleCreature: Opfer existiert nicht.\n"); - return; - } - pTVar1 = this->Actor; - if (pTVar1 == (TCreature *)0x0) { - return; - } - iVar4 = this->Percent; - if (iVar4 < 0) { - if (pTVar1 == Victim) { - return; - } - if (WorldType == NON_PVP) { - iVar4 = (*pTVar1->_vptr_TCreature[4])(pTVar1); - if (((char)iVar4 != '\0') && - (iVar4 = (*Victim->_vptr_TCreature[4])(Victim), (char)iVar4 != '\0')) { - return; - } - iVar4 = this->Percent; - } - if (iVar4 < 0) { - bVar3 = GetRaceNoParalyze(Victim->Race); - if (bVar3) { - return; - } - if (((this->Percent < 0) && (Victim->Type == PLAYER)) && - (bVar3 = CheckRight(Victim->ID,INVULNERABLE), bVar3)) { - return; - } - } - } - iVar4 = 6; - do { - uVar2 = this->Skills; - if ((uVar2 & 1) == 0) { - bVar3 = false; - if ((7 < iVar4) && (iVar4 < 0xc)) { - bVar3 = true; - } - if (!bVar3) goto LAB_0807f750; - } - else { -LAB_0807f750: - if ((((uVar2 & 2) != 0) || (iVar4 != 7)) && (((uVar2 & 4) != 0 || (iVar4 != 6)))) { - this_00 = (Victim->super_TSkillBase).Skills[iVar4]; - if (this->Percent < -100) { - value = -0x14 - this_00->Act; - } - else { - value = (this->Percent * this_00->Act) / 100; - } - TSkill::SetMDAct(this_00,value); - TSkillBase::SetTimer(&Victim->super_TSkillBase); - } - } - iVar4 = iVar4 + 1; - if (0xb < iVar4) { - return; - } - } while( true ); -} - - - -// DWARF original prototype: void TOutfitImpact(TOutfitImpact * this, TCreature * _Actor, TOutfit -// _Outfit, int _Duration) - -void __thiscall -TOutfitImpact::TOutfitImpact(TOutfitImpact *this,TCreature *_Actor,TOutfit _Outfit,int _Duration) - -{ - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127ab8; - if (_Actor == (TCreature *)0x0) { - error("TOutfitImpact::TOutfitImpact: Actor ist NULL.\n"); - } - (this->Outfit).field_1 = _Outfit.field_1; - (this->Outfit).OutfitID = _Outfit.OutfitID; - this->Actor = _Actor; - this->Duration = _Duration; - return; -} - - - -// DWARF original prototype: void TOutfitImpact(TOutfitImpact * this, TCreature * _Actor, TOutfit -// _Outfit, int _Duration) - -void __thiscall -TOutfitImpact::TOutfitImpact(TOutfitImpact *this,TCreature *_Actor,TOutfit _Outfit,int _Duration) - -{ - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127ab8; - if (_Actor == (TCreature *)0x0) { - error("TOutfitImpact::TOutfitImpact: Actor ist NULL.\n"); - } - (this->Outfit).field_1 = _Outfit.field_1; - (this->Outfit).OutfitID = _Outfit.OutfitID; - this->Actor = _Actor; - this->Duration = _Duration; - return; -} - - - -// DWARF original prototype: void handleCreature(TOutfitImpact * this, TCreature * Victim) - -void __thiscall TOutfitImpact::handleCreature(TOutfitImpact *this,TCreature *Victim) - -{ - anon_union_4_2_730cd3ca_for_TOutfit_2 aVar1; - - if (Victim != (TCreature *)0x0) { - aVar1 = (this->Outfit).field_1; - (Victim->Outfit).OutfitID = (this->Outfit).OutfitID; - (Victim->Outfit).field_1 = aVar1; - TSkillBase::SetTimer(&Victim->super_TSkillBase); - return; - } - error("TOutfitImpact::handleCreature: Opfer existiert nicht.\n"); - return; -} - - - -// DWARF original prototype: void TSummonImpact(TSummonImpact * this, TCreature * _Actor, int _Race, -// int _Maximum) - -void __thiscall -TSummonImpact::TSummonImpact(TSummonImpact *this,TCreature *_Actor,int _Race,int _Maximum) - -{ - bool bVar1; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127aa0; - if (_Actor == (TCreature *)0x0) { - error("TSummonImpact::TSummonImpact: Actor ist NULL.\n"); - } - bVar1 = false; - if ((0 < _Race) && (_Race < 0x200)) { - bVar1 = true; - } - if (!bVar1) { - error(&DAT_080faac0,_Race); - } - this->Actor = _Actor; - this->Race = _Race; - this->Maximum = _Maximum; - return; -} - - - -// DWARF original prototype: void TSummonImpact(TSummonImpact * this, TCreature * _Actor, int _Race, -// int _Maximum) - -void __thiscall -TSummonImpact::TSummonImpact(TSummonImpact *this,TCreature *_Actor,int _Race,int _Maximum) - -{ - bool bVar1; - - (this->super_TImpact)._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127aa0; - if (_Actor == (TCreature *)0x0) { - error("TSummonImpact::TSummonImpact: Actor ist NULL.\n"); - } - bVar1 = false; - if ((0 < _Race) && (_Race < 0x200)) { - bVar1 = true; - } - if (!bVar1) { - error(&DAT_080faac0,_Race); - } - this->Actor = _Actor; - this->Race = _Race; - this->Maximum = _Maximum; - return; -} - - - -// DWARF original prototype: void handleField(TSummonImpact * this, int x, int y, int z) - -void __thiscall TSummonImpact::handleField(TSummonImpact *this,int x,int y,int z) - -{ - bool bVar1; - - if (this->Actor != (TCreature *)0x0) { - bVar1 = false; - if ((0 < this->Race) && (this->Race < 0x200)) { - bVar1 = true; - } - if ((bVar1) && (this->Actor->SummonedCreatures < this->Maximum)) { - bVar1 = SearchSummonField(&x,&y,&z,2); - if (bVar1) { - CreateMonster(this->Race,x,y,z,0,this->Actor->ID,true); - } - } - } - return; -} - - - -void ActorShapeSpell(TCreature *Actor,TImpact *Impact,int Effect) - -{ - bool bVar1; - int iVar2; - - if (Actor == (TCreature *)0x0) { - error("ActorShapeSpell: Sprecher existiert nicht.\n"); - return; - } - iVar2 = (*Impact->_vptr_TImpact[2])(Impact); - if (((char)iVar2 != '\0') && (bVar1 = IsProtectionZone(), bVar1)) { - return; - } - (*Impact->_vptr_TImpact[1])(Impact,Actor); - if (Effect != 0) { - GraphicalEffect(); - } - return; -} - - - -void VictimShapeSpell(TCreature *Actor,TCreature *Victim,int Range,int Animation,TImpact *Impact, - int Effect) - -{ - bool bVar1; - int iVar2; - int *piVar3; - int local_44; - int local_40; - Object local_3c [4]; - Object local_2c [7]; - - if (Actor == (TCreature *)0x0) { - error("VictimShapeSpell: Sprecher existiert nicht.\n"); - } - else if ((Victim != (TCreature *)0x0) && (Actor->posz == Victim->posz)) { - iVar2 = Actor->posx - Victim->posx; - local_40 = -iVar2; - if (-1 < iVar2) { - local_40 = iVar2; - } - iVar2 = Actor->posy - Victim->posy; - local_44 = -iVar2; - if (-1 < iVar2) { - local_44 = iVar2; - } - piVar3 = &local_44; - if (local_44 <= local_40) { - piVar3 = &local_40; - } - if ((*piVar3 <= Range) && - (((iVar2 = (*Impact->_vptr_TImpact[2])(Impact), (char)iVar2 == '\0' || - (bVar1 = IsProtectionZone(), !bVar1)) && - (bVar1 = ThrowPossible(Actor->posx,Actor->posy,Actor->posz,Victim->posx,Victim->posy, - Victim->posz,0), bVar1)))) { - if ((Animation != 0) && ((Actor->posx != Victim->posx || (Actor->posy != Victim->posy))) - ) { - local_2c[0].ObjectID = (Victim->CrObject).ObjectID; - local_3c[0].ObjectID = (Actor->CrObject).ObjectID; - Missile(local_3c,local_2c,Animation); - } - (*Impact->_vptr_TImpact[1])(Impact,Victim); - if (Effect != 0) { - GraphicalEffect(); - } - } - } - return; -} - - - -void OriginShapeSpell(TCreature *Actor,int Radius,TImpact *Impact,int Effect) - -{ - bool bVar1; - int iVar2; - int zy; - int iVar3; - TCreature *pTVar4; - TCreature *dest; - int zx; - int z; - int local_78; - int *local_74; - int y; - int x; - int local_64; - int j; - int i; - ulong local_4c; - Object Help; - ulong local_2c; - Object Obj; - - if (Actor == (TCreature *)0x0) { - error(&DAT_080fabc0); - } - else { - j = 0; - if (-1 < Radius) { - local_74 = &Circle[0].Count; - local_78 = 0; - do { - local_64 = 0; - iVar2 = local_78; - if (0 < *local_74) { - do { - zx = Circle[0].x[iVar2 + local_64] + Actor->posx; - zy = Circle[0].y[iVar2 + local_64] + Actor->posy; - iVar2 = Actor->posz; - bVar1 = ThrowPossible(Actor->posx,Actor->posy,iVar2,zx,zy,iVar2,0); - if ((bVar1) && - ((iVar3 = (*Impact->_vptr_TImpact[2])(Impact), (char)iVar3 == '\0' || - (bVar1 = IsProtectionZone(), !bVar1)))) { - (**Impact->_vptr_TImpact)(Impact,zx,zy,iVar2); - GetFirstObject(); - if (local_2c != NONE.ObjectID) { - do { - local_4c = local_2c; - Object::getNextObject((Object *)&i); - iVar2 = i; - local_2c = i; - Object::getObjectType((Object *)&i); - if (i == 99) { - i = local_4c; - pTVar4 = GetCreature((Object *)&i); - if (pTVar4 != (TCreature *)0x0) { - (*Impact->_vptr_TImpact[1])(Impact,pTVar4); - } - } - } while (iVar2 != NONE.ObjectID); - } - local_4c = NONE.ObjectID; - if (Effect != 0) { - GraphicalEffect(); - } - } - local_64 = local_64 + 1; - iVar2 = j * 0x41; - } while (local_64 < *local_74); - } - j = j + 1; - local_74 = local_74 + 0x41; - local_78 = local_78 + 0x41; - } while (j <= Radius); - } - } - return; -} - - - -// WARNING: Variable defined which should be unmapped: Actor_local - -void DestinationShapeSpell - (TCreature *Actor,TCreature *Victim,int Range,int Animation,int Radius, - TImpact *Impact,int Effect) - -{ - TCreature *Actor_local; - - if (Actor != (TCreature *)0x0) { - if (Victim != (TCreature *)0x0) { - CircleShapeSpell(Actor,Victim->posx,Victim->posy,Victim->posz,Range,Animation,Radius, - Impact,Effect); - } - return; - } - error("DestinationShapeSpell: Sprecher existiert nicht.\n"); - return; -} - - - -void CircleShapeSpell(TCreature *Actor,int DestX,int DestY,int DestZ,int Range,int Animation, - int Radius,TImpact *Impact,int Effect) - -{ - bool bVar1; - int iVar2; - TCreature *pTVar3; - int *piVar4; - TCreature *dest; - int zx; - int y; - int iVar5; - int local_80; - int *local_7c; - int x; - int local_70; - int j; - int i; - int local_64; - int local_60; - Object local_5c [4]; - ulong local_4c; - Object Help; - Object local_3c; - Object Obj; - Object local_2c [7]; - - if (Actor == (TCreature *)0x0) { - error("CircleShapeSpell: Sprecher existiert nicht.\n"); - } - else if (Actor->posz == DestZ) { - iVar5 = Actor->posx - DestX; - local_60 = -iVar5; - if (-1 < iVar5) { - local_60 = iVar5; - } - iVar5 = Actor->posy - DestY; - local_64 = -iVar5; - if (-1 < iVar5) { - local_64 = iVar5; - } - piVar4 = &local_64; - if (local_64 <= local_60) { - piVar4 = &local_60; - } - if ((*piVar4 <= Range) && - (bVar1 = ThrowPossible(Actor->posx,Actor->posy,DestZ,DestX,DestY,DestZ,0), bVar1)) { - if ((Animation != 0) && ((Actor->posx != DestX || (Actor->posy != DestY)))) { - local_2c[0].ObjectID = (Actor->CrObject).ObjectID; - GetMapContainer((int)&local_3c,DestX,DestY); - Missile(local_2c,&local_3c,Animation); - } - j = 0; - if (-1 < Radius) { - local_7c = &Circle[0].Count; - local_80 = 0; - do { - local_70 = 0; - iVar5 = local_80; - if (0 < *local_7c) { - do { - zx = DestX + Circle[0].x[iVar5 + local_70]; - iVar5 = DestY + Circle[0].y[iVar5 + local_70]; - bVar1 = ThrowPossible(DestX,DestY,DestZ,zx,iVar5,DestZ,0); - if ((bVar1) && - ((iVar2 = (*Impact->_vptr_TImpact[2])(Impact), (char)iVar2 == '\0' || - (bVar1 = IsProtectionZone(), !bVar1)))) { - (**Impact->_vptr_TImpact)(Impact,zx,iVar5,DestZ); - GetFirstObject(); - if (local_3c.ObjectID != NONE.ObjectID) { - do { - local_4c = local_3c.ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - Object::getNextObject(local_5c); - local_3c.ObjectID = local_5c[0].ObjectID; - local_2c[0].ObjectID = local_5c[0].ObjectID; - Object::getObjectType(local_5c); - if (local_5c[0].ObjectID == 99) { - local_5c[0].ObjectID = local_4c; - pTVar3 = GetCreature(local_5c); - if (pTVar3 != (TCreature *)0x0) { - (*Impact->_vptr_TImpact[1])(Impact,pTVar3); - } - } - } while (local_3c.ObjectID != NONE.ObjectID); - } - local_4c = NONE.ObjectID; - local_2c[0].ObjectID = NONE.ObjectID; - if (Effect != 0) { - GraphicalEffect(); - } - } - local_70 = local_70 + 1; - iVar5 = j * 0x41; - } while (local_70 < *local_7c); - } - j = j + 1; - local_7c = local_7c + 0x41; - local_80 = local_80 + 0x41; - } while (j <= Radius); - } - } - } - return; -} - - - -void AngleShapeSpell(TCreature *Actor,int Angle,int Range,TImpact *Impact,int Effect) - -{ - int sy; - int sz; - bool bVar1; - int iVar2; - TCreature *pTVar3; - TCreature *dest; - int y; - int iVar4; - int x; - int iVar5; - int j; - int iVar6; - int local_78; - int local_74; - int z; - int local_60; - int i; - ulong local_4c; - Object Help; - ulong local_2c; - Object Obj; - - if (Actor == (TCreature *)0x0) { - error(&DAT_080facc0); - } - else { - local_60 = 1; - if (0 < Range) { - local_78 = -Angle; - local_74 = Angle; - do { - iVar6 = local_78 / 0x5a; - if (iVar6 <= local_74 / 0x5a) { - do { - iVar2 = Actor->posx; - sy = Actor->posy; - sz = Actor->posz; - iVar4 = Actor->Direction; - iVar5 = local_60; - if (iVar4 == 1) { -LAB_080804bf: - iVar5 = iVar2 + iVar5; - iVar4 = sy + iVar6; - } - else if (iVar4 < 2) { - if (iVar4 != 0) { -LAB_08080658: - error(&DAT_080fac80,iVar4); - return; - } - iVar5 = iVar2 + iVar6; - iVar4 = sy - local_60; - } - else { - if (iVar4 != 2) { - if (iVar4 != 3) goto LAB_08080658; - iVar5 = -local_60; - goto LAB_080804bf; - } - iVar5 = iVar2 + iVar6; - iVar4 = sy + local_60; - } - bVar1 = ThrowPossible(iVar2,sy,sz,iVar5,iVar4,sz,0); - if ((bVar1) && - ((iVar2 = (*Impact->_vptr_TImpact[2])(Impact), (char)iVar2 == '\0' || - (bVar1 = IsProtectionZone(), !bVar1)))) { - (**Impact->_vptr_TImpact)(Impact,iVar5,iVar4,sz); - GetFirstObject(); - if (local_2c != NONE.ObjectID) { - do { - local_4c = local_2c; - Object::getNextObject((Object *)&i); - iVar2 = i; - local_2c = i; - Object::getObjectType((Object *)&i); - if (i == 99) { - i = local_4c; - pTVar3 = GetCreature((Object *)&i); - if (pTVar3 != (TCreature *)0x0) { - (*Impact->_vptr_TImpact[1])(Impact,pTVar3); - } - } - } while (iVar2 != NONE.ObjectID); - } - local_4c = NONE.ObjectID; - if (Effect != 0) { - GraphicalEffect(); - } - } - iVar6 = iVar6 + 1; - } while (iVar6 <= local_74 / 0x5a); - } - local_60 = local_60 + 1; - local_74 = local_74 + Angle; - local_78 = local_78 - Angle; - } while (local_60 <= Range); - } - } - return; -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void MassCombat(void) - -{ - bool bVar1; - undefined4 *puVar2; - int Delay; - TCreature *in_stack_00000004; - Object *in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000010; - int in_stack_00000018; - int in_stack_0000001c; - ushort in_stack_00000020; - int in_stack_00000024; - char *Text; - int local_58; - int x; - int y; - int z; - TDamageImpact Impact; - Object local_2c [7]; - - // try { // try from 080806cf to 08080835 has its CatchHandler @ 08080853 - bVar1 = Object::exists(in_stack_00000008); - if (bVar1) { - if (in_stack_00000004 != (TCreature *)0x0) { - local_2c[0].ObjectID = in_stack_00000008->ObjectID; - GetObjectCoordinates(local_2c,&local_58,&x,&y); - CheckAffectedPlayers(); - bVar1 = ThrowPossible(in_stack_00000004->posx,in_stack_00000004->posy, - in_stack_00000004->posz,local_58,x,y,0); - if (bVar1) { - Delay = 1000; - if (WorldType != PVP_ENFORCED) { - Delay = 2000; - } - CheckMana(in_stack_00000004,in_stack_0000000c,in_stack_00000010,Delay); - z = (int)&PTR_handleField_08127b48; - Impact.Power._0_1_ = 0; - Impact.Actor = (TCreature *)(uint)in_stack_00000020; - CircleShapeSpell(in_stack_00000004,local_58,x,y,0x7fffffff,in_stack_00000024, - in_stack_0000001c,(TImpact *)&z,in_stack_00000018); - return; - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 7; - goto LAB_08080812; - } - Text = &DAT_080fad00; - } - else { - Text = &DAT_080fad40; - } - error(Text); - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; -LAB_08080812: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - -// WARNING: Unknown calling convention -- yet parameter storage is locked - -void AngleCombat(void) - -{ - int Delay; - undefined4 *puVar1; - TCreature *in_stack_00000004; - int in_stack_00000008; - int in_stack_0000000c; - int in_stack_00000014; - int in_stack_00000018; - int in_stack_0000001c; - ushort in_stack_00000020; - TImpact local_3c; - TDamageImpact Impact; - - if (in_stack_00000004 != (TCreature *)0x0) { - if (((in_stack_00000018 == 1) && (in_stack_0000001c == 0)) || (WorldType == PVP_ENFORCED)) { - Delay = 1000; - } - else { - Delay = 2000; - } - // try { // try from 080808bb to 08080971 has its CatchHandler @ 08080972 - CheckMana(in_stack_00000004,in_stack_00000008,in_stack_0000000c,Delay); - local_3c._vptr_TImpact = (_func_int_varargs **)&PTR_handleField_08127b48; - if (in_stack_00000004 == (TCreature *)0x0) { - error("TDamageImpact::TDamageImpact: Actor ist NULL.\n"); - } - Impact.Power._0_1_ = 0; - Impact.Actor = (TCreature *)(uint)in_stack_00000020; - AngleShapeSpell(in_stack_00000004,in_stack_0000001c,in_stack_00000018,&local_3c, - in_stack_00000014); - return; - } - error(&DAT_080fad80); - puVar1 = (undefined4 *)__cxa_allocate_exception(4); - *puVar1 = 0xffffffff; - // WARNING: Subroutine does not return - __cxa_throw(puVar1,&RESULT::typeinfo,0); -} - - - -void Combat(TCreature *cr,Object *Target,int Mana,int SoulPoints,int Damage,int EffectNr, - int AnimationNr,ushort DmgType) - -{ - bool bVar1; - undefined4 *puVar2; - int Delay; - char *Text; - Object *pOVar3; - int *y_00; - int *z_00; - ushort DmgType_local; - int x; - int y; - int z; - TDamageImpact Impact; - ObjectType local_4c [4]; - ulong local_3c; - Object local_2c [7]; - - // try { // try from 080809b2 to 08080ba2 has its CatchHandler @ 08080bc3 - bVar1 = Object::exists(Target); - if (bVar1) { - if (cr != (TCreature *)0x0) { - local_2c[0] = (Object)Target->ObjectID; - z_00 = &y; - y_00 = &x; - GetObjectCoordinates(local_2c,(int *)&DmgType_local,y_00,z_00); - pOVar3 = Target; - Object::getObjectType(local_2c); - if (local_2c[0].ObjectID != 99) { - ObjectType::setTypeID(local_4c,99); - pOVar3 = _DmgType_local; - y_00 = (int *)x; - z_00 = (int *)y; - GetFirstSpecObject(); - local_2c[0].ObjectID = local_3c; - Target->ObjectID = local_3c; - } - local_4c[0].TypeID = NONE.ObjectID; - if (Target->ObjectID == NONE.ObjectID) { - puVar2 = (undefined4 *)__cxa_allocate_exception(4,pOVar3,y_00,z_00); - *puVar2 = 0x27; - } - else { - CheckAffectedPlayers(); - bVar1 = ThrowPossible(cr->posx,cr->posy,cr->posz,(int)_DmgType_local,x,y,0); - if (bVar1) { - Delay = 1000; - if (WorldType != PVP_ENFORCED) { - Delay = 2000; - } - CheckMana(cr,Mana,SoulPoints,Delay); - z = (int)&PTR_handleField_08127b48; - Impact.super_TImpact._vptr_TImpact = (_func_int_varargs **)cr; - Impact.Power._0_1_ = 0; - Impact.DamageType = Damage; - Impact.Actor = (TCreature *)(uint)DmgType; - CircleShapeSpell(cr,(int)_DmgType_local,x,y,0x7fffffff,AnimationNr,0, - (TImpact *)&z,EffectNr); - return; - } - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 7; - } - goto LAB_08080b22; - } - Text = &DAT_080fadc0; - } - else { - Text = &DAT_080fae00; - } - error(Text); - puVar2 = (undefined4 *)__cxa_allocate_exception(4); - *puVar2 = 0xffffffff; -LAB_08080b22: - // WARNING: Subroutine does not return - __cxa_throw(puVar2,&RESULT::typeinfo,0); -} - - - void KillAllMonsters(TCreature *cr,int EffectNr,int Radius) { @@ -28418,46 +26812,6 @@ void _GLOBAL__I_SpellSyllable(void) -// DWARF original prototype: void handleField(TImpact * this, int param_1, int param_2, int param_3) - -void __thiscall TImpact::handleField(TImpact *this,int param_1,int param_2,int param_3) - -{ - return; -} - - - -// DWARF original prototype: void handleCreature(TImpact * this, TCreature * param_1) - -void __thiscall TImpact::handleCreature(TImpact *this,TCreature *param_1) - -{ - return; -} - - - -// DWARF original prototype: bool isAggressive(TImpact * this) - -bool __thiscall TImpact::isAggressive(TImpact *this) - -{ - return true; -} - - - -// DWARF original prototype: bool isAggressive(THealingImpact * this) - -bool __thiscall THealingImpact::isAggressive(THealingImpact *this) - -{ - return false; -} - - - // DWARF original prototype: void // ~basic_stringbuf(basic_stringbuf,std::allocator_> * this, int // __in_chrg) diff --git a/src/creature.cc b/src/creature.cc index 4fee0b3..65beee0 100644 --- a/src/creature.cc +++ b/src/creature.cc @@ -58,13 +58,13 @@ void TCreature::Attack(void){ // TODO(fusion): This probably belongs elsewhere but we should come back to // this when we're wrapping up creature files. -static bool IsCreaturePlayer(uint32 CreatureID){ +bool IsCreaturePlayer(uint32 CreatureID){ return CreatureID < 0x40000000; } // TODO(fusion): This probably belongs elsewhere but we should come back to // this when we're wrapping up creature files. -static void AddKillStatistics(int AttackerRace, int DefenderRace){ +void AddKillStatistics(int AttackerRace, int DefenderRace){ // NOTE(fusion): I think the race name can be "human" only for players, // which means we're probably tracking how many creatures are killed by // players with `KilledCreatures`, and how many players are killed by diff --git a/src/creature.hh b/src/creature.hh index d5f4f1b..79fee7c 100644 --- a/src/creature.hh +++ b/src/creature.hh @@ -144,4 +144,9 @@ struct TCreature: TSkillBase { TConnection *Connection; }; +// TODO(fusion): These probably belong elsewhere but we should come back to +// this when we're wrapping up creature files. +bool IsCreaturePlayer(uint32 CreatureID); +void AddKillStatistics(int AttackerRace, int DefenderRace); + #endif //TIBIA_CREATURE_HH_ diff --git a/src/enums.hh b/src/enums.hh index 6d02208..489f8a6 100644 --- a/src/enums.hh +++ b/src/enums.hh @@ -89,6 +89,19 @@ enum DamageType: int { DAMAGE_MANADRAIN = 0x0200, }; +// NOTE(fusion): Not in debug symbols. +enum Direction: int { + DIRECTION_INVALID = -1, + DIRECTION_NORTH = 0, + DIRECTION_EAST = 1, + DIRECTION_SOUTH = 2, + DIRECTION_WEST = 3, + DIRECTION_SOUTHWEST = 4, + DIRECTION_SOUTHEAST = 5, + DIRECTION_NORTHWEST = 6, + DIRECTION_NORTHEAST = 7, +}; + // TODO(fusion): Review these names. enum EffectType: int { EFFECT_NONE = 0, diff --git a/src/magic.cc b/src/magic.cc index a09e52d..85dbc11 100644 --- a/src/magic.cc +++ b/src/magic.cc @@ -64,6 +64,28 @@ static const char SpellSyllable[51][6] = { "", }; +static bool IsAggressionValid(TCreature *Actor, TCreature *Victim){ + ASSERT(Actor != NULL && Victim != NULL); + + if(Actor == Victim){ + return false; + } + + if(WorldType == NON_PVP && Actor->IsPeaceful() && Victim->IsPeaceful()){ + return false; + } + + if(GetRaceNoParalyze(Victim->Race)){ + return false; + } + + if(Victim->Type == PLAYER && CheckRight(Victim->ID, INVULNERABLE)){ + return false; + } + + return true; +} + // TImpact // ============================================================================= void TImpact::handleField(int a, int b, int c){ @@ -197,27 +219,10 @@ void TSpeedImpact::handleCreature(TCreature *Victim){ } int Percent = this->Percent; - if(Percent < 0){ - // TODO(fusion): This looks like some inlined function to check if an - // aggression is valid. - if(Actor == Victim){ - return; - } - - if(WorldType == NON_PVP && Actor->IsPeaceful() && Victim->IsPeaceful()){ - return; - } - - if(GetRaceNoParalyze(Victim->Race)){ - return; - } - - if(Victim->Type == PLAYER && CheckRight(Victim->ID, INVULNERABLE)){ - return; - } + if(Percent < 0 && !IsAggressionValid(Actor, Victim)){ + return; } - TSkill *GoStrength = Victim->Skills[SKILL_GO_STRENGTH]; if(Percent < -100){ // TODO(fusion): Not sure what's this about. @@ -253,31 +258,15 @@ void TDrunkenImpact::handleCreature(TCreature *Victim){ } TCreature *Actor = this->Actor; - if(Actor != NULL){ - // TODO(fusion): This looks like some inlined function to check if an - // aggression is valid. - if(Actor == Victim){ - return; - } - - if(WorldType == NON_PVP && Actor->IsPeaceful() && Victim->IsPeaceful()){ - return; - } - - if(GetRaceNoParalyze(Victim->Race)){ - return; - } - - if(Victim->Type == PLAYER && CheckRight(Victim->ID, INVULNERABLE)){ - return; - } + if(Actor == NULL || !IsAggressionValid(Actor, Victim)){ + return; + } - int Power = this->Power; - int Duration = this->Duration; - TSkill *Drunk = Victim->Skills[SKILL_DRUNK]; - if(Drunk->TimerValue() <= Power){ - Victim->SetTimer(SKILL_DRUNK, Power, Duration, Duration, -1); - } + int Power = this->Power; + int Duration = this->Duration; + TSkill *Drunk = Victim->Skills[SKILL_DRUNK]; + if(Drunk->TimerValue() <= Power){ + Victim->SetTimer(SKILL_DRUNK, Power, Duration, Duration, -1); } } @@ -306,29 +295,12 @@ void TStrengthImpact::handleCreature(TCreature *Victim){ } int Percent = this->Percent; - if(Percent < 0){ - // TODO(fusion): This looks like some inlined function to check if an - // aggression is valid. - if(Actor == Victim){ - return; - } - - if(WorldType == NON_PVP && Actor->IsPeaceful() && Victim->IsPeaceful()){ - return; - } - - if(GetRaceNoParalyze(Victim->Race)){ - return; - } - - if(Victim->Type == PLAYER && CheckRight(Victim->ID, INVULNERABLE)){ - return; - } + if(Percent < 0 && !IsAggressionValid(Actor, Victim)){ + return; } int Skills = this->Skills; int Duration = this->Duration; - for(int SkillNr = 6; SkillNr <= 11; SkillNr += 1){ if((Skills & 1) == 0 && (SkillNr == SKILL_SWORD @@ -409,8 +381,377 @@ void TSummonImpact::handleField(int x, int y, int z){ } } -// Magic Related Functions +// Spell Primitives // ============================================================================= +void ActorShapeSpell(TCreature *Actor, TImpact *Impact, int Effect){ + if(Actor == NULL){ + error("ActorShapeSpell: Sprecher existiert nicht.\n"); + return; + } + + if(Impact->isAggressive() && IsProtectionZone(Actor->posx, Actor->posy, Actor->posz)){ + return; + } + + Impact->handleCreature(Actor); + if(Effect != EFFECT_NONE){ + GraphicalEffect(Actor->posx, Actor->posy, Actor->posz, Effect); + } +} + +void VictimShapeSpell(TCreature *Actor, TCreature *Victim, + int Range, int Animation, TImpact *Impact, int Effect){ + if(Actor == NULL){ + error("VictimShapeSpell: Sprecher existiert nicht.\n"); + return; + } + + if(Victim == NULL || Actor->posz != Victim->posz){ + return; + } + + int Distance = std::max( + std::abs(Actor->posx - Victim->posx), + std::abs(Actor->posy - Victim->posy)); + if(Distance > Range){ + return; + } + + // TODO(fusion): We don't check whether `Actor` is inside a protection zone. + // It might be checked elsewhere. + if(Impact->isAggressive() && IsProtectionZone(Victim->posx, Victim->posy, Victim->posz)){ + return; + } + + if(!ThrowPossible(Actor->posx, Actor->posy, Actor->posz, + Victim->posx, Victim->posy, Victim->posz, 0)){ + return; + } + + if(Animation != ANIMATION_NONE && Distance > 0){ + Missile(Actor->CrObject, Victim->CrObject, Animation); + } + + Impact->handleCreature(Victim); + + if(Effect != EFFECT_NONE){ + GraphicalEffect(Victim->posx, Victim->posy, Victim->posz, Effect); + } +} + +// TODO(fusion): This function wasn't in the debug symbols but it was repeated +// in both `OriginShapeSpell` and `CircleShapeSpell` so I'm almost sure it was +// inlined there. +static void ExecuteCircleSpell(int DestX, int DestY, int DestZ, + int Radius, TImpact *Impact, int Effect){ + // TODO(fusion): This clamping wasn't present in the original function but + // it is probably a good idea. + if(Radius >= NARRAY(Circle)){ + Radius = NARRAY(Circle) - 1; + } + + bool Aggressive = Impact->isAggressive(); + for(int R = 0; R < Radius; R += 1){ + int CirclePoints = Circle[R].Count; + for(int Point = 0; Point < CirclePoints; Point += 1){ + int FieldX = DestX + Circle[R].x[Point]; + int FieldY = DestY + Circle[R].y[Point]; + int FieldZ = DestZ; + + if(Aggressive && IsProtectionZone(FieldX, FieldY, FieldZ)){ + continue; + } + + if(!ThrowPossible(DestX, DestY, DestZ, FieldX, FieldY, FieldZ, 0)){ + continue; + } + + Impact->handleField(FieldX, FieldY, FieldZ); + + Object Obj = GetFirstObject(FieldX, FieldY, FieldZ); + while(Obj != NONE){ + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Victim = GetCreature(Obj); + if(Victim != NULL){ + Impact->handleCreature(Victim); + } + } + Obj = Obj.getNextObject(); + } + + if(Effect != EFFECT_NONE){ + GraphicalEffect(FieldX, FieldY, FieldZ, Effect); + } + } + } +} + +void OriginShapeSpell(TCreature *Actor, int Radius, TImpact *Impact, int Effect){ + if(Actor == NULL){ + error("OriginShapeSpell: Übergebene Kreatur existiert nicht.\n"); + return; + } + + ExecuteCircleSpell(Actor->posx, Actor->posy, Actor->posz, Radius, Impact, Effect); +} + +void CircleShapeSpell(TCreature *Actor, int DestX, int DestY, int DestZ, + int Range, int Animation, int Radius, TImpact *Impact, int Effect){ + if(Actor == NULL){ + error("CircleShapeSpell: Sprecher existiert nicht.\n"); + return; + } + + int Distance = std::max( + std::abs(Actor->posx - DestX), + std::abs(Actor->posy - DestY)); + if(Distance > Range || Actor->posz != DestZ){ + return; + } + + if(!ThrowPossible(Actor->posx, Actor->posy, Actor->posz, DestX, DestY, DestZ, 0)){ + return; + } + + if(Animation != ANIMATION_NONE && Distance > 0){ + Missile(Actor->CrObject, GetMapContainer(DestX, DestY, DestZ), Animation); + } + + ExecuteCircleSpell(DestX, DestY, DestZ, Radius, Impact, Effect); +} + +void DestinationShapeSpell(TCreature *Actor, TCreature *Victim, + int Range, int Animation, int Radius, TImpact *Impact, int Effect){ + if(Actor == NULL){ + error("DestinationShapeSpell: Sprecher existiert nicht.\n"); + return; + } + + if(Victim != NULL){ + CircleShapeSpell(Actor, Victim->posx, Victim->posy, Victim->posz, + Range, Animation, Radius, Impact, Effect); + } +} + +void AngleShapeSpell(TCreature *Actor, int Angle, int Range, TImpact *Impact, int Effect){ + if(Actor == NULL){ + error("AngleShapeSpell: Übergebene Kreatur existiert nicht.\n"); + return; + } + + int ActorX = Actor->posx; + int ActorY = Actor->posy; + int ActorZ = Actor->posz; + int Direction = Actor->Direction; + bool Aggressive = Impact->isAggressive(); + for(int Forward = 1; Forward <= Range; Forward += 1){ + int Left = -(Forward * Angle) / 90; + int Right = +(Forward * Angle) / 90; + for(int Across = Left; Across <= Right; Across += 1){ + int FieldX = ActorX; + int FieldY = ActorY; + int FieldZ = ActorZ; + if(Direction == DIRECTION_NORTH){ + FieldX += Across; + FieldY -= Forward; + }else if(Direction == DIRECTION_EAST){ + FieldX += Forward; + FieldY += Across; + }else if(Direction == DIRECTION_SOUTH){ + FieldX -= Across; + FieldY += Forward; + }else if(Direction == DIRECTION_WEST){ + FieldX -= Forward; + FieldY -= Across; + }else{ + error("AngleShapeSpell: Ungültige Blickrichtung %d.\n", Direction); + return; + } + + if(Aggressive && IsProtectionZone(FieldX, FieldY, FieldZ)){ + continue; + } + + if(!ThrowPossible(ActorX, ActorZ, ActorZ, FieldX, FieldY, FieldZ, 0)){ + continue; + } + + Impact->handleField(FieldX, FieldY, FieldZ); + + Object Obj = GetFirstObject(FieldX, FieldY, FieldZ); + while(Obj != NONE){ + if(Obj.getObjectType().isCreatureContainer()){ + TCreature *Victim = GetCreature(Obj); + if(Victim != NULL){ + Impact->handleCreature(Victim); + } + } + Obj = Obj.getNextObject(); + } + + if(Effect != EFFECT_NONE){ + GraphicalEffect(FieldX, FieldY, FieldZ, Effect); + } + } + } +} + +// Spell Casting +// ============================================================================= +int GetDirection(int dx, int dy){ + // TODO(fusion): This function originally returned directions different from + // the ones used by creatures. I've converted it to use the same values which + // are also defined in `enums.hh` for simplicity. + int Result; + if(dx == 0){ + if(dy < 0){ + Result = DIRECTION_NORTH; + }else if(dy > 0){ + Result = DIRECTION_SOUTH; + }else{ + Result = DIRECTION_INVALID; + } + }else{ + // NOTE(fusion): This function uses the approximate tangent value, avoiding + // floating point calculations, for whatever reason. The tangent is unique + // and odd in the interval (-PI/2, +PI/2). We also need to recall that the + // Y-axis is inverted in Tibia, so we need to negate `dy`. + constexpr int Tangent_67_5 = 618; // => 618 / 256 ~ 2.41 ~ tan(67.5 deg) + constexpr int Tangent_22_5 = 106; // => 106 / 256 ~ 0.41 ~ tan(22.5 deg) + int Tangent = (-dy * 256) / dx; // => (dy * 256) / dx ~ (dy / dx) * 256 + if(Tangent >= Tangent_67_5){ + Result = DIRECTION_NORTH; + }else if(Tangent >= Tangent_22_5){ + Result = (dx < 0) ? DIRECTION_NORTHWEST : DIRECTION_NORTHEAST; + }else if(Tangent >= -Tangent_22_5){ + Result = (dx < 0) ? DIRECTION_WEST : DIRECTION_EAST; + }else if(Tangent >= -Tangent_67_5){ + Result = (dx < 0) ? DIRECTION_SOUTHWEST : DIRECTION_SOUTHEAST; + }else{ + Result = DIRECTION_SOUTH; + } + } + return Result; +} + +void CheckSpellbook(TCreature *Creature, int SpellNr){ + if(Creature == NULL){ + error("CheckSpellbook: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + if(Creature->Type == PLAYER && !CheckRight(Creature->ID, ALL_SPELLS) + && !((TPlayer*)Creature)->SpellKnown(SpellNr)){ + throw SPELLUNKNOWN; + } +} + +void CheckAccount(TCreature *Creature, int SpellNr){ + if(Creature == NULL){ + error("CheckAccount: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + // TODO(fusion): Why is this the only function that checks the spell number? + if(SpellNr < 1 || SpellNr >= NARRAY(SpellList)){ + error("CheckAccount: Ungültige Spruchnummer %d.\n", SpellNr); + throw ERROR; + } + + if(Creature->Type == PLAYER && (SpellList[SpellNr].Flags & 2) != 0 + && !CheckRight(Creature->ID, PREMIUM_ACCOUNT)){ + throw NOPREMIUMACCOUNT; + } +} + +void CheckLevel(TCreature *Creature, int SpellNr){ + if(Creature == NULL){ + error("CheckLevel: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + if(Creature->Type == PLAYER && !CheckRight(Creature->ID, ALL_SPELLS)){ + TSkill *Level = Creature->Skills[SKILL_LEVEL]; + if(Level == NULL){ + error("CheckLevel: Kein Skill LEVEL.\n"); + throw ERROR; + } + + if(Level->Get() < SpellList[SpellNr].Level){ + throw LOWLEVEL; + } + } +} + +void CheckRuneLevel(TCreature *Creature, int SpellNr){ + if(Creature == NULL){ + error("CheckRuneLevel: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + if(Creature->Type == PLAYER && !CheckRight(Creature->ID, ALL_SPELLS)){ + TSkill *MagicLevel = Creature->Skills[SKILL_MAGIC_LEVEL]; + if(MagicLevel == NULL){ + error("CheckLevel: Kein Skill MAGLEVEL.\n"); + throw ERROR; + } + + if(MagicLevel->Get() < SpellList[SpellNr].RuneLevel){ + throw LOWMAGICLEVEL; + } + } +} + +void CheckMagicItem(TCreature *Creature, ObjectType Type){ + if(Creature == NULL){ + error("CheckMagicObject: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + if(Creature->Type == PLAYER && !CheckRight(Creature->ID, ALL_SPELLS) + && CountInventoryObjects(Creature->ID, Type, 0) == 0){ + throw MAGICITEM; + } +} + +void CheckRing(TCreature *Creature, int SpellNr){ + if(Creature == NULL){ + error("CheckRing: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + // TODO(fusion): Not sure why this was present in the original function or + // what is the purpose of this function. +#if 0 + if(Creature->Type == PLAYER){ + CheckRight(Creature->ID, ALL_SPELLS); + } +#endif +} + +void CheckAffectedPlayers(TCreature *Creature, int x, int y, int z){ + if(Creature == NULL){ + error("CheckAffectedPlayers: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + if(WorldType == NORMAL + && Creature->Type == PLAYER + && Creature->Combat.SecureMode == SECURE_MODE_ENABLED){ + Object Obj = GetFirstObject(x, y, z); + while(Obj != NONE){ + if(Obj.getObjectType().isCreatureContainer()){ + uint32 TargetID = Obj.getCreatureID(); + if(IsCreaturePlayer(TargetID) && Creature->ID != TargetID + && !((TPlayer*)Creature)->IsAttackJustified(TargetID)){ + throw SECUREMODE; + } + } + Obj = Obj.getNextObject(); + } + } +} + void CheckMana(TCreature *Creature, int ManaPoints, int SoulPoints, int Delay){ if(Creature == NULL){ error("CheckMana: Übergebene Kreatur existiert nicht.\n"); @@ -456,6 +797,130 @@ void CheckMana(TCreature *Creature, int ManaPoints, int SoulPoints, int Delay){ } } +int ComputeDamage(TCreature *Creature, int SpellNr, int Damage, int Variation){ + if(Variation != 0){ + Damage += random(-Variation, Variation); + } + + if(Creature != NULL && Creature->Type == PLAYER){ + int Level = Creature->Skills[SKILL_LEVEL]->Get(); + int MagicLevel = Creature->Skills[SKILL_MAGIC_LEVEL]->Get(); + int Multiplier = Level * 2 + MagicLevel * 3; + if(SpellNr != 0){ + if((SpellList[SpellNr].Flags & 4) != 0 && Multiplier > 100){ + Multiplier = 100; + } + + if((SpellList[SpellNr].Flags & 8) != 0 && Multiplier < 100){ + Multiplier = 100; + } + } + Damage = (Damage * Multiplier) / 100; + } + + return Damage; +} + +bool IsAggressiveSpell(int SpellNr){ + if(SpellNr < 1 || SpellNr >= NARRAY(SpellList)){ + error("IsAggressiveSpell: Ungültige Spruchnummer %d.\n", SpellNr); + return false; + } + + return (SpellList[SpellNr].Flags & 1) != 0; +} + +void MassCombat(TCreature *Creature, Object Target, int ManaPoints, int SoulPoints, + int Damage, int Effect, int Radius, int DamageType, int Animation){ + if(!Target.exists()){ + error("MassCombat: Übergebenes Ziel existiert nicht.\n"); + throw ERROR; + } + + if(Creature != NULL){ + error("MassCombat: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + int TargetX, TargetY, TargetZ; + GetObjectCoordinates(Target, &TargetX, &TargetY, &TargetZ); + CheckAffectedPlayers(Creature, TargetX, TargetY, TargetZ); + if(!ThrowPossible(Creature->posx, Creature->posy, Creature->posz, + TargetX, TargetY, TargetZ, 0)){ + throw CANNOTTHROW; + } + + int Delay = 2000; + if(WorldType == PVP_ENFORCED){ + Delay = 1000; + } + CheckMana(Creature, ManaPoints, SoulPoints, Delay); + + TDamageImpact Impact(Creature, DamageType, Damage, false); + CircleShapeSpell(Creature, TargetX, TargetY, TargetZ, + INT_MAX, Animation, Radius, &Impact, Effect); +} + +void AngleCombat(TCreature *Creature, int ManaPoints, int SoulPoints, + int Damage, int Effect, int Range, int Angle, int DamageType){ + if(Creature == NULL){ + error("AngleCombat: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + int Delay = 2000; + if(WorldType == PVP_ENFORCED || (Range == 1 && Angle == 0)){ + Delay = 1000; + } + CheckMana(Creature, ManaPoints, SoulPoints, Delay); + + TDamageImpact Impact(Creature, DamageType, Damage, false); + AngleShapeSpell(Creature, Angle, Range, &Impact, Effect); +} + +void Combat(TCreature *Creature, Object Target, int ManaPoints, int SoulPoints, + int Damage,int Effect, int Animation, int DamageType){ + if(!Target.exists()){ + error("Combat: Übergebenes Ziel existiert nicht.\n"); + throw ERROR; + } + + if(Creature == NULL){ + error("Combat: Übergebene Kreatur existiert nicht.\n"); + throw ERROR; + } + + int TargetX, TargetY, TargetZ; + GetObjectCoordinates(Target, &TargetX, &TargetY, &TargetZ); + if(!Target.getObjectType().isCreatureContainer()){ + Target = GetFirstSpecObject(TargetX, TargetY, TargetZ, TYPEID_CREATURE_CONTAINER); + } + + if(Target == NONE){ + throw NOCREATURE; + } + + CheckAffectedPlayers(Creature, TargetX, TargetY, TargetZ); + if(!ThrowPossible(Creature->posx, Creature->posy, Creature->posz, + TargetX, TargetY, TargetZ, 0)){ + throw CANNOTTHROW; + } + + int Delay = 2000; + if(WorldType == PVP_ENFORCED){ + Delay = 1000; + } + CheckMana(Creature, ManaPoints, SoulPoints, Delay); + + TDamageImpact Impact(Creature, DamageType, Damage, false); + CircleShapeSpell(Creature, TargetX, TargetY, TargetZ, + INT_MAX, Animation, 0, &Impact, Effect); +} + +// Spell Functions +// ============================================================================= +// TODO + // Magic Init Functions // ============================================================================= static void InitCircles(void){ diff --git a/src/player.hh b/src/player.hh index b98882e..a0ae9e1 100644 --- a/src/player.hh +++ b/src/player.hh @@ -75,6 +75,8 @@ struct TPlayer: TCreature { uint32 GetPartyLeader(bool CheckFormer); + bool SpellKnown(int SpellNr); + bool IsAttackJustified(uint32 Victim); void RecordAttack(uint32 Victim); void RecordMurder(uint32 Victim); diff --git a/src/stubs.hh b/src/stubs.hh index 3a58557..c254ec7 100644 --- a/src/stubs.hh +++ b/src/stubs.hh @@ -26,6 +26,7 @@ extern void CircleShapeSpell(TCreature *Actor, int DestX, int DestY, int DestZ, int Range, int Animation, int Radius, TImpact *Impact, int Effect); extern void CleanHouseField(int x, int y, int z); extern int ComputeDamage(TCreature *Creature, int SpellNr, int Damage, int Variation); +extern int CountInventoryObjects(uint32 CreatureID, ObjectType Type, uint32 Value); extern void CreateField(int x, int y, int z, int FieldType, uint32 Owner, bool Peaceful); extern void CreateMonster(int Race, int x, int y, int z, int Home, uint32 Master, bool ShowEffect); extern void CreatePlayerList(bool Online); @@ -33,6 +34,7 @@ extern void CreatePool(Object Con, ObjectType Type, uint32 Value); extern void Delete(Object Obj, int Count); extern Object GetBodyObject(uint32 CreatureID, int Position); extern TCreature *GetCreature(uint32 CreatureID); +extern TCreature *GetCreature(Object Obj); extern TConnection *GetFirstConnection(void); extern TConnection *GetNextConnection(void); extern TPlayer *GetPlayer(uint32 CreatureID); -- cgit v1.2.3