summaryrefslogtreecommitdiff
path: root/src/hexen/p_things.c
blob: db0d89cc2bbe163fa84e7ae210c31e4bea85de61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 1993-2008 Raven Software
// Copyright(C) 2008 Simon Howard
//
// 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., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
//-----------------------------------------------------------------------------


// HEADER FILES ------------------------------------------------------------

#include "h2def.h"
#include "p_local.h"
#include "s_sound.h"

// MACROS ------------------------------------------------------------------

// TYPES -------------------------------------------------------------------

// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------

// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------

// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------

static boolean ActivateThing(mobj_t * mobj);
static boolean DeactivateThing(mobj_t * mobj);

// EXTERNAL DATA DECLARATIONS ----------------------------------------------

// PUBLIC DATA DEFINITIONS -------------------------------------------------

mobjtype_t TranslateThingType[] = {
    MT_MAPSPOT,                 // T_NONE
    MT_CENTAUR,                 // T_CENTAUR
    MT_CENTAURLEADER,           // T_CENTAURLEADER
    MT_DEMON,                   // T_DEMON
    MT_ETTIN,                   // T_ETTIN
    MT_FIREDEMON,               // T_FIREGARGOYLE
    MT_SERPENT,                 // T_WATERLURKER
    MT_SERPENTLEADER,           // T_WATERLURKERLEADER
    MT_WRAITH,                  // T_WRAITH
    MT_WRAITHB,                 // T_WRAITHBURIED
    MT_FIREBALL1,               // T_FIREBALL1
    MT_MANA1,                   // T_MANA1
    MT_MANA2,                   // T_MANA2
    MT_SPEEDBOOTS,              // T_ITEMBOOTS
    MT_ARTIEGG,                 // T_ITEMEGG
    MT_ARTIFLY,                 // T_ITEMFLIGHT
    MT_SUMMONMAULATOR,          // T_ITEMSUMMON
    MT_TELEPORTOTHER,           // T_ITEMTPORTOTHER
    MT_ARTITELEPORT,            // T_ITEMTELEPORT
    MT_BISHOP,                  // T_BISHOP
    MT_ICEGUY,                  // T_ICEGOLEM
    MT_BRIDGE,                  // T_BRIDGE
    MT_BOOSTARMOR,              // T_DRAGONSKINBRACERS
    MT_HEALINGBOTTLE,           // T_ITEMHEALTHPOTION
    MT_HEALTHFLASK,             // T_ITEMHEALTHFLASK
    MT_ARTISUPERHEAL,           // T_ITEMHEALTHFULL
    MT_BOOSTMANA,               // T_ITEMBOOSTMANA
    MT_FW_AXE,                  // T_FIGHTERAXE
    MT_FW_HAMMER,               // T_FIGHTERHAMMER
    MT_FW_SWORD1,               // T_FIGHTERSWORD1
    MT_FW_SWORD2,               // T_FIGHTERSWORD2
    MT_FW_SWORD3,               // T_FIGHTERSWORD3
    MT_CW_SERPSTAFF,            // T_CLERICSTAFF
    MT_CW_HOLY1,                // T_CLERICHOLY1
    MT_CW_HOLY2,                // T_CLERICHOLY2
    MT_CW_HOLY3,                // T_CLERICHOLY3
    MT_MW_CONE,                 // T_MAGESHARDS
    MT_MW_STAFF1,               // T_MAGESTAFF1
    MT_MW_STAFF2,               // T_MAGESTAFF2
    MT_MW_STAFF3,               // T_MAGESTAFF3
    MT_EGGFX,                   // T_MORPHBLAST
    MT_ROCK1,                   // T_ROCK1
    MT_ROCK2,                   // T_ROCK2
    MT_ROCK3,                   // T_ROCK3
    MT_DIRT1,                   // T_DIRT1
    MT_DIRT2,                   // T_DIRT2
    MT_DIRT3,                   // T_DIRT3
    MT_DIRT4,                   // T_DIRT4
    MT_DIRT5,                   // T_DIRT5
    MT_DIRT6,                   // T_DIRT6
    MT_ARROW,                   // T_ARROW
    MT_DART,                    // T_DART
    MT_POISONDART,              // T_POISONDART
    MT_RIPPERBALL,              // T_RIPPERBALL
    MT_SGSHARD1,                // T_STAINEDGLASS1
    MT_SGSHARD2,                // T_STAINEDGLASS2
    MT_SGSHARD3,                // T_STAINEDGLASS3
    MT_SGSHARD4,                // T_STAINEDGLASS4
    MT_SGSHARD5,                // T_STAINEDGLASS5
    MT_SGSHARD6,                // T_STAINEDGLASS6
    MT_SGSHARD7,                // T_STAINEDGLASS7
    MT_SGSHARD8,                // T_STAINEDGLASS8
    MT_SGSHARD9,                // T_STAINEDGLASS9
    MT_SGSHARD0,                // T_STAINEDGLASS0
    MT_PROJECTILE_BLADE,        // T_BLADE
    MT_ICESHARD,                // T_ICESHARD
    MT_FLAME_SMALL,             // T_FLAME_SMALL
    MT_FLAME_LARGE,             // T_FLAME_LARGE
    MT_ARMOR_1,                 // T_MESHARMOR
    MT_ARMOR_2,                 // T_FALCONSHIELD
    MT_ARMOR_3,                 // T_PLATINUMHELM
    MT_ARMOR_4,                 // T_AMULETOFWARDING
    MT_ARTIPOISONBAG,           // T_ITEMFLECHETTE
    MT_ARTITORCH,               // T_ITEMTORCH
    MT_BLASTRADIUS,             // T_ITEMREPULSION
    MT_MANA3,                   // T_MANA3
    MT_ARTIPUZZSKULL,           // T_PUZZSKULL
    MT_ARTIPUZZGEMBIG,          // T_PUZZGEMBIG
    MT_ARTIPUZZGEMRED,          // T_PUZZGEMRED
    MT_ARTIPUZZGEMGREEN1,       // T_PUZZGEMGREEN1
    MT_ARTIPUZZGEMGREEN2,       // T_PUZZGEMGREEN2
    MT_ARTIPUZZGEMBLUE1,        // T_PUZZGEMBLUE1
    MT_ARTIPUZZGEMBLUE2,        // T_PUZZGEMBLUE2
    MT_ARTIPUZZBOOK1,           // T_PUZZBOOK1
    MT_ARTIPUZZBOOK2,           // T_PUZZBOOK2
    MT_KEY1,                    // T_METALKEY
    MT_KEY2,                    // T_SMALLMETALKEY
    MT_KEY3,                    // T_AXEKEY
    MT_KEY4,                    // T_FIREKEY
    MT_KEY5,                    // T_GREENKEY
    MT_KEY6,                    // T_MACEKEY
    MT_KEY7,                    // T_SILVERKEY
    MT_KEY8,                    // T_RUSTYKEY
    MT_KEY9,                    // T_HORNKEY
    MT_KEYA,                    // T_SERPENTKEY
    MT_WATER_DRIP,              // T_WATERDRIP
    MT_FLAME_SMALL_TEMP,        // T_TEMPSMALLFLAME
    MT_FLAME_SMALL,             // T_PERMSMALLFLAME
    MT_FLAME_LARGE_TEMP,        // T_TEMPLARGEFLAME
    MT_FLAME_LARGE,             // T_PERMLARGEFLAME
    MT_DEMON_MASH,              // T_DEMON_MASH
    MT_DEMON2_MASH,             // T_DEMON2_MASH
    MT_ETTIN_MASH,              // T_ETTIN_MASH
    MT_CENTAUR_MASH,            // T_CENTAUR_MASH
    MT_THRUSTFLOOR_UP,          // T_THRUSTSPIKEUP
    MT_THRUSTFLOOR_DOWN,        // T_THRUSTSPIKEDOWN
    MT_WRAITHFX4,               // T_FLESH_DRIP1
    MT_WRAITHFX5,               // T_FLESH_DRIP2
    MT_WRAITHFX2                // T_SPARK_DRIP
};

