- scriptified most of a_strifestuff.cpp.

This commit is contained in:
Christoph Oelckers 2016-11-28 23:30:14 +01:00
parent caef5344b0
commit edd8e51a69
15 changed files with 376 additions and 383 deletions

View File

@ -66,70 +66,6 @@ int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int
return health;
}
// Klaxon Warning Light -----------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_TurretLook)
{
PARAM_SELF_PROLOGUE(AActor);
AActor *target;
if (self->flags5 & MF5_INCONVERSATION)
return 0;
self->threshold = 0;
target = self->LastHeard;
if (target != NULL &&
target->health > 0 &&
target->flags & MF_SHOOTABLE &&
(self->flags & MF_FRIENDLY) != (target->flags & MF_FRIENDLY))
{
self->target = target;
if ((self->flags & MF_AMBUSH) && !P_CheckSight (self, target))
{
return 0;
}
if (self->SeeSound != 0)
{
S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM);
}
self->LastHeard = NULL;
self->threshold = 10;
self->SetState (self->SeeState);
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_KlaxonBlare)
{
PARAM_SELF_PROLOGUE(AActor);
if (--self->reactiontime < 0)
{
self->target = NULL;
self->reactiontime = self->GetDefault()->reactiontime;
CALL_ACTION(A_TurretLook, self);
if (self->target == NULL)
{
self->SetIdle();
}
else
{
self->reactiontime = 50;
}
}
if (self->reactiontime == 2)
{
// [RH] Unalert monsters near the alarm and not just those in the same sector as it.
P_NoiseAlert (NULL, self, false);
}
else if (self->reactiontime > 50)
{
S_Sound (self, CHAN_VOICE, "misc/alarm", 1, ATTN_NORM);
}
return 0;
}
// Power Coupling -----------------------------------------------------------
class APowerCoupling : public AActor
@ -183,185 +119,3 @@ public:
IMPLEMENT_CLASS(AMeat, false, false)
//==========================================================================
//
// A_TossGib
//
//==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_TossGib)
{
PARAM_SELF_PROLOGUE(AActor);
const char *gibtype = (self->flags & MF_NOBLOOD) ? "Junk" : "Meat";
AActor *gib = Spawn (gibtype, self->PosPlusZ(24.), ALLOW_REPLACE);
if (gib == NULL)
{
return 0;
}
gib->Angles.Yaw = pr_gibtosser() * (360 / 256.f);
gib->VelFromAngle(pr_gibtosser() & 15);
gib->Vel.Z = pr_gibtosser() & 15;
return 0;
}
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_FLoopActiveSound)
{
PARAM_SELF_PROLOGUE(AActor);
if (self->ActiveSound != 0 && !(level.time & 7))
{
S_Sound (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM);
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_Countdown)
{
PARAM_SELF_PROLOGUE(AActor);
if (--self->reactiontime <= 0)
{
P_ExplodeMissile (self, NULL, NULL);
self->flags &= ~MF_SKULLFLY;
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_LoopActiveSound)
{
PARAM_SELF_PROLOGUE(AActor);
if (self->ActiveSound != 0 && !S_IsActorPlayingSomething (self, CHAN_VOICE, -1))
{
S_Sound (self, CHAN_VOICE|CHAN_LOOP, self->ActiveSound, 1, ATTN_NORM);
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
{
PARAM_SELF_PROLOGUE(AActor);
sector_t *sec = self->Sector;
if (self->Z() == sec->floorplane.ZatPoint(self) && sec->PortalBlocksMovement(sector_t::floor))
{
if (sec->special == Damage_InstantDeath)
{
P_DamageMobj (self, NULL, NULL, 999, NAME_InstantDeath);
}
else if (sec->special == Scroll_StrifeCurrent)
{
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
double speed = (anglespeed % 10) / 16.;
DAngle an = (anglespeed / 10) * (360 / 8.);
self->Thrust(an, speed);
}
}
return 0;
}
//============================================================================
//
// A_ClearSoundTarget
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_ClearSoundTarget)
{
PARAM_SELF_PROLOGUE(AActor);
AActor *actor;
self->Sector->SoundTarget = NULL;
for (actor = self->Sector->thinglist; actor != NULL; actor = actor->snext)
{
actor->LastHeard = NULL;
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_ItBurnsItBurns)
{
PARAM_SELF_PROLOGUE(AActor);
S_Sound (self, CHAN_VOICE, "human/imonfire", 1, ATTN_NORM);
if (self->player != nullptr && self->player->mo == self)
{
P_SetPsprite(self->player, PSP_STRIFEHANDS, self->FindState("FireHands"));
self->player->ReadyWeapon = nullptr;
self->player->PendingWeapon = WP_NOCHANGE;
self->player->playerstate = PST_LIVE;
self->player->extralight = 3;
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_DropFire)
{
PARAM_SELF_PROLOGUE(AActor);
AActor *drop = Spawn("FireDroplet", self->PosPlusZ(24.), ALLOW_REPLACE);
drop->Vel.Z = -1.;
P_RadiusAttack (self, self, 64, 64, NAME_Fire, 0);
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_CrispyPlayer)
{
PARAM_SELF_PROLOGUE(AActor);
if (self->player != nullptr && self->player->mo == self)
{
DPSprite *psp;
psp = self->player->GetPSprite(PSP_STRIFEHANDS);
FState *firehandslower = self->FindState("FireHandsLower");
FState *firehands = self->FindState("FireHands");
FState *state = psp->GetState();
if (state != nullptr && firehandslower != nullptr && firehands != nullptr && firehands < firehandslower)
{
self->player->playerstate = PST_DEAD;
psp->SetState(state + (firehandslower - firehands));
}
else if (state == nullptr)
{
psp->SetState(nullptr);
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, A_HandLower)
{
PARAM_SELF_PROLOGUE(AActor);
if (self->player != nullptr)
{
DPSprite *psp = self->player->GetPSprite(PSP_STRIFEHANDS);
if (psp->GetState() == nullptr)
{
psp->SetState(nullptr);
return 0;
}
psp->y += 9;
if (psp->y > WEAPONBOTTOM*2)
{
psp->SetState(nullptr);
}
if (self->player->extralight > 0) self->player->extralight--;
}
return 0;
}

View File

@ -6807,3 +6807,32 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetTranslation)
self->SetTranslation(trname);
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
{
PARAM_SELF_PROLOGUE(AActor);
sector_t *sec = self->Sector;
if (self->Z() == sec->floorplane.ZatPoint(self) && sec->PortalBlocksMovement(sector_t::floor))
{
if (sec->special == Damage_InstantDeath)
{
P_DamageMobj(self, NULL, NULL, 999, NAME_InstantDeath);
}
else if (sec->special == Scroll_StrifeCurrent)
{
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
double speed = (anglespeed % 10) / 16.;
DAngle an = (anglespeed / 10) * (360 / 8.);
self->Thrust(an, speed);
}
}
return 0;
}

View File

@ -265,10 +265,11 @@ void P_NoiseAlert (AActor *target, AActor *emitter, bool splash, double maxdist)
DEFINE_ACTION_FUNCTION(AActor, NoiseAlert)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT(emitter, AActor);
PARAM_OBJECT(target, AActor);
PARAM_BOOL_DEF(splash);
PARAM_FLOAT_DEF(maxdist);
P_NoiseAlert(self, emitter, splash, maxdist);
// Note that the emitter is self, not the target of the alert! Target can be NULL.
P_NoiseAlert(target, self, splash, maxdist);
return 0;
}

View File

@ -1078,3 +1078,16 @@ DEFINE_FIELD_BIT(FState, StateFlags, bNoDelay, STF_NODELAY)
DEFINE_FIELD_BIT(FState, StateFlags, bSameFrame, STF_SAMEFRAME)
DEFINE_FIELD_BIT(FState, StateFlags, bCanRaise, STF_CANRAISE)
DEFINE_FIELD_BIT(FState, StateFlags, bDehacked, STF_DEHACKED)
DEFINE_ACTION_FUNCTION(FState, DistanceTo)
{
PARAM_SELF_STRUCT_PROLOGUE(FState);
PARAM_POINTER(other, FState);
// Safely calculate the distance between two states.
auto o1 = FState::StaticFindStateOwner(self);
int retv;
if (other < o1->OwnedStates || other >= o1->OwnedStates + o1->NumOwnedStates) retv = INT_MIN;
else retv = int(other - self);
ACTION_RETURN_INT(retv);
}

View File

@ -743,6 +743,12 @@ void InitThingdef()
playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame);
GlobalSymbols.AddSymbol(playerf);
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
// is to create a static variable from it and reference that in the script. Yuck!!!
static AWeapon *wpnochg = WP_NOCHANGE;
playerf = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg);
GlobalSymbols.AddSymbol(playerf);
// this needs to be done manually until it can be given a proper type.
RUNTIME_CLASS(AActor)->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, DecalGenerator));

View File

@ -166,6 +166,7 @@ zscript/strife/coin.txt
zscript/strife/crusader.txt
zscript/strife/entityboss.txt
zscript/strife/inquisitor.txt
zscript/strife/klaxon.txt
zscript/strife/loremaster.txt
zscript/strife/macil.txt
zscript/strife/merchants.txt
@ -181,6 +182,7 @@ zscript/strife/sentinel.txt
zscript/strife/stalker.txt
zscript/strife/strifeammo.txt
zscript/strife/strifearmor.txt
zscript/strife/strifefunctions.txt
zscript/strife/strifeitems.txt
zscript/strife/strifekeys.txt
zscript/strife/strifestuff.txt

View File

@ -287,7 +287,7 @@ class Actor : Thinker native
native bool isTeammate(Actor other);
native int PlayerNumber();
native void SetFriendPlayer(PlayerInfo player);
native void NoiseAlert(Actor emitter, bool splash = false, double maxdist = 0);
native void NoiseAlert(Actor target, bool splash = false, double maxdist = 0);
native void ClearBounce();
native TerrainDef GetFloorTerrain();
@ -615,16 +615,11 @@ class Actor : Thinker native
native void A_PlayerScream();
native void A_SkullPop(class<PlayerChunk> skulltype = "BloodySkull");
native void A_CheckPlayerDone();
native void A_CheckTerrain();
native void A_Wander(int flags = 0);
native void A_Look2();
native void A_TossGib();
native void A_TurretLook();
native void A_KlaxonBlare();
native void A_Countdown();
native void A_AlertMonsters(double maxdist = 0, int flags = 0);
native void A_ClearSoundTarget();
native void A_CheckTerrain();
deprecated native void A_MissileAttack();
deprecated native void A_MeleeAttack();
@ -633,8 +628,6 @@ class Actor : Thinker native
native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class<Actor> pufftype = "BulletPuff");
native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false);
deprecated void A_PlayWeaponSound(sound whattoplay) { A_PlaySound(whattoplay, CHAN_WEAPON); }
native void A_FLoopActiveSound();
native void A_LoopActiveSound();
native void A_StopSound(int slot = CHAN_VOICE); // Bad default but that's what is originally was...
deprecated native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0);
deprecated native void A_StopSoundEx(name slot);
@ -698,7 +691,6 @@ class Actor : Thinker native
native bool A_SelectWeapon(class<Weapon> whichweapon, int flags = 0);
native void A_ClassBossHealth();
native void A_RocketInFlight();
native void A_DropFire();
native void A_RemoveForcefield();
native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT);

