mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-16 01:11:50 +00:00
605a9a7715
- Converted a_zombie.cpp and most of a_strifestuff.cpp to DECORATE. - Converted a_strifekeys.cpp to DECORATE and moved the pickup messages to the string table. - Removed the WIF_HITS_GHOSTS weapon flag and replaced it with MF2_THRUGHOST. There is no need to keep two flags around with virtually the same meaning. - Changed the ShadowArmor to use the VISIBILITYPULSE flag to change its translucency. It looks much better now than the cheap code pointer based blinking it used before. - Converted most of a_strifeitems.cpp to DECORATE and moved the pickup messages to the string table. - Converted a_strifearmor.cpp to DECORATE and moved the pickup messages to the string table. - Moved the messages for killing spectres to the string table. - Converted the quest items to DECORATE. Also changed A_GiveQuestItem to get the messages it prints from the string table instead of the quest item's tag string. May 5, 2006 (Changes by Graf Zahl) - Removed the hopelessly outdated thingdef_doc.txt file from the repository. - Converted a_peasant.cpp and a_ratbuddy.cpp to DECORATE. - Fixed: C_DoKey didn't treat an empty string as 'no binding' when checking for valid double bindings. - Converted a_merchants.cpp to DECORATE. - Added MF5_NODAMAGE flag to generalize the behavior of Strife's merchants which can be shot but take no damage from getting hurt. - Converted a_beggars.cpp to DECORATE. - Added an Inventory.GiveQuest property. This makes it possible to define all of Strife's original items that also give a quest item in DECORATE but it is also useful to define items like the ones in Day of the Acolyte without ugly workarounds. - Added a Tag property and Strife teaser conversation IDs to DECORATE so now it is possible to define many of Strife's items. - Added a FastSpeed property to DECORATE so that projectiles can finally be assigned a higher speed for fast mode. - Added a ACS_LockedExecuteDoor special. It is basically the same as the existing ACS_LockedExecute but it uses the 'door' message instead of 'remote'. This cannot be integrated into ACS_LockedExecute because all its arguments are already in use. - Added a fully customizable A_CustomMeleeAttack function for DECORATE. SVN r83 (trunk)
1001 lines
25 KiB
C++
1001 lines
25 KiB
C++
#include "actor.h"
|
|
#include "gi.h"
|
|
#include "m_random.h"
|
|
#include "s_sound.h"
|
|
#include "d_player.h"
|
|
#include "a_action.h"
|
|
#include "p_local.h"
|
|
#include "a_doomglobal.h"
|
|
#include "a_strifeglobal.h"
|
|
#include "p_enemy.h"
|
|
#include "p_lnspec.h"
|
|
#include "c_console.h"
|
|
|
|
// Notes so I don't forget them:
|
|
// Strife does some extra stuff in A_Explode if a player caused the explosion. (probably NoiseAlert)
|
|
// See the instructions @ 21249.
|
|
//
|
|
// Strife's FLOATSPEED is 5 and not 4.
|
|
//
|
|
// In P_CheckMissileRange, mobjtypes 53,54,55,56,57,58 shift the distance right 4 bits (some, but not all the acolytes)
|
|
// mobjtypes 61,63,91 shift it right 1 bit
|
|
//
|
|
// When shooting missiles at something, if MF_SHADOW is set, the angle is adjusted with the formula:
|
|
// angle += pr_spawnmissile.Random2() << 21
|
|
// When MF_STRIFEx4000000 is set, the angle is adjusted similarly:
|
|
// angle += pr_spawnmissile.Random2() << 22
|
|
// Note that these numbers are different from those used by all the other Doom engine games.
|
|
|
|
/* These mobjinfos have been converted:
|
|
|
|
0 ForceFieldGuard
|
|
1 StrifePlayer
|
|
2 WeaponSmith
|
|
3 BarKeep
|
|
4 Armorer
|
|
5 Medic
|
|
6 Peasant1
|
|
7 Peasant2
|
|
8 Peasant3
|
|
9 Peasant4
|
|
10 Peasant5
|
|
11 Peasant6
|
|
12 Peasant7
|
|
13 Peasant8
|
|
14 Peasant9
|
|
15 Peasant10
|
|
16 Peasant11
|
|
17 Peasant12
|
|
18 Peasant13
|
|
19 Peasant14
|
|
20 Peasant15
|
|
21 Peasant16
|
|
22 Peasant17
|
|
23 Peasant18
|
|
24 Peasant19
|
|
25 Peasant20
|
|
26 Peasant21
|
|
27 Peasant22
|
|
28 Zombie
|
|
29 AcolyteToBe
|
|
30 ZombieSpawner
|
|
31 Tank1
|
|
32 Tank2
|
|
33 Tank3
|
|
34 Tank4
|
|
35 Tank5
|
|
36 Tank6
|
|
37 KneelingGuy
|
|
38 Beggar1
|
|
39 Beggar2
|
|
40 Beggar3
|
|
41 Beggar4
|
|
42 Beggar5
|
|
43 Rebel1
|
|
44 Rebel2
|
|
45 Rebel3
|
|
46 Rebel4
|
|
47 Rebel5
|
|
48 Rebel6
|
|
49 Macil1
|
|
50 Macil2
|
|
51 RocketTrail
|
|
52 Reaver
|
|
53 AcolyteTan
|
|
54 AcolyteRed
|
|
55 AcolyteRust
|
|
56 AcolyteGray
|
|
57 AcolyteDGreen
|
|
58 AcolyteGold
|
|
59 AcolyteLGreen
|
|
60 AcolyteBlue
|
|
61 AcolyteShadow
|
|
62 Templar
|
|
63 Crusader
|
|
64 StrifeBishop
|
|
65 Oracle
|
|
66 Loremaster (aka Priest)
|
|
67 AlienSpectre1
|
|
68 AlienChunkSmall
|
|
69 AlienChunkLarge
|
|
70 AlienSpectre2
|
|
71 AlienSpectre3
|
|
72 AlienSpectre4
|
|
73 AlienSpectre5
|
|
74 EntityBoss
|
|
75 EntitySecond
|
|
76 EntityNest
|
|
77 EntityPod
|
|
78 SpectralLightningH1
|
|
79 SpectralLightningH2
|
|
80 SpectralLightningBall1
|
|
81 SpectralLightningBall2
|
|
82 SpectralLightningH3
|
|
83 SpectralLightningHTail
|
|
84 SpectralLightningBigBall1
|
|
85 SpectralLightningBigBall2
|
|
86 SpectralLightningV1
|
|
87 SpectralLightningV2
|
|
88 SpectralLightningSpot
|
|
89 SpectralLightningBigV1
|
|
90 SpectralLightningBigV2
|
|
91 Sentinel
|
|
92 Stalker
|
|
93 Inquisitor
|
|
94 InquisitorArm
|
|
95 Programmer
|
|
96 ProgrammerBase
|
|
97 LoreShot
|
|
98 LoreShot2
|
|
99 MiniMissile
|
|
100 CrusaderMissile
|
|
101 BishopMissile
|
|
102 ElectricBolt
|
|
103 PoisonBolt
|
|
104 SentinelFX1
|
|
105 SentinelFX2
|
|
106 HEGrenade
|
|
107 PhosphorousGrenade
|
|
108 InquisitorShot
|
|
109 PhosphorousFire
|
|
110 MaulerTorpedo
|
|
111 MaulerTorpedoWave
|
|
112 FlameMissile
|
|
113 FastFlameMissile
|
|
114 MaulerPuff
|
|
115 StrifePuff
|
|
116 StrifeSpark
|
|
117 Blood
|
|
118 TeleportFog
|
|
119 ItemFog
|
|
120 --- Doomednum is 14, which makes it a teleport destination. Don't know why it's in the mobjinfo table.
|
|
121 KlaxonWarningLight
|
|
122 CeilingTurret
|
|
123 Piston
|
|
124 Computer
|
|
125 MedPatch
|
|
126 MedicalKit
|
|
127 SurgeryKit
|
|
128 DegninOre
|
|
129 MetalArmor
|
|
130 LeatherArmor
|
|
131 WaterBottle
|
|
132 Mug
|
|
133 BaseKey
|
|
134 GovsKey
|
|
135 Passcard
|
|
136 IDBadge
|
|
137 PrisonKey
|
|
138 SeveredHand
|
|
139 Power1Key
|
|
140 Power2Key
|
|
141 Power3Key
|
|
142 GoldKey
|
|
143 IDCard
|
|
144 SilverKey
|
|
145 OracleKey
|
|
146 MilitaryID
|
|
147 OrderKey
|
|
148 WarehouseKey
|
|
149 BrassKey
|
|
150 RedCrystalKey
|
|
151 BlueCrystalKey
|
|
152 ChapelKey
|
|
153 CatacombKey
|
|
154 SecurityKey
|
|
155 CoreKey
|
|
156 MaulerKey
|
|
157 FactoryKey
|
|
158 MineKey
|
|
159 NewKey5
|
|
160 ShadowArmor
|
|
161 EnvironmentalSuit
|
|
162 GuardUniform
|
|
163 OfficersUniform
|
|
164 StrifeMap
|
|
165 Scanner
|
|
166
|
|
167 Targeter
|
|
168 Coin
|
|
169 Gold10
|
|
170 Gold25
|
|
171 Gold50
|
|
172 Gold300
|
|
173 BeldinsRing
|
|
174 OfferingChalice
|
|
175 Ear
|
|
176 Communicator
|
|
177 HEGrenadeRounds
|
|
178 PhosphorusGrenadeRounds
|
|
179 ClipOfBullets
|
|
180 BoxOfBullets
|
|
181 MiniMissiles
|
|
182 CrateOfMissiles
|
|
183 EnergyPod
|
|
184 EnergyPack
|
|
185 PoisonBolts
|
|
186 ElectricBolts
|
|
187 AmmoSatchel
|
|
188 AssaultGun
|
|
189 AssaultGunStanding
|
|
190 FlameThrower
|
|
191 FlameThrowerParts
|
|
192 MiniMissileLauncher
|
|
193 Mauler
|
|
194 StrifeCrossbow
|
|
195 StrifeGrenadeLauncher
|
|
196 Sigil1
|
|
197 Sigil2
|
|
198 Sigil3
|
|
199 Sigil4
|
|
200 Sigil5
|
|
201 PowerCrystal
|
|
202 RatBuddy
|
|
203 WoodenBarrel
|
|
204 ExplosiveBarrel2
|
|
205 TargetPractice
|
|
206 LightSilverFluorescent
|
|
207 LightBrownFluorescent
|
|
208 LightGoldFluorescent
|
|
209 LightGlobe
|
|
210 PillarTechno
|
|
211 PillarAztec
|
|
212 PillarAztecDamaged
|
|
213 PillarAztecRuined
|
|
214 PillarHugeTech
|
|
215 PillarAlienPower
|
|
216 SStalactiteBig
|
|
217 SStalactiteSmall
|
|
218 SStalagmiteBig
|
|
219 CavePillarTop
|
|
220 CavePillarBottom
|
|
221 SStalagmiteSmall
|
|
222 Candle
|
|
223 StrifeCandelabra
|
|
224 WaterDropOnFloor
|
|
225 WaterfallSplash
|
|
226 WaterDrip
|
|
227 WaterFountain
|
|
228 HeartsInTank
|
|
229 TeleportSwirl
|
|
230 DeadCrusader
|
|
231 DeadStrifePlayer
|
|
232 DeadPeasant
|
|
233 DeadAcolyte
|
|
234 DeadReaver
|
|
235 DeadRebel
|
|
236 SacrificedGuy
|
|
237 PileOfGuts
|
|
238 StrifeBurningBarrel
|
|
239 BurningBowl
|
|
240 BurningBrazier
|
|
241 SmallTorchLit
|
|
242 SmallTorchUnlit
|
|
243 CeilingChain
|
|
244 CageLight
|
|
245 Statue
|
|
246 StatueRuined
|
|
247 MediumTorch
|
|
248 OutsideLamp
|
|
249 PoleLantern
|
|
250 SRock1
|
|
251 SRock2
|
|
252 SRock3
|
|
253 SRock4
|
|
254 StickInWater
|
|
255 Rubble1
|
|
256 Rubble2
|
|
257 Rubble3
|
|
258 Rubble4
|
|
259 Rubble5
|
|
260 Rubble6
|
|
261 Rubble7
|
|
262 Rubble8
|
|
263 SurgeryCrab
|
|
264 LargeTorch
|
|
265 HugeTorch
|
|
266 PalmTree
|
|
267 BigTree2
|
|
268 PottedTree
|
|
269 TreeStub
|
|
270 ShortBush
|
|
271 TallBush
|
|
272 ChimneyStack
|
|
273 BarricadeColumn
|
|
274 Pot
|
|
275 Pitcher
|
|
276 Stool
|
|
277 MetalPot
|
|
278 Tub
|
|
279 Anvil
|
|
280 TechLampSilver
|
|
281 TechLampBrass
|
|
282 Tray
|
|
283 AmmoFiller
|
|
284 SigilBanner
|
|
285 RebelBoots
|
|
286 RebelHelmet
|
|
287 RebelShirt
|
|
288 PowerCoupling
|
|
289 BrokenPowerCoupling
|
|
290 AlienBubbleColumn
|
|
291 AlienFloorBubble
|
|
292 AlienCeilingBubble
|
|
293 AlienAspClimber
|
|
294 AlienSpiderLight
|
|
295 Meat
|
|
296 Junk
|
|
297 FireDroplet
|
|
298 AmmoFillup
|
|
299 HealthFillup
|
|
300 Info
|
|
301 RaiseAlarm
|
|
302 OpenDoor222
|
|
303 CloseDoor222
|
|
304 PrisonPass
|
|
305 OpenDoor224
|
|
306 UpgradeStamina
|
|
307 UpgradeAccuracy
|
|
308 InterrogatorReport (seems to be unused)
|
|
309 HealthTraining
|
|
310 GunTraining
|
|
311 OraclePass
|
|
312 QuestItem1
|
|
313 QuestItem2
|
|
314 QuestItem3
|
|
315 QuestItem4
|
|
316 QuestItem5
|
|
317 QuestItem6
|
|
318 QuestItem7
|
|
319 QuestItem8
|
|
320 QuestItem9
|
|
321 QuestItem10
|
|
322 QuestItem11
|
|
323 QuestItem12
|
|
324 QuestItem13
|
|
325 QuestItem14
|
|
326 QuestItem15
|
|
327 QuestItem16
|
|
328 QuestItem17
|
|
329 QuestItem18
|
|
330 QuestItem19
|
|
331 QuestItem20
|
|
332 QuestItem21
|
|
333 QuestItem22
|
|
334 QuestItem23
|
|
335 QuestItem24
|
|
336 QuestItem25
|
|
337 QuestItem26
|
|
338 QuestItem27
|
|
339 QuestItem28
|
|
340 QuestItem29
|
|
341 QuestItem30
|
|
342 QuestItem31
|
|
343 SlideshowStarter
|
|
*/
|
|
|
|
static FRandom pr_gibtosser ("GibTosser");
|
|
|
|
void A_TossGib (AActor *);
|
|
void A_LoopActiveSound (AActor *);
|
|
void A_FLoopActiveSound (AActor *);
|
|
void A_Countdown (AActor *);
|
|
void A_XXScream (AActor *);
|
|
void A_SentinelRefire (AActor *);
|
|
|
|
// Force Field Guard --------------------------------------------------------
|
|
|
|
void A_RemoveForceField (AActor *);
|
|
|
|
class AForceFieldGuard : public AActor
|
|
{
|
|
DECLARE_ACTOR (AForceFieldGuard, AActor)
|
|
public:
|
|
int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, int damagetype);
|
|
};
|
|
|
|
FState AForceFieldGuard::States[] =
|
|
{
|
|
S_NORMAL (TOKN, 'A', -1, NULL, NULL),
|
|
S_NORMAL (XPRK, 'A', 1, A_RemoveForceField, NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AForceFieldGuard, Strife, 25, 0)
|
|
PROP_StrifeType (0)
|
|
PROP_SpawnHealth (10)
|
|
PROP_SpawnState (0)
|
|
PROP_DeathState (1)
|
|
PROP_RadiusFixed (2)
|
|
PROP_HeightFixed (1)
|
|
PROP_Mass (10000)
|
|
PROP_Flags (MF_SHOOTABLE|MF_NOSECTOR)
|
|
PROP_Flags4 (MF4_INCOMBAT)
|
|
END_DEFAULTS
|
|
|
|
int AForceFieldGuard::TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, int damagetype)
|
|
{
|
|
if (inflictor == NULL || !inflictor->IsKindOf (RUNTIME_CLASS(ADegninOre)))
|
|
{
|
|
return -1;
|
|
}
|
|
return health;
|
|
}
|
|
|
|
// Kneeling Guy -------------------------------------------------------------
|
|
|
|
void A_SetShadow (AActor *self)
|
|
{
|
|
self->flags |= MF_STRIFEx8000000|MF_SHADOW;
|
|
self->RenderStyle = STYLE_Translucent;
|
|
self->alpha = HR_SHADOW;
|
|
}
|
|
|
|
void A_ClearShadow (AActor *self)
|
|
{
|
|
self->flags &= ~(MF_STRIFEx8000000|MF_SHADOW);
|
|
self->RenderStyle = STYLE_Normal;
|
|
self->alpha = OPAQUE;
|
|
}
|
|
|
|
static FRandom pr_gethurt ("HurtMe!");
|
|
|
|
void A_GetHurt (AActor *self)
|
|
{
|
|
self->flags4 |= MF4_INCOMBAT;
|
|
if ((pr_gethurt() % 5) == 0)
|
|
{
|
|
S_SoundID (self, CHAN_VOICE, self->PainSound, 1, ATTN_NORM);
|
|
self->health--;
|
|
}
|
|
if (self->health <= 0)
|
|
{
|
|
self->Die (self->target, self->target);
|
|
}
|
|
}
|
|
|
|
class AKneelingGuy : public AActor
|
|
{
|
|
DECLARE_ACTOR (AKneelingGuy, AActor)
|
|
};
|
|
|
|
FState AKneelingGuy::States[] =
|
|
{
|
|
#define S_KNEEL 0
|
|
S_NORMAL (NEAL, 'A', 15, A_LoopActiveSound, &States[S_KNEEL+1]),
|
|
S_NORMAL (NEAL, 'B', 40, A_LoopActiveSound, &States[S_KNEEL]),
|
|
|
|
#define S_KNEEL_PAIN (S_KNEEL+2)
|
|
S_NORMAL (NEAL, 'C', 5, A_SetShadow, &States[S_KNEEL_PAIN+1]),
|
|
S_NORMAL (NEAL, 'B', 4, A_Pain, &States[S_KNEEL_PAIN+2]),
|
|
S_NORMAL (NEAL, 'C', 5, A_ClearShadow, &States[S_KNEEL]),
|
|
|
|
#define S_KNEEL_HURT (S_KNEEL_PAIN+3)
|
|
S_NORMAL (NEAL, 'B', 6, NULL, &States[S_KNEEL_HURT+1]),
|
|
S_NORMAL (NEAL, 'C', 13, A_GetHurt, &States[S_KNEEL_HURT]),
|
|
|
|
#define S_KNEEL_DIE (S_KNEEL_HURT+2)
|
|
S_NORMAL (NEAL, 'D', 5, NULL, &States[S_KNEEL_DIE+1]),
|
|
S_NORMAL (NEAL, 'E', 5, A_Scream, &States[S_KNEEL_DIE+2]),
|
|
S_NORMAL (NEAL, 'F', 6, NULL, &States[S_KNEEL_DIE+3]),
|
|
S_NORMAL (NEAL, 'G', 5, A_NoBlocking, &States[S_KNEEL_DIE+4]),
|
|
S_NORMAL (NEAL, 'H', 5, NULL, &States[S_KNEEL_DIE+5]),
|
|
S_NORMAL (NEAL, 'I', 6, NULL, &States[S_KNEEL_DIE+6]),
|
|
S_NORMAL (NEAL, 'J', -1, NULL, NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AKneelingGuy, Strife, 204, 0)
|
|
PROP_SpawnState (S_KNEEL)
|
|
PROP_SeeState (S_KNEEL)
|
|
PROP_PainState (S_KNEEL_PAIN)
|
|
PROP_WoundState (S_KNEEL_HURT)
|
|
PROP_DeathState (S_KNEEL_DIE)
|
|
|
|
PROP_SpawnHealth (51)
|
|
PROP_PainChance (255)
|
|
PROP_RadiusFixed (6)
|
|
PROP_HeightFixed (17)
|
|
PROP_MassLong (50000)
|
|
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD)
|
|
PROP_Flags3 (MF3_ISMONSTER)
|
|
PROP_Flags4 (MF4_INCOMBAT)
|
|
PROP_MinMissileChance (150)
|
|
PROP_StrifeType (37)
|
|
|
|
PROP_PainSound ("misc/static")
|
|
PROP_DeathSound ("misc/static")
|
|
PROP_ActiveSound ("misc/chant")
|
|
END_DEFAULTS
|
|
|
|
// Klaxon Warning Light -----------------------------------------------------
|
|
|
|
void A_TurretLook (AActor *self)
|
|
{
|
|
AActor *target;
|
|
|
|
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;
|
|
}
|
|
if (self->SeeSound != 0)
|
|
{
|
|
S_SoundID (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM);
|
|
}
|
|
self->LastHeard = NULL;
|
|
self->threshold = 10;
|
|
self->SetState (self->SeeState);
|
|
}
|
|
}
|
|
|
|
void A_KlaxonBlare (AActor *self)
|
|
{
|
|
if (--self->reactiontime < 0)
|
|
{
|
|
self->target = NULL;
|
|
self->reactiontime = self->GetDefault()->reactiontime;
|
|
A_TurretLook (self);
|
|
if (self->target == NULL)
|
|
{
|
|
self->SetState (self->SpawnState);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|
|
class AKlaxonWarningLight : public AActor
|
|
{
|
|
DECLARE_ACTOR (AKlaxonWarningLight, AActor)
|
|
};
|
|
|
|
FState AKlaxonWarningLight::States[] =
|
|
{
|
|
S_NORMAL (KLAX, 'A', 5, A_TurretLook, &States[0]),
|
|
|
|
S_NORMAL (KLAX, 'B', 6, A_KlaxonBlare, &States[2]),
|
|
S_NORMAL (KLAX, 'C', 60, NULL, &States[1])
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AKlaxonWarningLight, Strife, 24, 0)
|
|
PROP_SpawnState (0)
|
|
PROP_SeeState (1)
|
|
PROP_ReactionTime (60)
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_AMBUSH|MF_SPAWNCEILING|MF_NOGRAVITY)
|
|
PROP_Flags4 (MF4_FIXMAPTHINGPOS|MF4_NOSPLASHALERT|MF4_SYNCHRONIZED)
|
|
PROP_StrifeType (121)
|
|
END_DEFAULTS
|
|
|
|
// CeilingTurret ------------------------------------------------------------
|
|
|
|
void A_ShootGun (AActor *);
|
|
|
|
class ACeilingTurret : public AActor
|
|
{
|
|
DECLARE_ACTOR (ACeilingTurret, AActor)
|
|
};
|
|
|
|
FState ACeilingTurret::States[] =
|
|
{
|
|
S_NORMAL (TURT, 'A', 5, A_TurretLook, &States[0]),
|
|
|
|
S_NORMAL (TURT, 'A', 2, A_Chase, &States[1]),
|
|
|
|
S_NORMAL (TURT, 'B', 4, A_ShootGun, &States[3]),
|
|
S_NORMAL (TURT, 'D', 3, A_SentinelRefire, &States[4]),
|
|
S_NORMAL (TURT, 'A', 4, A_SentinelRefire, &States[2]),
|
|
|
|
S_BRIGHT (BALL, 'A', 6, A_Scream, &States[6]),
|
|
S_BRIGHT (BALL, 'B', 6, NULL, &States[7]),
|
|
S_BRIGHT (BALL, 'C', 6, NULL, &States[8]),
|
|
S_BRIGHT (BALL, 'D', 6, NULL, &States[9]),
|
|
S_BRIGHT (BALL, 'E', 6, NULL, &States[10]),
|
|
S_NORMAL (TURT, 'C', -1, NULL, NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (ACeilingTurret, Strife, 27, 0)
|
|
PROP_StrifeType (122)
|
|
PROP_SpawnHealth (125)
|
|
PROP_SpawnState (0)
|
|
PROP_SeeState (1)
|
|
PROP_PainState (2)
|
|
PROP_MissileState (2)
|
|
PROP_DeathState (5)
|
|
PROP_SpeedFixed (0)
|
|
PROP_PainChance (0)
|
|
PROP_MassLong (10000000)
|
|
PROP_Flags (MF_SHOOTABLE|MF_AMBUSH|MF_SPAWNCEILING|MF_NOGRAVITY|
|
|
MF_NOBLOOD|MF_COUNTKILL)
|
|
PROP_Flags4 (MF4_NOSPLASHALERT|MF4_DONTFALL)
|
|
PROP_MinMissileChance (150)
|
|
PROP_DeathSound ("turret/death")
|
|
END_DEFAULTS
|
|
|
|
// Power Coupling -----------------------------------------------------------
|
|
|
|
class APowerCoupling : public AActor
|
|
{
|
|
DECLARE_ACTOR (APowerCoupling, AActor)
|
|
public:
|
|
void Die (AActor *source, AActor *inflictor);
|
|
};
|
|
|
|
FState APowerCoupling::States[] =
|
|
{
|
|
S_NORMAL (COUP, 'A', 5, NULL, &States[1]),
|
|
S_NORMAL (COUP, 'B', 5, NULL, &States[0]),
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (APowerCoupling, Strife, 220, 0)
|
|
PROP_SpawnState (0)
|
|
PROP_SpawnHealth (40)
|
|
PROP_RadiusFixed (17)
|
|
PROP_HeightFixed (64)
|
|
PROP_MassLong (999999)
|
|
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPPED|MF_NOBLOOD|MF_NOTDMATCH)
|
|
PROP_Flags4 (MF4_INCOMBAT)
|
|
PROP_StrifeType (288)
|
|
END_DEFAULTS
|
|
|
|
void APowerCoupling::Die (AActor *source, AActor *inflictor)
|
|
{
|
|
Super::Die (source, inflictor);
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAXPLAYERS; ++i)
|
|
if (playeringame[i] && players[i].health > 0)
|
|
break;
|
|
|
|
if (i == MAXPLAYERS)
|
|
return;
|
|
|
|
// [RH] In case the player broke it with the dagger, alert the guards now.
|
|
if (LastHeard != source)
|
|
{
|
|
P_NoiseAlert (source, this);
|
|
}
|
|
EV_DoDoor (DDoor::doorClose, NULL, players[i].mo, 225, 2*FRACUNIT, 0, 0, 0);
|
|
EV_DoFloor (DFloor::floorLowerToHighest, NULL, 44, FRACUNIT, 0, 0, 0);
|
|
players[i].mo->GiveInventoryType (QuestItemClasses[5]);
|
|
S_Sound (CHAN_VOICE, "svox/voc13", 1, ATTN_NORM);
|
|
players[i].SetLogNumber (13);
|
|
P_DropItem (this, "BrokenPowerCoupling", -1, 256);
|
|
Destroy ();
|
|
}
|
|
|
|
// Gibs for things that bleed -----------------------------------------------
|
|
|
|
class AMeat : public AActor
|
|
{
|
|
DECLARE_ACTOR (AMeat, AActor)
|
|
public:
|
|
void BeginPlay ()
|
|
{
|
|
// Strife used mod 19, but there are 20 states. Hmm.
|
|
SetState (SpawnState + pr_gibtosser() % 20);
|
|
}
|
|
};
|
|
|
|
FState AMeat::States[] =
|
|
{
|
|
S_NORMAL (MEAT, 'A', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'B', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'C', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'D', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'E', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'F', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'G', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'H', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'I', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'J', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'K', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'L', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'M', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'N', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'O', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'P', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'Q', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'R', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'S', 700, NULL, NULL),
|
|
S_NORMAL (MEAT, 'T', 700, NULL, NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AMeat, Any, -1, 0)
|
|
PROP_SpawnState (0)
|
|
PROP_Flags (MF_NOCLIP)
|
|
END_DEFAULTS
|
|
|
|
// Gibs for things that don't bleed -----------------------------------------
|
|
|
|
class AJunk : public AMeat
|
|
{
|
|
DECLARE_ACTOR (AJunk, AMeat)
|
|
};
|
|
|
|
FState AJunk::States[] =
|
|
{
|
|
S_NORMAL (JUNK, 'A', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'B', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'C', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'D', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'E', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'F', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'G', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'H', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'I', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'J', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'K', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'L', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'M', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'N', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'O', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'P', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'Q', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'R', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'S', 700, NULL, NULL),
|
|
S_NORMAL (JUNK, 'T', 700, NULL, NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AJunk, Any, -1, 0)
|
|
PROP_SpawnState (0)
|
|
PROP_Flags (MF_NOCLIP)
|
|
END_DEFAULTS
|
|
|
|
//==========================================================================
|
|
//
|
|
// A_TossGib
|
|
//
|
|
//==========================================================================
|
|
|
|
void A_TossGib (AActor *self)
|
|
{
|
|
const TypeInfo *gibtype = (self->flags & MF_NOBLOOD) ? RUNTIME_CLASS(AJunk) : RUNTIME_CLASS(AMeat);
|
|
AActor *gib = Spawn (gibtype, self->x, self->y, self->z + 24*FRACUNIT);
|
|
angle_t an;
|
|
int speed;
|
|
|
|
if (gib == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
an = pr_gibtosser() << 24;
|
|
gib->angle = an;
|
|
speed = pr_gibtosser() & 15;
|
|
gib->momx = speed * finecosine[an >> ANGLETOFINESHIFT];
|
|
gib->momy = speed * finesine[an >> ANGLETOFINESHIFT];
|
|
gib->momz = (pr_gibtosser() & 15) << FRACBITS;
|
|
}
|
|
|
|
//============================================================================
|
|
|
|
void A_FLoopActiveSound (AActor *self)
|
|
{
|
|
if (self->ActiveSound != 0 && !(level.time & 7))
|
|
{
|
|
S_SoundID (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM);
|
|
}
|
|
}
|
|
|
|
void A_Countdown (AActor *self)
|
|
{
|
|
if (--self->reactiontime <= 0)
|
|
{
|
|
P_ExplodeMissile (self, NULL);
|
|
self->flags &= ~MF_SKULLFLY;
|
|
}
|
|
}
|
|
|
|
void A_LoopActiveSound (AActor *self)
|
|
{
|
|
if (self->ActiveSound != 0 && !S_IsActorPlayingSomething (self, CHAN_VOICE))
|
|
{
|
|
S_LoopedSoundID (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM);
|
|
}
|
|
}
|
|
|
|
void A_CheckTerrain (AActor *self)
|
|
{
|
|
sector_t *sec = self->Sector;
|
|
|
|
if (self->z == sec->floorplane.ZatPoint (self->x, self->y))
|
|
{
|
|
if ((sec->special & 0xFF) == Damage_InstantDeath)
|
|
{
|
|
P_DamageMobj (self, NULL, NULL, 999, MOD_UNKNOWN);
|
|
}
|
|
else if ((sec->special & 0xFF) == Scroll_StrifeCurrent)
|
|
{
|
|
int anglespeed = sec->tag - 100;
|
|
fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);
|
|
angle_t finean = (anglespeed / 10) << (32-3);
|
|
finean >>= ANGLETOFINESHIFT;
|
|
self->momx += FixedMul (speed, finecosine[finean]);
|
|
self->momy += FixedMul (speed, finesine[finean]);
|
|
}
|
|
}
|
|
}
|
|
|
|
//============================================================================
|
|
//
|
|
// A_ClearSoundTarget
|
|
//
|
|
//============================================================================
|
|
|
|
void A_ClearSoundTarget (AActor *self)
|
|
{
|
|
AActor *actor;
|
|
|
|
self->Sector->SoundTarget = NULL;
|
|
for (actor = self->Sector->thinglist; actor != NULL; actor = actor->snext)
|
|
{
|
|
actor->LastHeard = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
// Fire Droplet -------------------------------------------------------------
|
|
|
|
class AFireDroplet : public AActor
|
|
{
|
|
DECLARE_ACTOR (AFireDroplet, AActor)
|
|
};
|
|
|
|
// [RH] I think these should be bright, even though they weren't in Strife.
|
|
FState AFireDroplet::States[] =
|
|
{
|
|
S_BRIGHT (FFOT, 'A', 9, NULL, &States[1]),
|
|
S_BRIGHT (FFOT, 'B', 9, NULL, &States[2]),
|
|
S_BRIGHT (FFOT, 'C', 9, NULL, &States[3]),
|
|
S_BRIGHT (FFOT, 'D', 9, NULL, NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AFireDroplet, Strife, -1, 0)
|
|
PROP_StrifeType (297)
|
|
PROP_SpawnState (0)
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOCLIP)
|
|
END_DEFAULTS
|
|
|
|
// Humanoid Base Class ------------------------------------------------------
|
|
|
|
void A_ItBurnsItBurns (AActor *);
|
|
void A_DropFire (AActor *);
|
|
void A_CrispyPlayer (AActor *);
|
|
void A_HandLower (AActor *);
|
|
void A_Yeargh (AActor *);
|
|
|
|
FState AStrifeHumanoid::States[] =
|
|
{
|
|
#define S_FIREHANDS 0
|
|
S_BRIGHT (WAVE, 'A', 3, NULL, &States[S_FIREHANDS+1]),
|
|
S_BRIGHT (WAVE, 'B', 3, NULL, &States[S_FIREHANDS+2]),
|
|
S_BRIGHT (WAVE, 'C', 3, NULL, &States[S_FIREHANDS+3]),
|
|
S_BRIGHT (WAVE, 'D', 3, NULL, &States[S_FIREHANDS]),
|
|
|
|
// [RH] These weren't bright in Strife, but I think they should be.
|
|
// (After all, they are now a light source.)
|
|
#define S_HUMAN_BURNDEATH (S_FIREHANDS+4)
|
|
S_BRIGHT (BURN, 'A', 3, A_ItBurnsItBurns, &States[S_HUMAN_BURNDEATH+1]),
|
|
S_BRIGHT (BURN, 'B', 3, A_DropFire, &States[S_HUMAN_BURNDEATH+2]),
|
|
S_BRIGHT (BURN, 'C', 3, A_Wander, &States[S_HUMAN_BURNDEATH+3]),
|
|
S_BRIGHT (BURN, 'D', 3, A_NoBlocking, &States[S_HUMAN_BURNDEATH+4]),
|
|
S_BRIGHT (BURN, 'E', 5, A_DropFire, &States[S_HUMAN_BURNDEATH+5]),
|
|
S_BRIGHT (BURN, 'F', 5, A_Wander, &States[S_HUMAN_BURNDEATH+6]),
|
|
S_BRIGHT (BURN, 'G', 5, A_Wander, &States[S_HUMAN_BURNDEATH+7]),
|
|
S_BRIGHT (BURN, 'H', 5, A_Wander, &States[S_HUMAN_BURNDEATH+8]),
|
|
S_BRIGHT (BURN, 'I', 5, A_DropFire, &States[S_HUMAN_BURNDEATH+9]),
|
|
S_BRIGHT (BURN, 'J', 5, A_Wander, &States[S_HUMAN_BURNDEATH+10]),
|
|
S_BRIGHT (BURN, 'K', 5, A_Wander, &States[S_HUMAN_BURNDEATH+11]),
|
|
S_BRIGHT (BURN, 'L', 5, A_Wander, &States[S_HUMAN_BURNDEATH+12]),
|
|
S_BRIGHT (BURN, 'M', 3, A_DropFire, &States[S_HUMAN_BURNDEATH+13]),
|
|
S_BRIGHT (BURN, 'N', 3, NULL, &States[S_HUMAN_BURNDEATH+14]),
|
|
S_BRIGHT (BURN, 'O', 5, NULL, &States[S_HUMAN_BURNDEATH+15]),
|
|
S_BRIGHT (BURN, 'P', 5, NULL, &States[S_HUMAN_BURNDEATH+16]),
|
|
S_BRIGHT (BURN, 'Q', 5, NULL, &States[S_HUMAN_BURNDEATH+17]),
|
|
S_BRIGHT (BURN, 'P', 5, NULL, &States[S_HUMAN_BURNDEATH+18]),
|
|
S_BRIGHT (BURN, 'Q', 5, NULL, &States[S_HUMAN_BURNDEATH+19]),
|
|
S_BRIGHT (BURN, 'R', 7, NULL, &States[S_HUMAN_BURNDEATH+20]),
|
|
S_BRIGHT (BURN, 'S', 7, NULL, &States[S_HUMAN_BURNDEATH+21]),
|
|
S_BRIGHT (BURN, 'T', 7, NULL, &States[S_HUMAN_BURNDEATH+22]),
|
|
S_BRIGHT (BURN, 'U', 7, NULL, &States[S_HUMAN_BURNDEATH+23]),
|
|
S_BRIGHT (BURN, 'V',700,NULL, NULL),
|
|
|
|
#define S_HUMAN_ZAPDEATH (S_HUMAN_BURNDEATH+24)
|
|
S_NORMAL (DISR, 'A', 5, A_Yeargh, &States[S_HUMAN_ZAPDEATH+1]),
|
|
S_NORMAL (DISR, 'B', 5, NULL, &States[S_HUMAN_ZAPDEATH+2]),
|
|
S_NORMAL (DISR, 'C', 5, NULL, &States[S_HUMAN_ZAPDEATH+3]),
|
|
S_NORMAL (DISR, 'D', 5, A_NoBlocking, &States[S_HUMAN_ZAPDEATH+4]),
|
|
S_NORMAL (DISR, 'E', 5, NULL, &States[S_HUMAN_ZAPDEATH+5]),
|
|
S_NORMAL (DISR, 'F', 5, NULL, &States[S_HUMAN_ZAPDEATH+6]),
|
|
S_NORMAL (DISR, 'G', 4, NULL, &States[S_HUMAN_ZAPDEATH+7]),
|
|
S_NORMAL (DISR, 'H', 4, NULL, &States[S_HUMAN_ZAPDEATH+8]),
|
|
S_NORMAL (DISR, 'I', 4, NULL, &States[S_HUMAN_ZAPDEATH+9]),
|
|
S_NORMAL (DISR, 'J', 4, NULL, &States[S_HUMAN_ZAPDEATH+10]),
|
|
S_NORMAL (MEAT, 'D',700,NULL, NULL),
|
|
|
|
#define S_FIREHANDS2 (S_HUMAN_ZAPDEATH+11)
|
|
S_BRIGHT (WAVE, 'A', 3, A_HandLower, &States[S_FIREHANDS2+1]),
|
|
S_BRIGHT (WAVE, 'B', 3, A_HandLower, &States[S_FIREHANDS2+2]),
|
|
S_BRIGHT (WAVE, 'C', 3, A_HandLower, &States[S_FIREHANDS2+3]),
|
|
S_BRIGHT (WAVE, 'D', 3, A_HandLower, &States[S_FIREHANDS2]),
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AStrifeHumanoid, Any, -1, 0)
|
|
PROP_BDeathState (S_HUMAN_BURNDEATH)
|
|
PROP_EDeathState (S_HUMAN_ZAPDEATH)
|
|
PROP_MaxStepHeight (16)
|
|
PROP_MaxDropOffHeight (32)
|
|
END_DEFAULTS
|
|
|
|
void A_ItBurnsItBurns (AActor *self)
|
|
{
|
|
int burnsound = S_FindSound ("human/imonfire");
|
|
if (burnsound != 0)
|
|
{
|
|
self->DeathSound = burnsound;
|
|
}
|
|
A_Scream (self);
|
|
if (self->player != NULL && self->player->mo == self)
|
|
{
|
|
P_SetPsprite (self->player, ps_weapon, &AStrifeHumanoid::States[S_FIREHANDS]);
|
|
P_SetPsprite (self->player, ps_flash, NULL);
|
|
self->player->ReadyWeapon = NULL;
|
|
self->player->PendingWeapon = WP_NOCHANGE;
|
|
self->player->playerstate = PST_LIVE;
|
|
}
|
|
}
|
|
|
|
void A_DropFire (AActor *self)
|
|
{
|
|
AActor *drop = Spawn<AFireDroplet> (self->x, self->y, self->z + 24*FRACUNIT);
|
|
drop->momz = -FRACUNIT;
|
|
P_RadiusAttack (self, self, 64, 64, MOD_FIRE, false);
|
|
}
|
|
|
|
void A_CrispyPlayer (AActor *self)
|
|
{
|
|
if (self->player != NULL && self->player->mo == self)
|
|
{
|
|
self->player->playerstate = PST_DEAD;
|
|
P_SetPsprite (self->player, ps_weapon, &AStrifeHumanoid::States[S_FIREHANDS2 +
|
|
(self->player->psprites[ps_weapon].state - &AStrifeHumanoid::States[S_FIREHANDS])]);
|
|
}
|
|
}
|
|
|
|
void A_HandLower (AActor *self)
|
|
{
|
|
if (self->player != NULL)
|
|
{
|
|
pspdef_t *psp = &self->player->psprites[ps_weapon];
|
|
psp->sy += FRACUNIT*9;
|
|
if (psp->sy > WEAPONBOTTOM*2)
|
|
{
|
|
P_SetPsprite (self->player, ps_weapon, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void A_Yeargh (AActor *self)
|
|
{
|
|
S_Sound (self, CHAN_VOICE, "misc/disruptordeath", 1, ATTN_NORM);
|
|
}
|
|
|
|
|