Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions TheForceEngine/TFE_DarkForces/Actor/actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,14 @@ namespace TFE_DarkForces
attackMod->meleeDmg = 0;
attackMod->meleeRate = FIXED(230);
attackMod->attackFlags = ATTFLAG_RANGED | ATTFLAG_LIT_RNG;

// new to TFE - burstfire
attackMod->hasBurstFire = JFALSE;
attackMod->burstFire.burstNumber = 5;
attackMod->burstFire.variation = 2;
attackMod->burstFire.interval = 29;
attackMod->burstFire.shotCount = 5;
attackMod->burstFire.lastShot = 0;

// Why is this being returned? This function maybe should be a void?
return attackMod->fireOffset.y;
Expand All @@ -318,6 +326,8 @@ namespace TFE_DarkForces
moveMod->collisionFlags |= ACTORCOL_GRAVITY;
// Added to disable auto-aim when dying.
logic->logic.obj->flags &= ~OBJ_FLAG_AIM;

logic->flags |= ACTOR_DYING; // added to stop burst fire when actor is dying
}

// Returns JTRUE if the object is on the floor, or JFALSE is not on the floor or moving too fast.
Expand Down Expand Up @@ -987,6 +997,11 @@ namespace TFE_DarkForces
// Do ranged attack (primary)
attackMod->anim.state = STATE_ATTACK1;
attackMod->timing.delay = attackMod->timing.rangedDelay;

if (attackMod->hasBurstFire)
{
attackMod->anim.flags &= ~AFLAG_PLAYONCE; // if logic has burst fire, allow attack anim to loop
}
}

if (obj->type == OBJ_TYPE_SPRITE)
Expand Down Expand Up @@ -1020,7 +1035,7 @@ namespace TFE_DarkForces
} break;
case STATE_ATTACK1:
{
if (!(attackMod->anim.flags & AFLAG_READY))
if (!(attackMod->anim.flags & AFLAG_READY) && !attackMod->hasBurstFire)
{
break;
}
Expand Down Expand Up @@ -1049,7 +1064,42 @@ namespace TFE_DarkForces
obj->flags |= OBJ_FLAG_FULLBRIGHT;
}

attackMod->anim.state = STATE_ANIMATE1;
// Burst fire option - set via custom logics
if (attackMod->hasBurstFire)
{
if (s_curTick < attackMod->burstFire.lastShot + attackMod->burstFire.interval)
{
break;
}

if (logic->flags & ACTOR_DYING) { break; }

if (attackMod->burstFire.shotCount <= 1)
{
// Burst is finished, end the looping & reset the shot count
attackMod->anim.state = STATE_ANIMATE1;
attackMod->anim.flags |= AFLAG_PLAYONCE;

s32 var = random(attackMod->burstFire.variation * 2);
s32 nextBurstNumber = attackMod->burstFire.burstNumber - attackMod->burstFire.variation + var;
attackMod->burstFire.shotCount = max(nextBurstNumber, 2);
}
else
{
// Reorient towards the player
attackMod->target.yaw = vec2ToAngle(s_playerObject->posWS.x - obj->posWS.x, s_playerObject->posWS.z - obj->posWS.z);

// Fire the next shot in the burst
attackMod->burstFire.lastShot = s_curTick;
attackMod->burstFire.shotCount--;
}
}
else
{
// No burst fire -- vanilla logic
attackMod->anim.state = STATE_ANIMATE1;
}

vec3_fixed fireOffset = {};

// Calculate the X,Z fire offsets based on where the enemy is facing. It doesn't matter for Y.
Expand Down
3 changes: 3 additions & 0 deletions TheForceEngine/TFE_DarkForces/Actor/actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ enum ActorDispatchFlags
ACTOR_PLAYER_VISIBLE = FLAG_BIT(3),
ACTOR_OFFIC_ALERT = FLAG_BIT(4), // use officer alert sounds
ACTOR_TROOP_ALERT = FLAG_BIT(5), // use stormtrooper alert sounds

// Added for TFE
ACTOR_DYING = FLAG_BIT(6),
};

// Forward Declarations.
Expand Down
13 changes: 13 additions & 0 deletions TheForceEngine/TFE_DarkForces/Actor/actorModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ struct ActorTarget
u32 flags;
};

struct ActorBurstFire
{
u32 burstNumber;
u32 variation;
Tick interval;
Tick lastShot;
s32 shotCount;
};

struct AttackModule
{
ActorModule header;
Expand All @@ -162,6 +171,10 @@ struct AttackModule
fixed16_16 meleeDmg;
fixed16_16 meleeRate;
u32 attackFlags; // see AttackFlags above.

// New in TFE - Burst fire properties
JBool hasBurstFire;
ActorBurstFire burstFire;
};