View File

@ -131,6 +131,8 @@ struct State native
native bool bSameFrame;
native bool bCanRaise;
native bool bDehacked;
native int DistanceTo(state other);
}
struct F3DFloor native

View File

@ -138,6 +138,15 @@ class PSprite : Object native
}
enum EPlayerState
{
PST_LIVE, // Playing or camping.
PST_DEAD, // Dead on the ground, view follows killer.
PST_REBORN, // Ready to restart/respawn???
PST_ENTER, // [BC] Entered the game
PST_GONE // Player has left the game
}
struct PlayerInfo native // this is what internally is known as player_t
{
native readonly PlayerPawn mo;

View File

@ -302,7 +302,7 @@ class AcolyteToBe : Acolyte
Door_Close(999, 64);
if (target != null && target.player != null)
{
target.NoiseAlert (self);
NoiseAlert (target);
}
}
}

View File

@ -0,0 +1,125 @@
// Klaxon Warning Light -----------------------------------------------------
class KlaxonWarningLight : Actor
{
Default
{
ReactionTime 60;
Radius 5;
+NOBLOCKMAP +AMBUSH
+SPAWNCEILING +NOGRAVITY
+FIXMAPTHINGPOS +NOSPLASHALERT
+SYNCHRONIZED
}
States
{
Spawn:
KLAX A 5 A_TurretLook;
Loop;
See:
KLAX B 6 A_KlaxonBlare;
KLAX C 60;
Loop;
}
}
// CeilingTurret ------------------------------------------------------------
class CeilingTurret : Actor
{
Default
{
Health 125;
Speed 0;
Painchance 0;
Mass 10000000;
Monster;
-SOLID
-CANPASS
+AMBUSH
+SPAWNCEILING
+NOGRAVITY
+NOBLOOD
+NOSPLASHALERT
+DONTFALL
MinMissileChance 150;
DeathSound "turret/death";
}
States
{
Spawn:
TURT A 5 A_TurretLook;
Loop;
See:
TURT A 2 A_Chase;
Loop;
Missile:
Pain:
TURT B 4 Slow A_ShootGun;
TURT D 3 Slow A_SentinelRefire;
TURT A 4 A_SentinelRefire;
Loop;
Death:
BALL A 6 Bright A_Scream;
BALL BCDE 6 Bright;
TURT C -1;
Stop;
}
}
extend class Actor
{
void A_TurretLook()
{
if (bInConversation)
return;
threshold = 0;
Actor targ = LastHeard;
if (targ != NULL && targ.health > 0 && targ.bShootable && !IsFriend(targ))
{
target = targ;
if (bAmbush && !CheckSight (targ))
{
return;
}
if (SeeSound != 0)
{
A_PlaySound (SeeSound, CHAN_VOICE);
}
LastHeard = NULL;
threshold = 10;
SetState (SeeState);
}
}
void A_KlaxonBlare()
{
if (--reactiontime < 0)
{
target = NULL;
reactiontime = Default.reactiontime;
A_TurretLook();
if (target == NULL)
{
SetIdle();
}
else
{
reactiontime = 50;
}
}
if (reactiontime == 2)
{
// [RH] Unalert monsters near the alarm and not just those in the same sector as it.
NoiseAlert (NULL, false);
}
else if (reactiontime > 50)
{
A_PlaySound ("misc/alarm", CHAN_VOICE);
}
}
}

