aboutsummaryrefslogtreecommitdiff
path: root/engines/dm/projexpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/dm/projexpl.cpp')
-rw-r--r--engines/dm/projexpl.cpp418
1 files changed, 418 insertions, 0 deletions
diff --git a/engines/dm/projexpl.cpp b/engines/dm/projexpl.cpp
new file mode 100644
index 0000000000..95d40bbaea
--- /dev/null
+++ b/engines/dm/projexpl.cpp
@@ -0,0 +1,418 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* Based on the Reverse Engineering work of Christophe Fontanel,
+* maintainer of the Dungeon Master Encyclopaedia (http://dmweb.free.fr/)
+*/
+
+
+#include "projexpl.h"
+#include "dungeonman.h"
+#include "timeline.h"
+#include "group.h"
+#include "objectman.h"
+#include "movesens.h"
+
+namespace DM {
+
+ProjExpl::ProjExpl(DMEngine* vm) : _vm(vm) {
+ _g361_lastCreatureAttackTime = -200;
+}
+
+void ProjExpl::f212_projectileCreate(Thing thing, int16 mapX, int16 mapY, uint16 cell, direction dir, byte kineticEnergy, byte attack, byte stepEnergy) {
+ Thing L0466_T_ProjectileThing;
+ Projectile* L0467_ps_Projectile;
+ TimelineEvent L0468_s_Event;
+
+
+ if ((L0466_T_ProjectileThing = _vm->_dungeonMan->f166_getUnusedThing(k14_ProjectileThingType)) == Thing::_none) { /* BUG0_16 If the game cannot create a projectile thing because it has run out of such things (60 maximum) then the object being thrown/shot/launched is orphaned. If the game has run out of projectile things it will try to remove a projectile from elsewhere in the dungeon, except in an area of 11x11 squares centered around the party (to make sure the player cannot actually see the thing disappear on screen) */
+ return;
+ }
+ L0466_T_ProjectileThing = M15_thingWithNewCell(L0466_T_ProjectileThing, cell);
+ L0467_ps_Projectile = (Projectile*)_vm->_dungeonMan->f156_getThingData(L0466_T_ProjectileThing);
+ L0467_ps_Projectile->_slot = thing;
+ L0467_ps_Projectile->_kineticEnergy = MIN((int16)kineticEnergy, (int16)255);
+ L0467_ps_Projectile->_attack = attack;
+ _vm->_dungeonMan->f163_linkThingToList(L0466_T_ProjectileThing, Thing(0), mapX, mapY); /* Projectiles are added on the square and not 'moved' onto the square. In the case of a projectile launcher sensor, this means that the new projectile traverses the square in front of the launcher without any trouble: there is no impact if it is a wall, the projectile direction is not changed if it is a teleporter. Impacts with creatures and champions are still processed */
+ M33_setMapAndTime(L0468_s_Event._mapTime, _vm->_dungeonMan->_g272_currMapIndex, _vm->_g313_gameTime + 1);
+ if (_g365_createLanucherProjectile) {
+ L0468_s_Event._type = k49_TMEventTypeMoveProjectile; /* Launcher projectiles can impact immediately */
+ } else {
+ L0468_s_Event._type = k48_TMEventTypeMoveProjectileIgnoreImpacts; /* Projectiles created by champions or creatures ignore impacts on their first movement */
+ }
+ L0468_s_Event._priority = 0;
+ L0468_s_Event._B._slot = L0466_T_ProjectileThing;
+ L0468_s_Event._C._projectile.setMapX(mapX);
+ L0468_s_Event._C._projectile.setMapY(mapY);
+ L0468_s_Event._C._projectile.setStepEnergy(stepEnergy);
+ L0468_s_Event._C._projectile.setDir(dir);
+ L0467_ps_Projectile->_eventIndex = _vm->_timeline->f238_addEventGetEventIndex(&L0468_s_Event);
+}
+
+bool ProjExpl::f217_projectileHasImpactOccurred(int16 impactType, int16 mapXCombo, int16 mapYCombo, int16 cell, Thing projectileThing) {
+#define AP0454_i_ProjectileTargetMapX mapXCombo
+#define AP0455_i_ProjectileTargetMapY mapYCombo
+#define AP0456_i_ChampionIndex cell
+ Projectile* L0490_ps_Projectile;
+ Group* L0491_ps_Group;
+ Thing L0486_T_ProjectileAssociatedThing;
+ int16 L0487_i_Multiple;
+#define AL0487_i_DoorState L0487_i_Multiple
+#define AL0487_i_IconIndex L0487_i_Multiple
+#define AL0487_i_Outcome L0487_i_Multiple
+#define AL0487_i_WeaponType L0487_i_Multiple
+ int16 L0488_i_Attack = 0;
+ Potion* L0492_ps_Potion = nullptr;
+ CreatureInfo* L0493_ps_CreatureInfo;
+ Door* L0494_ps_Door;
+ Weapon* L0495_ps_Weapon;
+ uint16* L0496_pui_CreatureHealth;
+ Thing* L0497_pT_GroupSlot;
+ Thing L0498_T_ExplosionThing;
+ int16 L0499_i_ProjectileMapX;
+ int16 L0500_i_ProjectileMapY;
+ int16 L0501_i_MapXCombo;
+ int16 L0502_i_MapYCombo;
+ byte L0503_uc_Square;
+ bool L0505_B_CreateExplosionOnImpact;
+ int16 L0489_i_ChampionAttack;
+ uint16 L0507_ui_Multiple;
+#define AL0507_ui_ExplosionAttack L0507_ui_Multiple
+#define AL0507_ui_SoundIndex L0507_ui_Multiple
+ int16 L0508_i_PotionPower = 0;
+ bool L0509_B_RemovePotion;
+ int16 L0510_i_ProjectileAssociatedThingType;
+ uint16 L0511_ui_CreatureType;
+ uint16 L0512_ui_CreatureIndex;
+
+ L0490_ps_Projectile = (Projectile*)_vm->_dungeonMan->f156_getThingData(Thing(projectileThing));
+ L0501_i_MapXCombo = mapXCombo;
+ L0502_i_MapYCombo = mapYCombo;
+ L0509_B_RemovePotion = false;
+ _g364_creatureDamageOutcome = k0_outcomeKilledNoCreaturesInGroup;
+ if ((L0510_i_ProjectileAssociatedThingType = (L0486_T_ProjectileAssociatedThing = L0490_ps_Projectile->_slot).getType()) == k8_PotionThingType) {
+ L0491_ps_Group = (Group*)_vm->_dungeonMan->f156_getThingData(L0486_T_ProjectileAssociatedThing);
+ switch (((Potion*)L0491_ps_Group)->getType()) {
+ case k3_PotionTypeVen:
+ L0498_T_ExplosionThing = Thing::_explPoisonCloud;
+ goto T0217004;
+ case k19_PotionTypeFulBomb:
+ L0498_T_ExplosionThing = Thing::_explFireBall;
+T0217004:
+ L0509_B_RemovePotion = true;
+ L0508_i_PotionPower = ((Potion*)L0491_ps_Group)->getPower();
+ L0492_ps_Potion = (Potion*)L0491_ps_Group;
+ }
+ }
+ L0505_B_CreateExplosionOnImpact = (L0510_i_ProjectileAssociatedThingType == k15_ExplosionThingType) && (L0486_T_ProjectileAssociatedThing != Thing::_explSlime) && (L0486_T_ProjectileAssociatedThing != Thing::_explPoisonBolt);
+ L0497_pT_GroupSlot = NULL;
+ L0489_i_ChampionAttack = 0;
+ if (mapXCombo <= 255) {
+ L0499_i_ProjectileMapX = mapXCombo;
+ L0500_i_ProjectileMapY = mapYCombo;
+ } else {
+ L0499_i_ProjectileMapX = (mapXCombo >> 8) - 1;
+ L0500_i_ProjectileMapY = (mapYCombo >> 8);
+ AP0454_i_ProjectileTargetMapX &= 0x00FF;
+ AP0455_i_ProjectileTargetMapY &= 0x00FF;
+ }
+ switch (impactType) {
+ case k4_DoorElemType:
+ AL0487_i_DoorState = Square(L0503_uc_Square = _vm->_dungeonMan->_g271_currMapData[AP0454_i_ProjectileTargetMapX][AP0455_i_ProjectileTargetMapY]).getDoorState();
+ L0494_ps_Door = (Door*)_vm->_dungeonMan->f157_getSquareFirstThingData(AP0454_i_ProjectileTargetMapX, AP0455_i_ProjectileTargetMapY);
+ if ((AL0487_i_DoorState != k5_doorState_DESTROYED) && (L0486_T_ProjectileAssociatedThing == Thing::_explOpenDoor)) {
+ if (L0494_ps_Door->hasButton()) {
+ _vm->_movsens->f268_addEvent(k10_TMEventTypeDoor, AP0454_i_ProjectileTargetMapX, AP0455_i_ProjectileTargetMapY, 0, k2_SensorEffToggle, _vm->_g313_gameTime + 1);
+ }
+ break;
+ }
+ if ((AL0487_i_DoorState == k5_doorState_DESTROYED) ||
+ (AL0487_i_DoorState <= k1_doorState_FOURTH) ||
+ (getFlag(_vm->_dungeonMan->_g275_currMapDoorInfo[L0494_ps_Door->getType()]._attributes, k0x0002_MaskDoorInfo_ProjectilesCanPassThrough) &&
+ ((L0510_i_ProjectileAssociatedThingType == k15_ExplosionThingType) ?
+ (L0486_T_ProjectileAssociatedThing.toUint16() >= Thing::_explHarmNonMaterial.toUint16()) :
+ ((L0490_ps_Projectile->_attack > _vm->getRandomNumber(128)) &&
+ getFlag(g237_ObjectInfo[_vm->_dungeonMan->f141_getObjectInfoIndex(L0486_T_ProjectileAssociatedThing)].getAllowedSlots(), k0x0100_ObjectAllowedSlotPouchPassAndThroughDoors)
+ && ((L0510_i_ProjectileAssociatedThingType != k10_JunkThingType) ||
+ ((AL0487_i_IconIndex = _vm->_objectMan->f33_getIconIndex(L0486_T_ProjectileAssociatedThing)) < 0) ||
+ (!((AL0487_i_IconIndex >= k176_IconIndiceJunkIronKey) && (AL0487_i_IconIndex <= k191_IconIndiceJunkMasterKey))))
+ )))) { /* ASSEMBLY_COMPILATION_DIFFERENCE jmp */
+ return false;
+ }
+ L0488_i_Attack = f216_projectileGetImpactAttack(L0490_ps_Projectile, L0486_T_ProjectileAssociatedThing) + 1;
+ _vm->_groupMan->f232_groupIsDoorDestoryedByAttack(AP0454_i_ProjectileTargetMapX, AP0455_i_ProjectileTargetMapY, L0488_i_Attack + _vm->getRandomNumber(L0488_i_Attack), false, 0);
+ break;
+ case kM2_ChampionElemType:
+ if ((AP0456_i_ChampionIndex = _vm->_championMan->f285_getIndexInCell(cell)) < 0) {
+ return false;
+ }
+ L0489_i_ChampionAttack = L0488_i_Attack = f216_projectileGetImpactAttack(L0490_ps_Projectile, L0486_T_ProjectileAssociatedThing);
+ break;
+ case kM1_CreatureElemType:
+ L0491_ps_Group = (Group*)_vm->_dungeonMan->f156_getThingData(_vm->_groupMan->f175_groupGetThing(AP0454_i_ProjectileTargetMapX, AP0455_i_ProjectileTargetMapY));
+ if (!(L0512_ui_CreatureIndex = _vm->_groupMan->f176_getCreatureOrdinalInCell(L0491_ps_Group, cell))) {
+ return false;
+ }
+ L0512_ui_CreatureIndex--;
+ L0493_ps_CreatureInfo = &g243_CreatureInfo[L0511_ui_CreatureType = L0491_ps_Group->_type];
+ if ((L0486_T_ProjectileAssociatedThing == Thing::_explFireBall) && (L0511_ui_CreatureType == k11_CreatureTypeBlackFlame)) {
+ L0496_pui_CreatureHealth = &L0491_ps_Group->_health[L0512_ui_CreatureIndex];
+ *L0496_pui_CreatureHealth = MIN(1000, *L0496_pui_CreatureHealth + f216_projectileGetImpactAttack(L0490_ps_Projectile, L0486_T_ProjectileAssociatedThing));
+ goto T0217044;
+ }
+ if (getFlag(L0493_ps_CreatureInfo->_attributes, k0x0040_MaskCreatureInfo_nonMaterial) && (L0486_T_ProjectileAssociatedThing != Thing::_explHarmNonMaterial)) {
+ return false;
+ }
+ if (L0488_i_Attack = (uint16)((unsigned long)f216_projectileGetImpactAttack(L0490_ps_Projectile, L0486_T_ProjectileAssociatedThing) << 6) / L0493_ps_CreatureInfo->_defense) {
+ if ((AL0487_i_Outcome = _vm->_groupMan->f190_groupGetDamageCreatureOutcome(L0491_ps_Group, L0512_ui_CreatureIndex, AP0454_i_ProjectileTargetMapX, AP0455_i_ProjectileTargetMapY, L0488_i_Attack + _vm->_groupMan->f192_groupGetResistanceAdjustedPoisonAttack(L0511_ui_CreatureType, _g366_projectilePoisonAttack), true)) != k0_outcomeKilledNoCreaturesInGroup) {
+ _vm->_groupMan->f209_processEvents29to41(AP0454_i_ProjectileTargetMapX, AP0455_i_ProjectileTargetMapY, kM2_TMEventTypeCreateReactionEvent30HitByProjectile, 0);
+ }
+ _g364_creatureDamageOutcome = AL0487_i_Outcome;
+ if (!L0505_B_CreateExplosionOnImpact &&
+ (AL0487_i_Outcome == k0_outcomeKilledNoCreaturesInGroup) &&
+ (L0510_i_ProjectileAssociatedThingType == k5_WeaponThingType) &&
+ getFlag(L0493_ps_CreatureInfo->_attributes, k0x0400_MaskCreatureInfo_keepThrownSharpWeapon)) {
+ L0495_ps_Weapon = (Weapon*)_vm->_dungeonMan->f156_getThingData(L0486_T_ProjectileAssociatedThing);
+ AL0487_i_WeaponType = L0495_ps_Weapon->getType();
+ if ((AL0487_i_WeaponType == k8_WeaponTypeDagger) || (AL0487_i_WeaponType == k27_WeaponTypeArrow) || (AL0487_i_WeaponType == k28_WeaponTypeSlayer) || (AL0487_i_WeaponType == k31_WeaponTypePoisonDart) || (AL0487_i_WeaponType == k32_WeaponTypeThrowingStar)) {
+ L0497_pT_GroupSlot = &L0491_ps_Group->_slot;
+ }
+ }
+ }
+ }
+ if (L0489_i_ChampionAttack && _vm->_championMan->f321_addPendingDamageAndWounds_getDamage(AP0456_i_ChampionIndex, L0488_i_Attack, k0x0004_ChampionWoundHead | k0x0008_ChampionWoundTorso, _g367_projectileAttackType) && _g366_projectilePoisonAttack && _vm->getRandomNumber(2)) {
+ _vm->_championMan->f322_championPoison(AP0456_i_ChampionIndex, _g366_projectilePoisonAttack);
+ }
+ if (L0505_B_CreateExplosionOnImpact || L0509_B_RemovePotion
+ ) {
+ if (L0509_B_RemovePotion) {
+ L0486_T_ProjectileAssociatedThing = L0498_T_ExplosionThing;
+ AL0507_ui_ExplosionAttack = L0508_i_PotionPower;
+ } else {
+ AL0507_ui_ExplosionAttack = L0490_ps_Projectile->_kineticEnergy;
+ }
+ if ((L0486_T_ProjectileAssociatedThing == Thing::_explLightningBolt) && !(AL0507_ui_ExplosionAttack >>= 1))
+ goto T0217044;
+ f213_explosionCreate(L0486_T_ProjectileAssociatedThing, AL0507_ui_ExplosionAttack, L0501_i_MapXCombo, L0502_i_MapYCombo, (L0486_T_ProjectileAssociatedThing == Thing::_explPoisonCloud) ? k255_CreatureTypeSingleCenteredCreature : cell);
+ } else {
+ if ((L0486_T_ProjectileAssociatedThing).getType() == k5_WeaponThingType) {
+ AL0507_ui_SoundIndex = k00_soundMETALLIC_THUD;
+ } else {
+ if (L0486_T_ProjectileAssociatedThing == Thing::_explPoisonBolt) {
+ AL0507_ui_SoundIndex = k13_soundSPELL;
+ } else {
+ AL0507_ui_SoundIndex = k04_soundWOODEN_THUD_ATTACK_TROLIN_ANTMAN_STONE_GOLEM;
+ }
+ }
+ warning("MISSING CODE: F0064_SOUND_RequestPlay_CPSD");
+ }
+T0217044:
+ if (L0509_B_RemovePotion) {
+ L0492_ps_Potion->_nextThing = Thing::_none;
+ L0490_ps_Projectile->_slot = L0498_T_ExplosionThing;
+ }
+ _vm->_dungeonMan->f164_unlinkThingFromList(projectileThing, Thing(0), L0499_i_ProjectileMapX, L0500_i_ProjectileMapY);
+ f215_projectileDelete(projectileThing, L0497_pT_GroupSlot, L0499_i_ProjectileMapX, L0500_i_ProjectileMapY);
+ return true;
+}
+
+uint16 ProjExpl::f216_projectileGetImpactAttack(Projectile* projectile, Thing thing) {
+ WeaponInfo* L0485_ps_WeaponInfo;
+ uint16 L0483_ui_Multiple;
+#define AL0483_ui_ThingType L0483_ui_Multiple
+#define AL0483_ui_Attack L0483_ui_Multiple
+ uint16 L0484_ui_KineticEnergy;
+
+
+ _g366_projectilePoisonAttack = 0;
+ _g367_projectileAttackType = k3_attackType_BLUNT;
+
+ L0484_ui_KineticEnergy = projectile->_kineticEnergy;
+ if ((AL0483_ui_ThingType = (thing).getType()) != k15_ExplosionThingType) {
+ if (AL0483_ui_ThingType == k5_WeaponThingType) {
+ L0485_ps_WeaponInfo = _vm->_dungeonMan->f158_getWeaponInfo(thing);
+ AL0483_ui_Attack = L0485_ps_WeaponInfo->_kineticEnergy;
+ _g367_projectileAttackType = k3_attackType_BLUNT;
+ } else {
+ AL0483_ui_Attack = _vm->getRandomNumber(4);
+ }
+ AL0483_ui_Attack += _vm->_dungeonMan->f140_getObjectWeight(thing) >> 1;
+ } else {
+ if (thing == Thing::_explSlime) {
+ AL0483_ui_Attack = _vm->getRandomNumber(16);
+ _g366_projectilePoisonAttack = AL0483_ui_Attack + 10;
+ AL0483_ui_Attack += _vm->getRandomNumber(32);
+ } else {
+ if (thing.toUint16() >= Thing::_explHarmNonMaterial.toUint16()) {
+ _g367_projectileAttackType = k5_attackType_MAGIC;
+ if (thing == Thing::_explPoisonBolt) {
+ _g366_projectilePoisonAttack = L0484_ui_KineticEnergy;
+ return 1;
+ }
+ return 0;
+ }
+ _g367_projectileAttackType = k1_attackType_FIRE;
+ AL0483_ui_Attack = _vm->getRandomNumber(16) + _vm->getRandomNumber(16) + 10;
+ if (thing == Thing::_explLightningBolt) {
+ _g367_projectileAttackType = k7_attackType_LIGHTNING;
+ AL0483_ui_Attack *= 5;
+ }
+ }
+ }
+ AL0483_ui_Attack = ((AL0483_ui_Attack + L0484_ui_KineticEnergy) >> 4) + 1;
+ AL0483_ui_Attack += _vm->getRandomNumber((AL0483_ui_Attack >> 1) + 1) + _vm->getRandomNumber(4);
+ AL0483_ui_Attack = MAX(AL0483_ui_Attack >> 1, AL0483_ui_Attack - (32 - (projectile->_attack >> 3)));
+ return AL0483_ui_Attack;
+}
+
+void ProjExpl::f213_explosionCreate(Thing explThing, uint16 attack, uint16 mapXCombo, uint16 mapYCombo, uint16 cell) {
+#define AP0443_ui_ProjectileMapX mapXCombo
+#define AP0444_ui_ProjectileMapY mapYCombo
+ Explosion* L0470_ps_Explosion;
+ CreatureInfo* L0471_ps_CreatureInfo;
+ Group* L0472_ps_Group;
+ Thing L0473_T_Thing;
+ int16 L0474_i_ProjectileTargetMapX;
+ int16 L0475_i_ProjectileTargetMapY;
+ int16 L0469_i_CreatureFireResistance;
+ TimelineEvent L0476_s_Event;
+
+
+ if ((L0473_T_Thing = _vm->_dungeonMan->f166_getUnusedThing(k15_ExplosionThingType)) == Thing::_none) {
+ return;
+ }
+ L0470_ps_Explosion = &((Explosion*)_vm->_dungeonMan->_g284_thingData[k15_ExplosionThingType])[(L0473_T_Thing).getIndex()];
+ if (mapXCombo <= 255) {
+ L0474_i_ProjectileTargetMapX = mapXCombo;
+ L0475_i_ProjectileTargetMapY = mapYCombo;
+ } else {
+ L0474_i_ProjectileTargetMapX = mapXCombo & 0x00FF;
+ L0475_i_ProjectileTargetMapY = mapYCombo & 0x00FF;
+ AP0443_ui_ProjectileMapX >>= 8;
+ AP0443_ui_ProjectileMapX--;
+ AP0444_ui_ProjectileMapY >>= 8;
+ }
+ if (cell == k255_CreatureTypeSingleCenteredCreature) {
+ L0470_ps_Explosion->setCentered(true);
+ } else {
+ L0470_ps_Explosion->setCentered(false);
+ L0473_T_Thing = M15_thingWithNewCell(L0473_T_Thing, cell);
+ }
+ L0470_ps_Explosion->setType(explThing.toUint16() - Thing::_firstExplosion.toUint16());
+ L0470_ps_Explosion->setAttack(attack);
+ if (explThing.toUint16() < Thing::_explHarmNonMaterial.toUint16()) {
+ warning("MISING CODE: F0064_SOUND_RequestPlay_CPSD");
+ } else {
+ if (explThing != Thing::_explSmoke) {
+ warning("MISSING CODE: F0064_SOUND_RequestPlay_CPSD");
+ }
+ }
+ _vm->_dungeonMan->f163_linkThingToList(L0473_T_Thing, Thing(0), AP0443_ui_ProjectileMapX, AP0444_ui_ProjectileMapY);
+ M33_setMapAndTime(L0476_s_Event._mapTime, _vm->_dungeonMan->_g272_currMapIndex, _vm->_g313_gameTime + ((explThing == Thing::_explRebirthStep1) ? 5 : 1));
+ L0476_s_Event._type = k25_TMEventTypeExplosion;
+ L0476_s_Event._priority = 0;
+ L0476_s_Event._C._slot = L0473_T_Thing;
+ L0476_s_Event._B._location._mapX = AP0443_ui_ProjectileMapX;
+ L0476_s_Event._B._location._mapY = AP0444_ui_ProjectileMapY;
+ _vm->_timeline->f238_addEventGetEventIndex(&L0476_s_Event);
+ if ((explThing == Thing::_explLightningBolt) || (explThing == Thing::_explFireBall)) {
+ AP0443_ui_ProjectileMapX = L0474_i_ProjectileTargetMapX;
+ AP0444_ui_ProjectileMapY = L0475_i_ProjectileTargetMapY;
+ attack = (attack >> 1) + 1;
+ attack += _vm->getRandomNumber(attack) + 1;
+ if ((explThing == Thing::_explFireBall) || (attack >>= 1)) {
+ if ((_vm->_dungeonMan->_g272_currMapIndex == _vm->_dungeonMan->_g309_partyMapIndex) && (AP0443_ui_ProjectileMapX == _vm->_dungeonMan->_g306_partyMapX) && (AP0444_ui_ProjectileMapY == _vm->_dungeonMan->_g307_partyMapY)) {
+ _vm->_championMan->f324_damageAll_getDamagedChampionCount(attack, k0x0001_ChampionWoundReadHand | k0x0002_ChampionWoundActionHand | k0x0004_ChampionWoundHead | k0x0008_ChampionWoundTorso | k0x0010_ChampionWoundLegs | k0x0020_ChampionWoundFeet, k1_attackType_FIRE);
+ } else {
+ if ((L0473_T_Thing = _vm->_groupMan->f175_groupGetThing(AP0443_ui_ProjectileMapX, AP0444_ui_ProjectileMapY)) != Thing::_endOfList) { /* ASSEMBLY_COMPILATION_DIFFERENCE jmp */
+ L0472_ps_Group = (Group*)_vm->_dungeonMan->f156_getThingData(L0473_T_Thing);
+ L0471_ps_CreatureInfo = &g243_CreatureInfo[L0472_ps_Group->_type];
+ if ((L0469_i_CreatureFireResistance = (L0471_ps_CreatureInfo->M60_getFireResistance())) != k15_immuneToFire) {
+ if (getFlag(L0471_ps_CreatureInfo->_attributes, k0x0040_MaskCreatureInfo_nonMaterial)) {
+ attack >>= 2;
+ }
+ if ((attack -= _vm->getRandomNumber((L0469_i_CreatureFireResistance << 1) + 1)) > 0) {
+ _g364_creatureDamageOutcome = _vm->_groupMan->f191_getDamageAllCreaturesOutcome(L0472_ps_Group, AP0443_ui_ProjectileMapX, AP0444_ui_ProjectileMapY, attack, true);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+int16 ProjExpl::f218_projectileGetImpactCount(int16 impactType, int16 mapX, int16 mapY, int16 cell) {
+ Thing L0513_T_Thing;
+ int16 L0514_i_ImpactCount;
+
+
+ L0514_i_ImpactCount = 0;
+ _g364_creatureDamageOutcome = k0_outcomeKilledNoCreaturesInGroup;
+T0218001:
+ L0513_T_Thing = _vm->_dungeonMan->f161_getSquareFirstThing(mapX, mapY);
+ while (L0513_T_Thing != Thing::_endOfList) {
+ if (((L0513_T_Thing).getType() == k14_ProjectileThingType) &&
+ ((L0513_T_Thing).getCell() == cell) &&
+ f217_projectileHasImpactOccurred(impactType, mapX, mapY, cell, L0513_T_Thing)) {
+ f214_projectileDeleteEvent(L0513_T_Thing);
+ L0514_i_ImpactCount++;
+ if ((impactType == kM1_CreatureElemType) && (_g364_creatureDamageOutcome == k2_outcomeKilledAllCreaturesInGroup))
+ break;
+ goto T0218001;
+ }
+ L0513_T_Thing = _vm->_dungeonMan->f159_getNextThing(L0513_T_Thing);
+ }
+ return L0514_i_ImpactCount;
+}
+
+void ProjExpl::f214_projectileDeleteEvent(Thing thing) {
+ Projectile* L0477_ps_Projectile;
+
+
+ L0477_ps_Projectile = (Projectile*)_vm->_dungeonMan->f156_getThingData(thing);
+ _vm->_timeline->f237_deleteEvent(L0477_ps_Projectile->_eventIndex);
+}
+
+void ProjExpl::f215_projectileDelete(Thing projectileThing, Thing* groupSlot, int16 mapX, int16 mapY) {
+ Thing L0478_T_PreviousThing;
+ Thing L0479_T_Thing;
+ Projectile* L0480_ps_Projectile;
+ Thing* L0481_ps_Generic;
+
+ L0480_ps_Projectile = (Projectile*)_vm->_dungeonMan->f156_getThingData(projectileThing);
+ if ((L0479_T_Thing = L0480_ps_Projectile->_slot).getType() != k15_ExplosionThingType) {
+ if (groupSlot != NULL) {
+ if ((L0478_T_PreviousThing = *groupSlot) == Thing::_endOfList) {
+ L0481_ps_Generic = (Thing*)_vm->_dungeonMan->f156_getThingData(L0479_T_Thing);
+ *L0481_ps_Generic = Thing::_endOfList;
+ *groupSlot = L0479_T_Thing;
+ } else {
+ _vm->_dungeonMan->f163_linkThingToList(L0479_T_Thing, L0478_T_PreviousThing, kM1_MapXNotOnASquare, 0);
+ }
+ } else {
+ _vm->_movsens->f267_getMoveResult(Thing((L0479_T_Thing).getTypeAndIndex() | getFlag(projectileThing.toUint16(), 0xC)), -2, 0, mapX, mapY);
+ }
+ }
+ L0480_ps_Projectile->_nextThing = Thing::_none;
+}
+}