// PRIVATE DATA DEFINITIONS ------------------------------------------------

// CODE --------------------------------------------------------------------

//==========================================================================
//
// EV_ThingProjectile
//
//==========================================================================

boolean EV_ThingProjectile(byte * args, boolean gravity)
{
    int tid;
    angle_t angle;
    int fineAngle;
    fixed_t speed;
    fixed_t vspeed;
    mobjtype_t moType;
    mobj_t *mobj;
    mobj_t *newMobj;
    int searcher;
    boolean success;

    success = false;
    searcher = -1;
    tid = args[0];
    moType = TranslateThingType[args[1]];
    if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL))
    {                           // Don't spawn monsters if -nomonsters
        return false;
    }
    angle = (int) args[2] << 24;
    fineAngle = angle >> ANGLETOFINESHIFT;
    speed = (int) args[3] << 13;
    vspeed = (int) args[4] << 13;
    while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
    {
        newMobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, moType);
        if (newMobj->info->seesound)
        {
            S_StartSound(newMobj, newMobj->info->seesound);
        }
        newMobj->target = mobj; // Originator
        newMobj->angle = angle;
        newMobj->momx = FixedMul(speed, finecosine[fineAngle]);
        newMobj->momy = FixedMul(speed, finesine[fineAngle]);
        newMobj->momz = vspeed;
        newMobj->flags2 |= MF2_DROPPED; // Don't respawn
        if (gravity == true)
        {
            newMobj->flags &= ~MF_NOGRAVITY;
            newMobj->flags2 |= MF2_LOGRAV;
        }
        if (P_CheckMissileSpawn(newMobj) == true)
        {
            success = true;
        }
    }
    return success;
}