View File

@ -0,0 +1,120 @@
// common Strife action functions.
extend class Actor
{
//============================================================================
void A_FLoopActiveSound()
{
if (ActiveSound != 0 && !(level.time & 7))
{
A_PlaySound (ActiveSound, CHAN_VOICE);
}
}
void A_LoopActiveSound()
{
A_PlaySound(ActiveSound, CHAN_VOICE, 1, true);
}
//============================================================================
//
//
//
//============================================================================
void A_Countdown()
{
if (--reactiontime <= 0)
{
ExplodeMissile ();
bSkullFly = false;
}
}
//============================================================================
//
// A_ClearSoundTarget
//
//============================================================================
void A_ClearSoundTarget()
{
CurSector.SoundTarget = null;
for (Actor mo = CurSector.thinglist; mo != null; mo = mo.snext)
{
mo.LastHeard = null;
}
}
//==========================================================================
//
// A_TossGib
//
//==========================================================================
void A_TossGib()
{
class <Actor> gibtype;
if (bNoBlood) gibtype = "Junk";
else gibtype = "Meat";
Actor gib = Spawn (gibtype, pos + (0,0,24), ALLOW_REPLACE);
if (gib == null)
{
return;
}
gib.Angle = random[GibTosser]() * (360 / 256.f);
gib.VelFromAngle(random[GibTosser]() & 15);
gib.Vel.Z = random[GibTosser]() & 15;
}
// A_ShootGun -------------------------------------------------------------
void A_ShootGun()
{
if (!target) return;
A_PlaySound ("monsters/rifle", CHAN_WEAPON);
A_FaceTarget ();
double pitch = AimLineAttack (angle, MISSILERANGE);
LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff");
}
// Kneeling Guy -------------------------------------------------------------
void A_SetShadow()
{
bShadow = true;
A_SetRenderStyle(HR_SHADOW, STYLE_Translucent);
}
void A_ClearShadow()
{
bShadow = false;
A_SetRenderStyle(1, STYLE_Normal);
}
void A_GetHurt()
{
bInCombat = true;
if ((random[HurtMe]() % 5) == 0)
{
A_PlaySound (PainSound, CHAN_VOICE);
health--;
}
if (health <= 0)
{
Die (target, target);
}
}
void A_DropFire()
{
Actor drop = Spawn("FireDroplet", pos + (0,0,24), ALLOW_REPLACE);
drop.Vel.Z = -1.;
A_Explode(64, 64, XF_NOSPLASH, damagetype: 'Fire');
}
}

