Add explosions improvements (#29)
This commit is contained in:
parent
3ccb087d20
commit
5170948588
|
@ -316,8 +316,32 @@ void _show_damage_to_object(Object* a1, int damage, int flags, Object* weapon, b
|
|||
sfx_name = sfxBuildCharName(a1, anim, CHARACTER_SOUND_EFFECT_UNUSED);
|
||||
animationRegisterPlaySoundEffect(a1, sfx_name, a10);
|
||||
|
||||
// SFALL
|
||||
if (explosionEmitsLight()) {
|
||||
// 0xFFFF0002:
|
||||
// - distance: 2
|
||||
// - intensity: 65535
|
||||
//
|
||||
// NOTE: Change intensity to 65536 (which is on par with
|
||||
// `anim_set_check_light_fix` Sfall's hack).
|
||||
animationRegisterSetLightIntensity(a1, 2, 65536, 0);
|
||||
}
|
||||
|
||||
animationRegisterAnimate(a1, anim, 0);
|
||||
|
||||
// SFALL
|
||||
if (explosionEmitsLight()) {
|
||||
// 0x00010000:
|
||||
// - distance: 0
|
||||
// - intensity: 1
|
||||
//
|
||||
// NOTE: Change intensity to 0. I guess using 1 was a
|
||||
// workaround for `anim_set_check_light_fix` hack which
|
||||
// requires two upper bytes to be non-zero to override
|
||||
// default behaviour.
|
||||
animationRegisterSetLightIntensity(a1, 0, 0, -1);
|
||||
}
|
||||
|
||||
int randomDistance = randomBetween(2, 5);
|
||||
int randomRotation = randomBetween(0, 5);
|
||||
|
||||
|
@ -692,7 +716,8 @@ int _action_ranged(Attack* attack, int anim)
|
|||
|
||||
bool isGrenade = false;
|
||||
if (anim == ANIM_THROW_ANIM) {
|
||||
if (damageType == DAMAGE_TYPE_EXPLOSION || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP) {
|
||||
// SFALL
|
||||
if (damageType == explosionGetDamageType() || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP) {
|
||||
isGrenade = true;
|
||||
}
|
||||
} else {
|
||||
|
@ -750,7 +775,12 @@ int _action_ranged(Attack* attack, int anim)
|
|||
|
||||
objectHide(projectile, NULL);
|
||||
|
||||
objectSetLight(projectile, 9, projectile->lightIntensity, NULL);
|
||||
// SFALL
|
||||
if (explosionEmitsLight() && projectile->lightIntensity == 0) {
|
||||
objectSetLight(projectile, projectileProto->item.lightDistance, projectileProto->item.lightIntensity, NULL);
|
||||
} else {
|
||||
objectSetLight(projectile, 9, projectile->lightIntensity, NULL);
|
||||
}
|
||||
|
||||
int projectileOrigin = _combat_bullet_start(attack->attacker, attack->defender);
|
||||
objectSetLocation(projectile, projectileOrigin, attack->attacker->elevation, NULL);
|
||||
|
@ -774,7 +804,8 @@ int _action_ranged(Attack* attack, int anim)
|
|||
v24 = attack->tile;
|
||||
}
|
||||
|
||||
if (isGrenade || damageType == DAMAGE_TYPE_EXPLOSION) {
|
||||
// SFALL
|
||||
if (isGrenade || damageType == explosionGetDamageType()) {
|
||||
if ((attack->attackerFlags & DAM_DROP) == 0) {
|
||||
int explosionFrmId;
|
||||
if (isGrenade) {
|
||||
|
@ -793,6 +824,12 @@ int _action_ranged(Attack* attack, int anim)
|
|||
explosionFrmId = 10;
|
||||
}
|
||||
|
||||
// SFALL
|
||||
int explosionFrmIdOverride = explosionGetFrm();
|
||||
if (explosionFrmIdOverride != -1) {
|
||||
explosionFrmId = explosionFrmIdOverride;
|
||||
}
|
||||
|
||||
if (isGrenade) {
|
||||
animationRegisterSetFid(projectile, weaponFid, -1);
|
||||
}
|
||||
|
@ -803,9 +840,23 @@ int _action_ranged(Attack* attack, int anim)
|
|||
const char* sfx = sfxBuildWeaponName(WEAPON_SOUND_EFFECT_HIT, weapon, attack->hitMode, attack->defender);
|
||||
animationRegisterPlaySoundEffect(projectile, sfx, 0);
|
||||
|
||||
animationRegisterAnimateAndHide(projectile, ANIM_STAND, 0);
|
||||
// SFALL
|
||||
if (explosionEmitsLight()) {
|
||||
animationRegisterAnimate(projectile, ANIM_STAND, 0);
|
||||
// 0xFFFF0008
|
||||
// - distance: 8
|
||||
// - intensity: 65535
|
||||
animationRegisterSetLightIntensity(projectile, 8, 65536, 0);
|
||||
} else {
|
||||
animationRegisterAnimateAndHide(projectile, ANIM_STAND, 0);
|
||||
}
|
||||
|
||||
for (int rotation = 0; rotation < ROTATION_COUNT; rotation++) {
|
||||
// SFALL
|
||||
int startRotation;
|
||||
int endRotation;
|
||||
explosionGetPattern(&startRotation, &endRotation);
|
||||
|
||||
for (int rotation = startRotation; rotation < endRotation; rotation++) {
|
||||
if (objectCreateWithFidPid(&(neighboors[rotation]), explosionFid, -1) != -1) {
|
||||
objectHide(neighboors[rotation], NULL);
|
||||
|
||||
|
@ -864,7 +915,8 @@ int _action_ranged(Attack* attack, int anim)
|
|||
}
|
||||
}
|
||||
|
||||
if (projectile != NULL && (isGrenade || damageType == DAMAGE_TYPE_EXPLOSION)) {
|
||||
// SFALL
|
||||
if (projectile != NULL && (isGrenade || damageType == explosionGetDamageType())) {
|
||||
animationRegisterHideObjectForced(projectile);
|
||||
} else if (anim == ANIM_THROW_ANIM && projectile != NULL) {
|
||||
animationRegisterSetFid(projectile, weaponFid, -1);
|
||||
|
|
|
@ -64,6 +64,10 @@ typedef enum AnimationKind {
|
|||
ANIM_KIND_26 = 26,
|
||||
ANIM_KIND_27 = 27,
|
||||
ANIM_KIND_NOOP = 28,
|
||||
|
||||
// New animation to update both light distance and intensity. Required to
|
||||
// impement Sfall's explosion light effects without resorting to hackery.
|
||||
ANIM_KIND_SET_LIGHT_INTENSITY,
|
||||
} AnimationKind;
|
||||
|
||||
typedef enum AnimationSequenceFlags {
|
||||
|
@ -197,6 +201,9 @@ typedef struct AnimationDescription {
|
|||
|
||||
// ANIM_KIND_CALLBACK3
|
||||
void* param3;
|
||||
|
||||
// ANIM_KIND_SET_LIGHT_INTENSITY
|
||||
int lightIntensity;
|
||||
};
|
||||
CacheEntry* artCacheKey;
|
||||
} AnimationDescription;
|
||||
|
@ -1527,6 +1534,11 @@ static int animationRunSequence(int animationSequenceIndex)
|
|||
tileWindowRefreshRect(&rect, animationDescription->owner->elevation);
|
||||
rc = _anim_set_continue(animationSequenceIndex, 0);
|
||||
break;
|
||||
case ANIM_KIND_SET_LIGHT_INTENSITY:
|
||||
objectSetLight(animationDescription->owner, animationDescription->lightDistance, animationDescription->lightIntensity, &rect);
|
||||
tileWindowRefreshRect(&rect, animationDescription->owner->elevation);
|
||||
rc = _anim_set_continue(animationSequenceIndex, 0);
|
||||
break;
|
||||
case ANIM_KIND_20:
|
||||
rc = _anim_move_on_stairs(animationDescription->owner, animationDescription->tile, animationDescription->elevation, animationDescription->anim, animationSequenceIndex);
|
||||
break;
|
||||
|
@ -3330,3 +3342,24 @@ static unsigned int animationComputeTicksPerFrame(Object* object, int fid)
|
|||
|
||||
return 1000 / fps;
|
||||
}
|
||||
|
||||
int animationRegisterSetLightIntensity(Object* owner, int lightDistance, int lightIntensity, int delay)
|
||||
{
|
||||
if (_check_registry(owner) == -1) {
|
||||
_anim_cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
AnimationSequence* animationSequence = &(gAnimationSequences[gAnimationSequenceCurrentIndex]);
|
||||
AnimationDescription* animationDescription = &(animationSequence->animations[gAnimationDescriptionCurrentIndex]);
|
||||
animationDescription->kind = ANIM_KIND_SET_LIGHT_INTENSITY;
|
||||
animationDescription->artCacheKey = NULL;
|
||||
animationDescription->owner = owner;
|
||||
animationDescription->lightDistance = lightDistance;
|
||||
animationDescription->lightIntensity = lightIntensity;
|
||||
animationDescription->delay = delay;
|
||||
|
||||
gAnimationDescriptionCurrentIndex++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -154,4 +154,6 @@ void _dude_stand(Object* obj, int rotation, int fid);
|
|||
void _dude_standup(Object* a1);
|
||||
void animationStop();
|
||||
|
||||
int animationRegisterSetLightIntensity(Object* owner, int lightDistance, int lightIntensity, int delay);
|
||||
|
||||
#endif /* ANIMATION_H */
|
||||
|
|
|
@ -3430,6 +3430,9 @@ int _combat_attack(Object* a1, Object* a2, int hitMode, int hitLocation)
|
|||
_critter_set_who_hit_me(a1, a2);
|
||||
}
|
||||
|
||||
// SFALL
|
||||
explosionSettingsReset();
|
||||
|
||||
_combat_call_display = 1;
|
||||
_combat_cleanup_enabled = 1;
|
||||
aiInfoSetLastTarget(a1, a2);
|
||||
|
@ -3707,7 +3710,8 @@ static int attackCompute(Attack* attack)
|
|||
|
||||
bool isGrenade = false;
|
||||
int damageType = weaponGetDamageType(attack->attacker, attack->weapon);
|
||||
if (anim == ANIM_THROW_ANIM && (damageType == DAMAGE_TYPE_EXPLOSION || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP)) {
|
||||
// SFALL
|
||||
if (anim == ANIM_THROW_ANIM && (damageType == explosionGetDamageType() || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP)) {
|
||||
isGrenade = true;
|
||||
}
|
||||
|
||||
|
@ -3835,7 +3839,8 @@ static int attackCompute(Attack* attack)
|
|||
}
|
||||
}
|
||||
|
||||
if ((damageType == DAMAGE_TYPE_EXPLOSION || isGrenade) && ((attack->attackerFlags & DAM_HIT) != 0 || (attack->attackerFlags & DAM_CRITICAL) == 0)) {
|
||||
// SFALL
|
||||
if ((damageType == explosionGetDamageType() || isGrenade) && ((attack->attackerFlags & DAM_HIT) != 0 || (attack->attackerFlags & DAM_CRITICAL) == 0)) {
|
||||
_compute_explosion_on_extras(attack, 0, isGrenade, 0);
|
||||
} else {
|
||||
if ((attack->attackerFlags & DAM_EXPLODE) != 0) {
|
||||
|
@ -3882,7 +3887,10 @@ void _compute_explosion_on_extras(Attack* attack, int a2, bool isGrenade, int a4
|
|||
int rotation = 0;
|
||||
int v5 = -1;
|
||||
int v19 = tile;
|
||||
while (attack->extrasLength < 6) {
|
||||
|
||||
// SFALL
|
||||
int maxTargets = explosionGetMaxTargets();
|
||||
while (attack->extrasLength < maxTargets) {
|
||||
if (v22 != 0 && (v5 == -1 || (v5 = tileGetTileInDirection(v5, rotation, 1)) != v19)) {
|
||||
v20++;
|
||||
if (v20 % v22 == 0) {
|
||||
|
|
|
@ -1399,7 +1399,10 @@ char* sfxBuildWeaponName(int effectType, Object* weapon, int hitMode, Object* ta
|
|||
v6 = 1;
|
||||
}
|
||||
|
||||
if (effectTypeCode != 'H' || target == NULL || weaponIsGrenade(weapon)) {
|
||||
int damageType = weaponGetDamageType(NULL, weapon);
|
||||
|
||||
// SFALL
|
||||
if (effectTypeCode != 'H' || target == NULL || damageType == explosionGetDamageType() || damageType == DAMAGE_TYPE_PLASMA || damageType == DAMAGE_TYPE_EMP) {
|
||||
materialCode = 'X';
|
||||
} else {
|
||||
const int type = FID_TYPE(target->fid);
|
||||
|
|
|
@ -3277,7 +3277,7 @@ static void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType)
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (item->pid == PROTO_ID_DYNAMITE_II || item->pid == PROTO_ID_PLASTIC_EXPLOSIVES_II) {
|
||||
} else if (explosiveIsActiveExplosive(item->pid)) {
|
||||
_dropped_explosive = 1;
|
||||
_obj_drop(v41, item);
|
||||
} else {
|
||||
|
|
263
src/item.cc
263
src/item.cc
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#define ADDICTION_COUNT (9)
|
||||
|
@ -62,6 +63,10 @@ static void booksInitCustom();
|
|||
static void booksAdd(int bookPid, int messageId, int skill);
|
||||
static void booksExit();
|
||||
|
||||
static void explosionsInit();
|
||||
static void explosionsReset();
|
||||
static void explosionsExit();
|
||||
|
||||
typedef struct DrugDescription {
|
||||
int drugPid;
|
||||
int gvar;
|
||||
|
@ -74,6 +79,13 @@ typedef struct BookDescription {
|
|||
int skill;
|
||||
} BookDescription;
|
||||
|
||||
typedef struct ExplosiveDescription {
|
||||
int pid;
|
||||
int activePid;
|
||||
int minDamage;
|
||||
int maxDamage;
|
||||
} ExplosiveDescription;
|
||||
|
||||
// 0x509FFC
|
||||
static char _aItem_1[] = "<item>";
|
||||
|
||||
|
@ -153,6 +165,20 @@ static Object* _wd_obj;
|
|||
static int _wd_gvar;
|
||||
|
||||
static std::vector<BookDescription> gBooks;
|
||||
static bool gExplosionEmitsLight;
|
||||
static int gGrenadeExplosionRadius;
|
||||
static int gRocketExplosionRadius;
|
||||
static int gDynamiteMinDamage;
|
||||
static int gDynamiteMaxDamage;
|
||||
static int gPlasticExplosiveMinDamage;
|
||||
static int gPlasticExplosiveMaxDamage;
|
||||
static std::vector<ExplosiveDescription> gExplosives;
|
||||
static int gExplosionStartRotation;
|
||||
static int gExplosionEndRotation;
|
||||
static int gExplosionFrm;
|
||||
static int gExplosionRadius;
|
||||
static int gExplosionDamageType;
|
||||
static int gExplosionMaxTargets;
|
||||
|
||||
// 0x4770E0
|
||||
int itemsInit()
|
||||
|
@ -170,6 +196,7 @@ int itemsInit()
|
|||
|
||||
// SFALL
|
||||
booksInit();
|
||||
explosionsInit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -177,7 +204,8 @@ int itemsInit()
|
|||
// 0x477144
|
||||
void itemsReset()
|
||||
{
|
||||
return;
|
||||
// SFALL
|
||||
explosionsReset();
|
||||
}
|
||||
|
||||
// 0x477148
|
||||
|
@ -187,6 +215,7 @@ void itemsExit()
|
|||
|
||||
// SFALL
|
||||
booksExit();
|
||||
explosionsExit();
|
||||
}
|
||||
|
||||
// NOTE: Collapsed.
|
||||
|
@ -2002,13 +2031,23 @@ int _item_w_area_damage_radius(Object* weapon, int hitMode)
|
|||
// 0x479180
|
||||
int _item_w_grenade_dmg_radius(Object* weapon)
|
||||
{
|
||||
return 2;
|
||||
// SFALL
|
||||
if (gExplosionRadius != -1) {
|
||||
return gExplosionRadius;
|
||||
}
|
||||
|
||||
return gGrenadeExplosionRadius;
|
||||
}
|
||||
|
||||
// 0x479188
|
||||
int _item_w_rocket_dmg_radius(Object* weapon)
|
||||
{
|
||||
return 3;
|
||||
// SFALL
|
||||
if (gExplosionRadius != -1) {
|
||||
return gExplosionRadius;
|
||||
}
|
||||
|
||||
return gRocketExplosionRadius;
|
||||
}
|
||||
|
||||
// 0x479190
|
||||
|
@ -3353,3 +3392,221 @@ bool booksGetInfo(int bookPid, int* messageIdPtr, int* skillPtr)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void explosionsInit()
|
||||
{
|
||||
gExplosionEmitsLight = false;
|
||||
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_EXPLOSION_EMITS_LIGHT_KEY, &gExplosionEmitsLight);
|
||||
|
||||
explosionsReset();
|
||||
}
|
||||
|
||||
static void explosionsReset()
|
||||
{
|
||||
gGrenadeExplosionRadius = 2;
|
||||
gRocketExplosionRadius = 3;
|
||||
|
||||
gDynamiteMinDamage = 30;
|
||||
gDynamiteMaxDamage = 50;
|
||||
gPlasticExplosiveMinDamage = 40;
|
||||
gPlasticExplosiveMaxDamage = 80;
|
||||
|
||||
if (configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DYNAMITE_MAX_DAMAGE_KEY, &gDynamiteMaxDamage)) {
|
||||
gDynamiteMaxDamage = std::clamp(gDynamiteMaxDamage, 0, 9999);
|
||||
}
|
||||
|
||||
if (configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DYNAMITE_MIN_DAMAGE_KEY, &gDynamiteMinDamage)) {
|
||||
gDynamiteMinDamage = std::clamp(gDynamiteMinDamage, 0, gDynamiteMaxDamage);
|
||||
}
|
||||
|
||||
if (configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_PLASTIC_EXPLOSIVE_MAX_DAMAGE_KEY, &gPlasticExplosiveMaxDamage)) {
|
||||
gPlasticExplosiveMaxDamage = std::clamp(gPlasticExplosiveMaxDamage, 0, 9999);
|
||||
}
|
||||
|
||||
if (configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_PLASTIC_EXPLOSIVE_MIN_DAMAGE_KEY, &gPlasticExplosiveMinDamage)) {
|
||||
gPlasticExplosiveMinDamage = std::clamp(gPlasticExplosiveMinDamage, 0, gPlasticExplosiveMaxDamage);
|
||||
}
|
||||
|
||||
gExplosives.clear();
|
||||
|
||||
explosionSettingsReset();
|
||||
}
|
||||
|
||||
static void explosionsExit()
|
||||
{
|
||||
gExplosives.clear();
|
||||
}
|
||||
|
||||
bool explosionEmitsLight()
|
||||
{
|
||||
return gExplosionEmitsLight;
|
||||
}
|
||||
|
||||
void weaponSetGrenadeExplosionRadius(int value)
|
||||
{
|
||||
gGrenadeExplosionRadius = value;
|
||||
}
|
||||
|
||||
void weaponSetRocketExplosionRadius(int value)
|
||||
{
|
||||
gRocketExplosionRadius = value;
|
||||
}
|
||||
|
||||
void explosiveAdd(int pid, int activePid, int minDamage, int maxDamage)
|
||||
{
|
||||
ExplosiveDescription explosiveDescription;
|
||||
explosiveDescription.pid = pid;
|
||||
explosiveDescription.activePid = activePid;
|
||||
explosiveDescription.minDamage = minDamage;
|
||||
explosiveDescription.maxDamage = maxDamage;
|
||||
gExplosives.push_back(std::move(explosiveDescription));
|
||||
}
|
||||
|
||||
bool explosiveIsExplosive(int pid)
|
||||
{
|
||||
if (pid == PROTO_ID_DYNAMITE_I) return true;
|
||||
if (pid == PROTO_ID_PLASTIC_EXPLOSIVES_I) return true;
|
||||
|
||||
for (const auto& explosive : gExplosives) {
|
||||
if (explosive.pid == pid) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool explosiveIsActiveExplosive(int pid)
|
||||
{
|
||||
if (pid == PROTO_ID_DYNAMITE_II) return true;
|
||||
if (pid == PROTO_ID_PLASTIC_EXPLOSIVES_II) return true;
|
||||
|
||||
for (const auto& explosive : gExplosives) {
|
||||
if (explosive.activePid == pid) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool explosiveActivate(int* pidPtr)
|
||||
{
|
||||
if (*pidPtr == PROTO_ID_DYNAMITE_I) {
|
||||
*pidPtr = PROTO_ID_DYNAMITE_II;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*pidPtr == PROTO_ID_PLASTIC_EXPLOSIVES_I) {
|
||||
*pidPtr = PROTO_ID_PLASTIC_EXPLOSIVES_II;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& explosive : gExplosives) {
|
||||
if (explosive.pid == *pidPtr) {
|
||||
*pidPtr = explosive.activePid;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool explosiveSetDamage(int pid, int minDamage, int maxDamage)
|
||||
{
|
||||
if (pid == PROTO_ID_DYNAMITE_I) {
|
||||
gDynamiteMinDamage = minDamage;
|
||||
gDynamiteMaxDamage = maxDamage;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pid == PROTO_ID_PLASTIC_EXPLOSIVES_I) {
|
||||
gPlasticExplosiveMinDamage = minDamage;
|
||||
gPlasticExplosiveMaxDamage = maxDamage;
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: For unknown reason this function do not update custom explosives
|
||||
// damage. Since we're after compatibility (at least at this time), the
|
||||
// only way to follow this behaviour.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool explosiveGetDamage(int pid, int* minDamagePtr, int* maxDamagePtr)
|
||||
{
|
||||
if (pid == PROTO_ID_DYNAMITE_I) {
|
||||
*minDamagePtr = gDynamiteMinDamage;
|
||||
*maxDamagePtr = gDynamiteMaxDamage;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pid == PROTO_ID_PLASTIC_EXPLOSIVES_I) {
|
||||
*minDamagePtr = gPlasticExplosiveMinDamage;
|
||||
*maxDamagePtr = gPlasticExplosiveMaxDamage;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& explosive : gExplosives) {
|
||||
if (explosive.pid == pid) {
|
||||
*minDamagePtr = explosive.minDamage;
|
||||
*maxDamagePtr = explosive.maxDamage;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void explosionSettingsReset()
|
||||
{
|
||||
gExplosionStartRotation = 0;
|
||||
gExplosionEndRotation = ROTATION_COUNT;
|
||||
gExplosionFrm = -1;
|
||||
gExplosionRadius = -1;
|
||||
gExplosionDamageType = DAMAGE_TYPE_EXPLOSION;
|
||||
gExplosionMaxTargets = 6;
|
||||
}
|
||||
|
||||
void explosionGetPattern(int* startRotationPtr, int* endRotationPtr)
|
||||
{
|
||||
*startRotationPtr = gExplosionStartRotation;
|
||||
*endRotationPtr = gExplosionEndRotation;
|
||||
}
|
||||
|
||||
void explosionSetPattern(int startRotation, int endRotation)
|
||||
{
|
||||
gExplosionStartRotation = startRotation;
|
||||
gExplosionEndRotation = endRotation;
|
||||
}
|
||||
|
||||
int explosionGetFrm()
|
||||
{
|
||||
return gExplosionFrm;
|
||||
}
|
||||
|
||||
void explosionSetFrm(int frm)
|
||||
{
|
||||
gExplosionFrm = frm;
|
||||
}
|
||||
|
||||
void explosionSetRadius(int radius)
|
||||
{
|
||||
gExplosionRadius = radius;
|
||||
}
|
||||
|
||||
int explosionGetDamageType()
|
||||
{
|
||||
return gExplosionDamageType;
|
||||
}
|
||||
|
||||
void explosionSetDamageType(int damageType)
|
||||
{
|
||||
gExplosionDamageType = damageType;
|
||||
}
|
||||
|
||||
int explosionGetMaxTargets()
|
||||
{
|
||||
return gExplosionMaxTargets;
|
||||
}
|
||||
|
||||
void explosionSetMaxTargets(int maxTargets)
|
||||
{
|
||||
gExplosionMaxTargets = maxTargets;
|
||||
}
|
||||
|
|
19
src/item.h
19
src/item.h
|
@ -124,5 +124,24 @@ int itemGetMoney(Object* obj);
|
|||
int itemSetMoney(Object* obj, int a2);
|
||||
|
||||
bool booksGetInfo(int bookPid, int* messageIdPtr, int* skillPtr);
|
||||
bool explosionEmitsLight();
|
||||
void weaponSetGrenadeExplosionRadius(int value);
|
||||
void weaponSetRocketExplosionRadius(int value);
|
||||
void explosiveAdd(int pid, int activePid, int minDamage, int maxDamage);
|
||||
bool explosiveIsExplosive(int pid);
|
||||
bool explosiveIsActiveExplosive(int pid);
|
||||
bool explosiveActivate(int* pidPtr);
|
||||
bool explosiveSetDamage(int pid, int minDamage, int maxDamage);
|
||||
bool explosiveGetDamage(int pid, int* minDamagePtr, int* maxDamagePtr);
|
||||
void explosionSettingsReset();
|
||||
void explosionGetPattern(int* startRotationPtr, int* endRotationPtr);
|
||||
void explosionSetPattern(int startRotation, int endRotation);
|
||||
int explosionGetFrm();
|
||||
void explosionSetFrm(int frm);
|
||||
void explosionSetRadius(int radius);
|
||||
int explosionGetDamageType();
|
||||
void explosionSetDamageType(int damageType);
|
||||
int explosionGetMaxTargets();
|
||||
void explosionSetMaxTargets(int maxTargets);
|
||||
|
||||
#endif /* ITEM_H */
|
||||
|
|
|
@ -2090,7 +2090,8 @@ int _obj_inven_free(Inventory* inventory)
|
|||
bool _obj_action_can_use(Object* obj)
|
||||
{
|
||||
int pid = obj->pid;
|
||||
if (pid != PROTO_ID_LIT_FLARE && pid != PROTO_ID_DYNAMITE_II && pid != PROTO_ID_PLASTIC_EXPLOSIVES_II) {
|
||||
// SFALL
|
||||
if (pid != PROTO_ID_LIT_FLARE && !explosiveIsActiveExplosive(pid)) {
|
||||
return _proto_action_can_use(pid);
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -843,10 +843,8 @@ static int _obj_use_explosive(Object* explosive)
|
|||
MessageListItem messageListItem;
|
||||
|
||||
int pid = explosive->pid;
|
||||
if (pid != PROTO_ID_DYNAMITE_I
|
||||
&& pid != PROTO_ID_PLASTIC_EXPLOSIVES_I
|
||||
&& pid != PROTO_ID_DYNAMITE_II
|
||||
&& pid != PROTO_ID_PLASTIC_EXPLOSIVES_II) {
|
||||
// SFALL
|
||||
if (!explosiveIsExplosive(pid)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -865,11 +863,8 @@ static int _obj_use_explosive(Object* explosive)
|
|||
displayMonitorAddMessage(messageListItem.text);
|
||||
}
|
||||
|
||||
if (pid == PROTO_ID_DYNAMITE_I) {
|
||||
explosive->pid = PROTO_ID_DYNAMITE_II;
|
||||
} else if (pid == PROTO_ID_PLASTIC_EXPLOSIVES_I) {
|
||||
explosive->pid = PROTO_ID_PLASTIC_EXPLOSIVES_II;
|
||||
}
|
||||
// SFALL
|
||||
explosiveActivate(&(explosive->pid));
|
||||
|
||||
int delay = 10 * seconds;
|
||||
|
||||
|
@ -1048,7 +1043,8 @@ int _protinst_use_item(Object* critter, Object* item)
|
|||
// 0x49BFE8
|
||||
static int _protinstTestDroppedExplosive(Object* a1)
|
||||
{
|
||||
if (a1->pid == PROTO_ID_DYNAMITE_II || a1->pid == PROTO_ID_PLASTIC_EXPLOSIVES_II) {
|
||||
// SFALL
|
||||
if (explosiveIsActiveExplosive(a1->pid)) {
|
||||
Attack attack;
|
||||
attackInit(&attack, gDude, 0, HIT_MODE_PUNCH, HIT_LOCATION_TORSO);
|
||||
attack.attackerFlags = DAM_HIT;
|
||||
|
|
12
src/queue.cc
12
src/queue.cc
|
@ -478,15 +478,9 @@ static int _queue_do_explosion_(Object* explosive, bool a2)
|
|||
|
||||
int maxDamage;
|
||||
int minDamage;
|
||||
if (explosive->pid == PROTO_ID_DYNAMITE_I || explosive->pid == PROTO_ID_DYNAMITE_II) {
|
||||
// Dynamite
|
||||
minDamage = 30;
|
||||
maxDamage = 50;
|
||||
} else {
|
||||
// Plastic explosive
|
||||
minDamage = 40;
|
||||
maxDamage = 80;
|
||||
}
|
||||
|
||||
// SFALL
|
||||
explosiveGetDamage(explosive->pid, &minDamage, &maxDamage);
|
||||
|
||||
// FIXME: I guess this is a little bit wrong, dude can never be null, I
|
||||
// guess it needs to check if owner is dude.
|
||||
|
|
|
@ -35,6 +35,11 @@
|
|||
#define SFALL_CONFIG_BURST_MOD_CENTER_DIVISOR_KEY "ComputeSpray_CenterDiv"
|
||||
#define SFALL_CONFIG_BURST_MOD_TARGET_MULTIPLIER_KEY "ComputeSpray_TargetMult"
|
||||
#define SFALL_CONFIG_BURST_MOD_TARGET_DIVISOR_KEY "ComputeSpray_TargetDiv"
|
||||
#define SFALL_CONFIG_DYNAMITE_MIN_DAMAGE_KEY "Dynamite_DmgMin"
|
||||
#define SFALL_CONFIG_DYNAMITE_MAX_DAMAGE_KEY "Dynamite_DmgMax"
|
||||
#define SFALL_CONFIG_PLASTIC_EXPLOSIVE_MIN_DAMAGE_KEY "PlasticExplosive_DmgMin"
|
||||
#define SFALL_CONFIG_PLASTIC_EXPLOSIVE_MAX_DAMAGE_KEY "PlasticExplosive_DmgMax"
|
||||
#define SFALL_CONFIG_EXPLOSION_EMITS_LIGHT_KEY "ExplosionsEmitLight"
|
||||
|
||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_MULTIPLIER 1
|
||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISOR 3
|
||||
|
|
Loading…
Reference in New Issue