//==========================================================================
//
// EV_ThingSpawn
//
//==========================================================================

boolean EV_ThingSpawn(byte * args, boolean fog)
{
    int tid;
    angle_t angle;
    mobj_t *mobj;
    mobj_t *newMobj;
    mobj_t *fogMobj;
    mobjtype_t moType;
    int searcher;
    boolean success;
    fixed_t z;

    success = false;
    searcher = -1;
    tid = args[0];
    moType = TranslateThingType[args[1]];
    if (nomonsters && (mobjinfo[moType].flags & MF_COUNTKILL))
    {                           // Don't spawn monsters if -nomonsters
        return false;
    }
    angle = (int) args[2] << 24;
    while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
    {
        if (mobjinfo[moType].flags2 & MF2_FLOATBOB)
        {
            z = mobj->z - mobj->floorz;
        }
        else
        {
            z = mobj->z;
        }
        newMobj = P_SpawnMobj(mobj->x, mobj->y, z, moType);
        if (P_TestMobjLocation(newMobj) == false)
        {                       // Didn't fit
            P_RemoveMobj(newMobj);
        }
        else
        {
            newMobj->angle = angle;
            if (fog == true)
            {
                fogMobj = P_SpawnMobj(mobj->x, mobj->y,
                                      mobj->z + TELEFOGHEIGHT, MT_TFOG);
                S_StartSound(fogMobj, SFX_TELEPORT);
            }
            newMobj->flags2 |= MF2_DROPPED;     // Don't respawn
            if (newMobj->flags2 & MF2_FLOATBOB)
            {
                newMobj->special1 = newMobj->z - newMobj->floorz;
            }
            success = true;
        }
    }
    return success;
}

//==========================================================================
//
// EV_ThingActivate
//
//==========================================================================

boolean EV_ThingActivate(int tid)
{
    mobj_t *mobj;
    int searcher;
    boolean success;

    success = false;
    searcher = -1;
    while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
    {
        if (ActivateThing(mobj) == true)
        {
            success = true;
        }
    }
    return success;
}

//==========================================================================
//
// EV_ThingDeactivate
//
//==========================================================================

boolean EV_ThingDeactivate(int tid)
{
    mobj_t *mobj;
    int searcher;
    boolean success;

    success = false;
    searcher = -1;
    while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
    {
        if (DeactivateThing(mobj) == true)
        {
            success = true;
        }
    }
    return success;
}

//==========================================================================
//
// EV_ThingRemove
//
//==========================================================================

boolean EV_ThingRemove(int tid)
{
    mobj_t *mobj;
    int searcher;
    boolean success;

    success = false;
    searcher = -1;
    while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
    {
        if (mobj->type == MT_BRIDGE)
        {
            A_BridgeRemove(mobj);
            return true;
        }
        P_RemoveMobj(mobj);
        success = true;
    }
    return success;
}

//==========================================================================
//
// EV_ThingDestroy
//
//==========================================================================

