aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-06-01 22:51:33 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-06-01 22:56:01 -0300
commit189d40706feea796fe9307c915f29d2158769357 (patch)
treec9daf3b799f417ea1018960c7bde7f3fb41b05c5
parent9c74d168961619d754ca9f51aa86686185d3f92e (diff)
downloadgame-189d40706feea796fe9307c915f29d2158769357.tar.gz
game-189d40706feea796fe9307c915f29d2158769357.zip
more work on spell primitives
-rw-r--r--reference/game.c1646
-rw-r--r--src/creature.cc4
-rw-r--r--src/creature.hh5
-rw-r--r--src/enums.hh13
-rw-r--r--src/magic.cc591
-rw-r--r--src/player.hh2
-rw-r--r--src/stubs.hh2
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<char,std::char_traits<char>,std::allocator<char>_> * 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<int>(
+ 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<int>(
+ 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);