View File

@ -54,50 +54,3 @@ class FireDroplet : Actor
Stop;
}
}
extend class Actor
{
//============================================================================
//
// A_ShootGun
//
//============================================================================
void A_ShootGun()
{
if (!target) return;
A_PlaySound ("monsters/rifle", CHAN_WEAPON);
A_FaceTarget ();
double pitch = AimLineAttack (angle, MISSILERANGE);
LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff");
}
// Kneeling Guy -------------------------------------------------------------
void A_SetShadow()
{
bShadow = true;
A_SetRenderStyle(HR_SHADOW, STYLE_Translucent);
}
void A_ClearShadow()
{
bShadow = false;
A_SetRenderStyle(1, STYLE_Normal);
}
void A_GetHurt()
{
bInCombat = true;
if ((random[HurtMe]() % 5) == 0)
{
A_PlaySound (PainSound, CHAN_VOICE);
health--;
}
if (health <= 0)
{
Die (target, target);
}
}
}

View File

@ -36,10 +36,6 @@ class StrifePlayer : PlayerPawn
Player.Colorset 7, "Blue", 0x90, 0x9F, 0x92, 0x20, 0x3F, 0x00, 0x1F, 0x50, 0x5F, 0x40, 0x4F, 0xC1, 0xCF, 0x01, 0x0F, 0xC0,0xC0,1,1, 0xD0, 0xDF, 0x10, 0x1F;
}
native void A_ItBurnsItBurns();
native void A_CrispyPlayer();
native void A_HandLower();
States
{
Spawn:
@ -101,5 +97,69 @@ class StrifePlayer : PlayerPawn
WAVE ABCD 3 A_HandLower;
Loop;
}
void A_ItBurnsItBurns()
{
A_PlaySound ("human/imonfire", CHAN_VOICE);
if (player != null && player.mo == self)
{
player.SetPsprite(PSP_STRIFEHANDS, FindState("FireHands"));
player.ReadyWeapon = null;
player.PendingWeapon = WP_NOCHANGE;
player.playerstate = PST_LIVE;
player.extralight = 3;
}
}
void A_CrispyPlayer()
{
if (player != null && player.mo == self)
{
PSprite psp = player.GetPSprite(PSP_STRIFEHANDS);
State firehandslower = FindState("FireHandsLower");
State firehands = FindState("FireHands");
if (psp.CurState != null && firehandslower != null && firehands != null)
{
// Calculate state to go to.
int dist = firehands.DistanceTo(psp.curState);
if (dist > 0)
{
player.playerstate = PST_DEAD;
psp.SetState(firehandslower + dist);
return;
}
}
player.playerstate = PST_DEAD;
psp.SetState(null);
}
}
void A_HandLower()
{
if (player != null)
{
PSprite psp = player.GetPSprite(PSP_STRIFEHANDS);
if (psp.CurState == null)
{
psp.SetState(null);
return;
}
psp.y += 9;
if (psp.y > WEAPONBOTTOM*2)
{
psp.SetState(null);
}
if (player.extralight > 0) player.extralight--;
}
return;
}
}