boolean EV_ThingDestroy(int tid)
{
    mobj_t *mobj;
    int searcher;
    boolean success;

    success = false;
    searcher = -1;
    while ((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL)
    {
        if (mobj->flags & MF_SHOOTABLE)
        {
            P_DamageMobj(mobj, NULL, NULL, 10000);
            success = true;
        }
    }
    return success;
}

//==========================================================================
//
// EV_ThingMove
//
// arg[0] = tid
// arg[1] = speed
// arg[2] = angle (255 = use mobj angle)
// arg[3] = distance (pixels>>2)
//
//==========================================================================

/*
boolean EV_ThingMove(byte *args)
{
	return false;
}
*/

//==========================================================================
//
// ActivateThing
//
//==========================================================================

static boolean ActivateThing(mobj_t * mobj)
{
    if (mobj->flags & MF_COUNTKILL)
    {                           // Monster
        if (mobj->flags2 & MF2_DORMANT)
        {
            mobj->flags2 &= ~MF2_DORMANT;
            mobj->tics = 1;
            return true;
        }
        return false;
    }
    switch (mobj->type)
    {
        case MT_ZTWINEDTORCH:
        case MT_ZTWINEDTORCH_UNLIT:
            P_SetMobjState(mobj, S_ZTWINEDTORCH_1);
            S_StartSound(mobj, SFX_IGNITE);
            break;
        case MT_ZWALLTORCH:
        case MT_ZWALLTORCH_UNLIT:
            P_SetMobjState(mobj, S_ZWALLTORCH1);
            S_StartSound(mobj, SFX_IGNITE);
            break;
        case MT_ZGEMPEDESTAL:
            P_SetMobjState(mobj, S_ZGEMPEDESTAL2);
            break;
        case MT_ZWINGEDSTATUENOSKULL:
            P_SetMobjState(mobj, S_ZWINGEDSTATUENOSKULL2);
            break;
        case MT_THRUSTFLOOR_UP:
        case MT_THRUSTFLOOR_DOWN:
            if (mobj->args[0] == 0)
            {
                S_StartSound(mobj, SFX_THRUSTSPIKE_LOWER);
                mobj->flags2 &= ~MF2_DONTDRAW;
                if (mobj->args[1])
                    P_SetMobjState(mobj, S_BTHRUSTRAISE1);
                else
                    P_SetMobjState(mobj, S_THRUSTRAISE1);
            }
            break;
        case MT_ZFIREBULL:
        case MT_ZFIREBULL_UNLIT:
            P_SetMobjState(mobj, S_ZFIREBULL_BIRTH);
            S_StartSound(mobj, SFX_IGNITE);
            break;
        case MT_ZBELL:
            if (mobj->health > 0)
            {
                P_DamageMobj(mobj, NULL, NULL, 10);     // 'ring' the bell
            }
            break;
        case MT_ZCAULDRON:
        case MT_ZCAULDRON_UNLIT:
            P_SetMobjState(mobj, S_ZCAULDRON1);
            S_StartSound(mobj, SFX_IGNITE);
            break;
        case MT_FLAME_SMALL:
            S_StartSound(mobj, SFX_IGNITE);
            P_SetMobjState(mobj, S_FLAME_SMALL1);
            break;
        case MT_FLAME_LARGE:
            S_StartSound(mobj, SFX_IGNITE);
            P_SetMobjState(mobj, S_FLAME_LARGE1);
            break;
        case MT_BAT_SPAWNER:
            P_SetMobjState(mobj, S_SPAWNBATS1);
            break;
        default:
            return false;
            break;
    }
    return true;
}

//==========================================================================
//
// DeactivateThing
//
//==========================================================================

static boolean DeactivateThing(mobj_t * mobj)
{
    if (mobj->flags & MF_COUNTKILL)
    {                           // Monster
        if (!(mobj->flags2 & MF2_DORMANT))
        {
            mobj->flags2 |= MF2_DORMANT;
            mobj->tics = -1;
            return true;
        }
        return false;
    }
    switch (mobj->type)
    {
        case MT_ZTWINEDTORCH:
        case MT_ZTWINEDTORCH_UNLIT:
            P_SetMobjState(mobj, S_ZTWINEDTORCH_UNLIT);
            break;
        case MT_ZWALLTORCH:
        case MT_ZWALLTORCH_UNLIT:
            P_SetMobjState(mobj, S_ZWALLTORCH_U);
            break;
        case MT_THRUSTFLOOR_UP:
        case MT_THRUSTFLOOR_DOWN:
            if (mobj->args[0] == 1)
            {
                S_StartSound(mobj, SFX_THRUSTSPIKE_RAISE);
                if (mobj->args[1])
                    P_SetMobjState(mobj, S_BTHRUSTLOWER);
                else
                    P_SetMobjState(mobj, S_THRUSTLOWER);
            }
            break;
        case MT_ZFIREBULL:
        case MT_ZFIREBULL_UNLIT:
            P_SetMobjState(mobj, S_ZFIREBULL_DEATH);
            break;
        case MT_ZCAULDRON:
        case MT_ZCAULDRON_UNLIT:
            P_SetMobjState(mobj, S_ZCAULDRON_U);
            break;
        case MT_FLAME_SMALL:
            P_SetMobjState(mobj, S_FLAME_SDORM1);
            break;
        case MT_FLAME_LARGE:
            P_SetMobjState(mobj, S_FLAME_LDORM1);
            break;
        case MT_BAT_SPAWNER:
            P_SetMobjState(mobj, S_SPAWNBATS_OFF);
            break;
        default:
            return false;
            break;
    }
    return true;
}