struct MovementModule
Expand Down
7 changes: 7 additions & 0 deletions TheForceEngine/TFE_DarkForces/Actor/actorSerialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,13 @@ namespace TFE_DarkForces
SERIALIZE(SaveVersionInit, attackMod->meleeDmg, 0);
SERIALIZE(SaveVersionInit, attackMod->meleeRate, 0);
SERIALIZE(SaveVersionInit, attackMod->attackFlags, 0);

SERIALIZE(ObjState_BurstFire, attackMod->hasBurstFire, JFALSE);
SERIALIZE(ObjState_BurstFire, attackMod->burstFire.burstNumber, 5);
SERIALIZE(ObjState_BurstFire, attackMod->burstFire.variation, 2);
SERIALIZE(ObjState_BurstFire, attackMod->burstFire.interval, 29);
SERIALIZE(ObjState_BurstFire, attackMod->burstFire.shotCount, 5);
SERIALIZE(ObjState_BurstFire, attackMod->burstFire.lastShot, 0);
}

void actor_serializeAttackModule(Stream* stream, ActorModule*& mod, ActorDispatch* dispatch)
Expand Down
2 changes: 1 addition & 1 deletion TheForceEngine/TFE_DarkForces/Actor/animTables.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace TFE_DarkForces
{
enum
enum ActorAnimation
{
ANIM_MOVE = 0,
ANIM_ATTACK1 = 1,
Expand Down
7 changes: 7 additions & 0 deletions TheForceEngine/TFE_DarkForces/Actor/enemies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,13 @@ namespace TFE_DarkForces
attackMod->fireOffset.x = floatToFixed16(cust->fireOffset.x);
attackMod->fireOffset.y = cust->fireOffset.y < -999 ? attackMod->fireOffset.y : floatToFixed16(cust->fireOffset.y); // if -1000 use the default value
attackMod->fireOffset.z = floatToFixed16(cust->fireOffset.z);

attackMod->hasBurstFire = cust->hasBurstFire ? JTRUE : JFALSE;
attackMod->burstFire.burstNumber = cust->burstNumber;
attackMod->burstFire.shotCount = cust->burstNumber;
attackMod->burstFire.variation = cust->burstVariation;
attackMod->burstFire.interval = cust->burstInterval;

s_actorState.attackMod = attackMod;
actor_addModule(dispatch, (ActorModule*)attackMod);

Expand Down
24 changes: 24 additions & 0 deletions TheForceEngine/TFE_ExternalData/dfLogics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,30 @@ namespace TFE_ExternalData
return true;
}

if (cJSON_IsBool(data) && strcasecmp(data->string, "hasBurstFire") == 0)
{
customLogic.hasBurstFire = cJSON_IsTrue(data);
return true;
}

if (cJSON_IsNumber(data) && strcasecmp(data->string, "burstNumber") == 0)
{
customLogic.burstNumber = data->valueint;
return true;
}

if (cJSON_IsNumber(data) && strcasecmp(data->string, "burstVariation") == 0)
{
customLogic.burstVariation = data->valueint;
return true;
}

if (cJSON_IsNumber(data) && strcasecmp(data->string, "burstInterval") == 0)
{
customLogic.burstInterval = (u32)(data->valuedouble * TICKS_PER_SECOND);
return true;
}

// When it comes to offsets these are considered from the perspective of the actor.
//
// Projectile spawn details guide.
Expand Down
6 changes: 6 additions & 0 deletions TheForceEngine/TFE_ExternalData/dfLogics.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ namespace TFE_ExternalData
u32 fireSpread = 30;
vec3_float fireOffset = { 0, -1000, 0 }; // (y = -1000) will be treated as default

// burst fire
bool hasBurstFire = false;
u32 burstNumber = 5;
u32 burstVariation = 2;
u32 burstInterval = 29;

// Thinker and movement
u32 speed = 4;
u32 verticalSpeed = 10;
Expand Down
3 changes: 2 additions & 1 deletion TheForceEngine/TFE_Jedi/Level/robjData.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ enum ObjStateVersion : u32
ObjState_RefList = 9,
ObjState_ExternalCamera = 10,
ObjState_LogicScriptCallV1 = 11, // adds ScriptCalls on pickup, death, alert
ObjState_CurVersion = ObjState_LogicScriptCallV1,
ObjState_BurstFire = 12,
ObjState_CurVersion = ObjState_BurstFire,
};

// TFE Scripting
Expand Down