diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-06-01 22:51:33 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-06-01 22:56:01 -0300 |
| commit | 189d40706feea796fe9307c915f29d2158769357 (patch) | |
| tree | c9daf3b799f417ea1018960c7bde7f3fb41b05c5 | |
| parent | 9c74d168961619d754ca9f51aa86686185d3f92e (diff) | |
| download | game-189d40706feea796fe9307c915f29d2158769357.tar.gz game-189d40706feea796fe9307c915f29d2158769357.zip | |
more work on spell primitives
| -rw-r--r-- | reference/game.c | 1646 | ||||
| -rw-r--r-- | src/creature.cc | 4 | ||||
| -rw-r--r-- | src/creature.hh | 5 | ||||
| -rw-r--r-- | src/enums.hh | 13 | ||||
| -rw-r--r-- | src/magic.cc | 591 | ||||
| -rw-r--r-- | src/player.hh | 2 | ||||
| -rw-r--r-- | 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<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); |