View File

@ -1796,81 +1796,8 @@ class KneelingGuy : Actor
NEAL J -1;
Stop;
}
}
// Klaxon Warning Light -----------------------------------------------------
class KlaxonWarningLight : Actor
{
Default
{
ReactionTime 60;
Radius 5;
+NOBLOCKMAP +AMBUSH
+SPAWNCEILING +NOGRAVITY
+FIXMAPTHINGPOS +NOSPLASHALERT
+SYNCHRONIZED
}
States
{
Spawn:
KLAX A 5 A_TurretLook;
Loop;
See:
KLAX B 6 A_KlaxonBlare;
KLAX C 60;
Loop;
}
}
// CeilingTurret ------------------------------------------------------------
class CeilingTurret : Actor
{
Default
{
Health 125;
Speed 0;
Painchance 0;
Mass 10000000;
Monster;
-SOLID
-CANPASS
+AMBUSH
+SPAWNCEILING
+NOGRAVITY
+NOBLOOD
+NOSPLASHALERT
+DONTFALL
MinMissileChance 150;
DeathSound "turret/death";
}
States
{
Spawn:
TURT A 5 A_TurretLook;
Loop;
See:
TURT A 2 A_Chase;
Loop;
Missile:
Pain:
TURT B 4 Slow A_ShootGun;
TURT D 3 Slow A_SentinelRefire;
TURT A 4 A_SentinelRefire;
Loop;
Death:
BALL A 6 Bright A_Scream;
BALL BCDE 6 Bright;
TURT C -1;
Stop;
}
}
// Power Coupling -----------------------------------------------------------
class PowerCoupling : Actor native