Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
298 serge 1
// Emacs style mode select   -*- C++ -*-
2
//-----------------------------------------------------------------------------
3
//
4
// $Id:$
5
//
6
// Copyright (C) 1993-1996 by id Software, Inc.
7
//
8
// This source is available for distribution and/or modification
9
// only under the terms of the DOOM Source Code License as
10
// published by id Software. All rights reserved.
11
//
12
// The source is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15
// for more details.
16
//
17
// $Log:$
18
//
19
// DESCRIPTION:
20
//	Handling interactions (i.e., collisions).
21
//
22
//-----------------------------------------------------------------------------
23
 
24
 
25
static const char
26
rcsid[] = "$Id: p_inter.c,v 1.4 1997/02/03 22:45:11 b1 Exp $";
27
 
28
 
29
// Data.
30
#include "doomdef.h"
31
#include "dstrings.h"
32
#include "sounds.h"
33
 
34
#include "doomstat.h"
35
 
36
#include "m_random.h"
37
#include "i_system.h"
38
 
39
#include "am_map.h"
40
 
41
#include "p_local.h"
42
 
43
#include "s_sound.h"
44
 
45
#ifdef __GNUG__
46
#pragma implementation "p_inter.h"
47
#endif
48
#include "p_inter.h"
49
 
50
 
51
#define BONUSADD	6
52
 
53
 
54
 
55
 
56
// a weapon is found with two clip loads,
57
// a big item has five clip loads
58
int	maxammo[NUMAMMO] = {200, 50, 300, 50};
59
int	clipammo[NUMAMMO] = {10, 4, 20, 1};
60
 
61
 
62
//
63
// GET STUFF
64
//
65
 
66
//
67
// P_GiveAmmo
68
// Num is the number of clip loads,
69
// not the individual count (0= 1/2 clip).
70
// Returns false if the ammo can't be picked up at all
71
//
72
 
73
boolean
74
P_GiveAmmo
75
( player_t*	player,
76
  ammotype_t	ammo,
77
  int		num )
78
{
79
    int		oldammo;
80
 
81
    if (ammo == am_noammo)
82
	return false;
83
 
84
    if (ammo < 0 || ammo > NUMAMMO)
85
	I_Error ("P_GiveAmmo: bad type %i", ammo);
86
 
87
    if ( player->ammo[ammo] == player->maxammo[ammo]  )
88
	return false;
89
 
90
    if (num)
91
	num *= clipammo[ammo];
92
    else
93
	num = clipammo[ammo]/2;
94
 
95
    if (gameskill == sk_baby
96
	|| gameskill == sk_nightmare)
97
    {
98
	// give double ammo in trainer mode,
99
	// you'll need in nightmare
100
	num <<= 1;
101
    }
102
 
103
 
104
    oldammo = player->ammo[ammo];
105
    player->ammo[ammo] += num;
106
 
107
    if (player->ammo[ammo] > player->maxammo[ammo])
108
	player->ammo[ammo] = player->maxammo[ammo];
109
 
110
    // If non zero ammo,
111
    // don't change up weapons,
112
    // player was lower on purpose.
113
    if (oldammo)
114
	return true;
115
 
116
    // We were down to zero,
117
    // so select a new weapon.
118
    // Preferences are not user selectable.
119
    switch (ammo)
120
    {
121
      case am_clip:
122
	if (player->readyweapon == wp_fist)
123
	{
124
	    if (player->weaponowned[wp_chaingun])
125
		player->pendingweapon = wp_chaingun;
126
	    else
127
		player->pendingweapon = wp_pistol;
128
	}
129
	break;
130
 
131
      case am_shell:
132
	if (player->readyweapon == wp_fist
133
	    || player->readyweapon == wp_pistol)
134
	{
135
	    if (player->weaponowned[wp_shotgun])
136
		player->pendingweapon = wp_shotgun;
137
	}
138
	break;
139
 
140
      case am_cell:
141
	if (player->readyweapon == wp_fist
142
	    || player->readyweapon == wp_pistol)
143
	{
144
	    if (player->weaponowned[wp_plasma])
145
		player->pendingweapon = wp_plasma;
146
	}
147
	break;
148
 
149
      case am_misl:
150
	if (player->readyweapon == wp_fist)
151
	{
152
	    if (player->weaponowned[wp_missile])
153
		player->pendingweapon = wp_missile;
154
	}
155
      default:
156
	break;
157
    }
158
 
159
    return true;
160
}
161
 
162
 
163
//
164
// P_GiveWeapon
165
// The weapon name may have a MF_DROPPED flag ored in.
166
//
167
boolean
168
P_GiveWeapon
169
( player_t*	player,
170
  weapontype_t	weapon,
171
  boolean	dropped )
172
{
173
    boolean	gaveammo;
174
    boolean	gaveweapon;
175
 
176
    if (netgame
177
	&& (deathmatch!=2)
178
	 && !dropped )
179
    {
180
	// leave placed weapons forever on net games
181
	if (player->weaponowned[weapon])
182
	    return false;
183
 
184
	player->bonuscount += BONUSADD;
185
	player->weaponowned[weapon] = true;
186
 
187
	if (deathmatch)
188
	    P_GiveAmmo (player, weaponinfo[weapon].ammo, 5);
189
	else
190
	    P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
191
	player->pendingweapon = weapon;
192
 
193
	if (player == &players[consoleplayer])
194
	    S_StartSound (NULL, sfx_wpnup);
195
	return false;
196
    }
197
 
198
    if (weaponinfo[weapon].ammo != am_noammo)
199
    {
200
	// give one clip with a dropped weapon,
201
	// two clips with a found weapon
202
	if (dropped)
203
	    gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1);
204
	else
205
	    gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
206
    }
207
    else
208
	gaveammo = false;
209
 
210
    if (player->weaponowned[weapon])
211
	gaveweapon = false;
212
    else
213
    {
214
	gaveweapon = true;
215
	player->weaponowned[weapon] = true;
216
	player->pendingweapon = weapon;
217
    }
218
 
219
    return (gaveweapon || gaveammo);
220
}
221
 
222
 
223
 
224
//
225
// P_GiveBody
226
// Returns false if the body isn't needed at all
227
//
228
boolean
229
P_GiveBody
230
( player_t*	player,
231
  int		num )
232
{
233
    if (player->health >= MAXHEALTH)
234
	return false;
235
 
236
    player->health += num;
237
    if (player->health > MAXHEALTH)
238
	player->health = MAXHEALTH;
239
    player->mo->health = player->health;
240
 
241
    return true;
242
}
243
 
244
 
245
 
246
//
247
// P_GiveArmor
248
// Returns false if the armor is worse
249
// than the current armor.
250
//
251
boolean
252
P_GiveArmor
253
( player_t*	player,
254
  int		armortype )
255
{
256
    int		hits;
257
 
258
    hits = armortype*100;
259
    if (player->armorpoints >= hits)
260
	return false;	// don't pick up
261
 
262
    player->armortype = armortype;
263
    player->armorpoints = hits;
264
 
265
    return true;
266
}
267
 
268
 
269
 
270
//
271
// P_GiveCard
272
//
273
void
274
P_GiveCard
275
( player_t*	player,
276
  card_t	card )
277
{
278
    if (player->cards[card])
279
	return;
280
 
281
    player->bonuscount = BONUSADD;
282
    player->cards[card] = 1;
283
}
284
 
285
 
286
//
287
// P_GivePower
288
//
289
boolean
290
P_GivePower
291
( player_t*	player,
292
  int /*powertype_t*/	power )
293
{
294
    if (power == pw_invulnerability)
295
    {
296
	player->powers[power] = INVULNTICS;
297
	return true;
298
    }
299
 
300
    if (power == pw_invisibility)
301
    {
302
	player->powers[power] = INVISTICS;
303
	player->mo->flags |= MF_SHADOW;
304
	return true;
305
    }
306
 
307
    if (power == pw_infrared)
308
    {
309
	player->powers[power] = INFRATICS;
310
	return true;
311
    }
312
 
313
    if (power == pw_ironfeet)
314
    {
315
	player->powers[power] = IRONTICS;
316
	return true;
317
    }
318
 
319
    if (power == pw_strength)
320
    {
321
	P_GiveBody (player, 100);
322
	player->powers[power] = 1;
323
	return true;
324
    }
325
 
326
    if (player->powers[power])
327
	return false;	// already got it
328
 
329
    player->powers[power] = 1;
330
    return true;
331
}
332
 
333
 
334
 
335
//
336
// P_TouchSpecialThing
337
//
338
void
339
P_TouchSpecialThing
340
( mobj_t*	special,
341
  mobj_t*	toucher )
342
{
343
    player_t*	player;
344
    int		i;
345
    fixed_t	delta;
346
    int		sound;
347
 
348
    delta = special->z - toucher->z;
349
 
350
    if (delta > toucher->height
351
	|| delta < -8*FRACUNIT)
352
    {
353
	// out of reach
354
	return;
355
    }
356
 
357
 
358
    sound = sfx_itemup;
359
    player = toucher->player;
360
 
361
    // Dead thing touching.
362
    // Can happen with a sliding player corpse.
363
    if (toucher->health <= 0)
364
	return;
365
 
366
    // Identify by sprite.
367
    switch (special->sprite)
368
    {
369
	// armor
370
      case SPR_ARM1:
371
	if (!P_GiveArmor (player, 1))
372
	    return;
373
	player->message = GOTARMOR;
374
	break;
375
 
376
      case SPR_ARM2:
377
	if (!P_GiveArmor (player, 2))
378
	    return;
379
	player->message = GOTMEGA;
380
	break;
381
 
382
	// bonus items
383
      case SPR_BON1:
384
	player->health++;		// can go over 100%
385
	if (player->health > 200)
386
	    player->health = 200;
387
	player->mo->health = player->health;
388
	player->message = GOTHTHBONUS;
389
	break;
390
 
391
      case SPR_BON2:
392
	player->armorpoints++;		// can go over 100%
393
	if (player->armorpoints > 200)
394
	    player->armorpoints = 200;
395
	if (!player->armortype)
396
	    player->armortype = 1;
397
	player->message = GOTARMBONUS;
398
	break;
399
 
400
      case SPR_SOUL:
401
	player->health += 100;
402
	if (player->health > 200)
403
	    player->health = 200;
404
	player->mo->health = player->health;
405
	player->message = GOTSUPER;
406
	sound = sfx_getpow;
407
	break;
408
 
409
      case SPR_MEGA:
410
	if (gamemode != commercial)
411
	    return;
412
	player->health = 200;
413
	player->mo->health = player->health;
414
	P_GiveArmor (player,2);
415
	player->message = GOTMSPHERE;
416
	sound = sfx_getpow;
417
	break;
418
 
419
	// cards
420
	// leave cards for everyone
421
      case SPR_BKEY:
422
	if (!player->cards[it_bluecard])
423
	    player->message = GOTBLUECARD;
424
	P_GiveCard (player, it_bluecard);
425
	if (!netgame)
426
	    break;
427
	return;
428
 
429
      case SPR_YKEY:
430
	if (!player->cards[it_yellowcard])
431
	    player->message = GOTYELWCARD;
432
	P_GiveCard (player, it_yellowcard);
433
	if (!netgame)
434
	    break;
435
	return;
436
 
437
      case SPR_RKEY:
438
	if (!player->cards[it_redcard])
439
	    player->message = GOTREDCARD;
440
	P_GiveCard (player, it_redcard);
441
	if (!netgame)
442
	    break;
443
	return;
444
 
445
      case SPR_BSKU:
446
	if (!player->cards[it_blueskull])
447
	    player->message = GOTBLUESKUL;
448
	P_GiveCard (player, it_blueskull);
449
	if (!netgame)
450
	    break;
451
	return;
452
 
453
      case SPR_YSKU:
454
	if (!player->cards[it_yellowskull])
455
	    player->message = GOTYELWSKUL;
456
	P_GiveCard (player, it_yellowskull);
457
	if (!netgame)
458
	    break;
459
	return;
460
 
461
      case SPR_RSKU:
462
	if (!player->cards[it_redskull])
463
	    player->message = GOTREDSKULL;
464
	P_GiveCard (player, it_redskull);
465
	if (!netgame)
466
	    break;
467
	return;
468
 
469
	// medikits, heals
470
      case SPR_STIM:
471
	if (!P_GiveBody (player, 10))
472
	    return;
473
	player->message = GOTSTIM;
474
	break;
475
 
476
      case SPR_MEDI:
477
	if (!P_GiveBody (player, 25))
478
	    return;
479
 
480
	if (player->health < 25)
481
	    player->message = GOTMEDINEED;
482
	else
483
	    player->message = GOTMEDIKIT;
484
	break;
485
 
486
 
487
	// power ups
488
      case SPR_PINV:
489
	if (!P_GivePower (player, pw_invulnerability))
490
	    return;
491
	player->message = GOTINVUL;
492
	sound = sfx_getpow;
493
	break;
494
 
495
      case SPR_PSTR:
496
	if (!P_GivePower (player, pw_strength))
497
	    return;
498
	player->message = GOTBERSERK;
499
	if (player->readyweapon != wp_fist)
500
	    player->pendingweapon = wp_fist;
501
	sound = sfx_getpow;
502
	break;
503
 
504
      case SPR_PINS:
505
	if (!P_GivePower (player, pw_invisibility))
506
	    return;
507
	player->message = GOTINVIS;
508
	sound = sfx_getpow;
509
	break;
510
 
511
      case SPR_SUIT:
512
	if (!P_GivePower (player, pw_ironfeet))
513
	    return;
514
	player->message = GOTSUIT;
515
	sound = sfx_getpow;
516
	break;
517
 
518
      case SPR_PMAP:
519
	if (!P_GivePower (player, pw_allmap))
520
	    return;
521
	player->message = GOTMAP;
522
	sound = sfx_getpow;
523
	break;
524
 
525
      case SPR_PVIS:
526
	if (!P_GivePower (player, pw_infrared))
527
	    return;
528
	player->message = GOTVISOR;
529
	sound = sfx_getpow;
530
	break;
531
 
532
	// ammo
533
      case SPR_CLIP:
534
	if (special->flags & MF_DROPPED)
535
	{
536
	    if (!P_GiveAmmo (player,am_clip,0))
537
		return;
538
	}
539
	else
540
	{
541
	    if (!P_GiveAmmo (player,am_clip,1))
542
		return;
543
	}
544
	player->message = GOTCLIP;
545
	break;
546
 
547
      case SPR_AMMO:
548
	if (!P_GiveAmmo (player, am_clip,5))
549
	    return;
550
	player->message = GOTCLIPBOX;
551
	break;
552
 
553
      case SPR_ROCK:
554
	if (!P_GiveAmmo (player, am_misl,1))
555
	    return;
556
	player->message = GOTROCKET;
557
	break;
558
 
559
      case SPR_BROK:
560
	if (!P_GiveAmmo (player, am_misl,5))
561
	    return;
562
	player->message = GOTROCKBOX;
563
	break;
564
 
565
      case SPR_CELL:
566
	if (!P_GiveAmmo (player, am_cell,1))
567
	    return;
568
	player->message = GOTCELL;
569
	break;
570
 
571
      case SPR_CELP:
572
	if (!P_GiveAmmo (player, am_cell,5))
573
	    return;
574
	player->message = GOTCELLBOX;
575
	break;
576
 
577
      case SPR_SHEL:
578
	if (!P_GiveAmmo (player, am_shell,1))
579
	    return;
580
	player->message = GOTSHELLS;
581
	break;
582
 
583
      case SPR_SBOX:
584
	if (!P_GiveAmmo (player, am_shell,5))
585
	    return;
586
	player->message = GOTSHELLBOX;
587
	break;
588
 
589
      case SPR_BPAK:
590
	if (!player->backpack)
591
	{
592
	    for (i=0 ; i
593
		player->maxammo[i] *= 2;
594
	    player->backpack = true;
595
	}
596
	for (i=0 ; i
597
	    P_GiveAmmo (player, i, 1);
598
	player->message = GOTBACKPACK;
599
	break;
600
 
601
	// weapons
602
      case SPR_BFUG:
603
	if (!P_GiveWeapon (player, wp_bfg, false) )
604
	    return;
605
	player->message = GOTBFG9000;
606
	sound = sfx_wpnup;
607
	break;
608
 
609
      case SPR_MGUN:
610
	if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) )
611
	    return;
612
	player->message = GOTCHAINGUN;
613
	sound = sfx_wpnup;
614
	break;
615
 
616
      case SPR_CSAW:
617
	if (!P_GiveWeapon (player, wp_chainsaw, false) )
618
	    return;
619
	player->message = GOTCHAINSAW;
620
	sound = sfx_wpnup;
621
	break;
622
 
623
      case SPR_LAUN:
624
	if (!P_GiveWeapon (player, wp_missile, false) )
625
	    return;
626
	player->message = GOTLAUNCHER;
627
	sound = sfx_wpnup;
628
	break;
629
 
630
      case SPR_PLAS:
631
	if (!P_GiveWeapon (player, wp_plasma, false) )
632
	    return;
633
	player->message = GOTPLASMA;
634
	sound = sfx_wpnup;
635
	break;
636
 
637
      case SPR_SHOT:
638
	if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) )
639
	    return;
640
	player->message = GOTSHOTGUN;
641
	sound = sfx_wpnup;
642
	break;
643
 
644
      case SPR_SGN2:
645
	if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) )
646
	    return;
647
	player->message = GOTSHOTGUN2;
648
	sound = sfx_wpnup;
649
	break;
650
 
651
      default:
652
	I_Error ("P_SpecialThing: Unknown gettable thing");
653
    }
654
 
655
    if (special->flags & MF_COUNTITEM)
656
	player->itemcount++;
657
    P_RemoveMobj (special);
658
    player->bonuscount += BONUSADD;
659
    if (player == &players[consoleplayer])
660
	S_StartSound (NULL, sound);
661
}
662
 
663
 
664
//
665
// KillMobj
666
//
667
void
668
P_KillMobj
669
( mobj_t*	source,
670
  mobj_t*	target )
671
{
672
    mobjtype_t	item;
673
    mobj_t*	mo;
674
 
675
    target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
676
 
677
    if (target->type != MT_SKULL)
678
	target->flags &= ~MF_NOGRAVITY;
679
 
680
    target->flags |= MF_CORPSE|MF_DROPOFF;
681
    target->height >>= 2;
682
 
683
    if (source && source->player)
684
    {
685
	// count for intermission
686
	if (target->flags & MF_COUNTKILL)
687
	    source->player->killcount++;
688
 
689
	if (target->player)
690
	    source->player->frags[target->player-players]++;
691
    }
692
    else if (!netgame && (target->flags & MF_COUNTKILL) )
693
    {
694
	// count all monster deaths,
695
	// even those caused by other monsters
696
	players[0].killcount++;
697
    }
698
 
699
    if (target->player)
700
    {
701
	// count environment kills against you
702
	if (!source)
703
	    target->player->frags[target->player-players]++;
704
 
705
	target->flags &= ~MF_SOLID;
706
	target->player->playerstate = PST_DEAD;
707
	P_DropWeapon (target->player);
708
 
709
	if (target->player == &players[consoleplayer]
710
	    && automapactive)
711
	{
712
	    // don't die in auto map,
713
	    // switch view prior to dying
714
	    AM_Stop ();
715
	}
716
 
717
    }
718
 
719
    if (target->health < -target->info->spawnhealth
720
	&& target->info->xdeathstate)
721
    {
722
	P_SetMobjState (target, target->info->xdeathstate);
723
    }
724
    else
725
	P_SetMobjState (target, target->info->deathstate);
726
    target->tics -= P_Random()&3;
727
 
728
    if (target->tics < 1)
729
	target->tics = 1;
730
 
731
    //	I_StartSound (&actor->r, actor->info->deathsound);
732
 
733
 
734
    // Drop stuff.
735
    // This determines the kind of object spawned
736
    // during the death frame of a thing.
737
    switch (target->type)
738
    {
739
      case MT_WOLFSS:
740
      case MT_POSSESSED:
741
	item = MT_CLIP;
742
	break;
743
 
744
      case MT_SHOTGUY:
745
	item = MT_SHOTGUN;
746
	break;
747
 
748
      case MT_CHAINGUY:
749
	item = MT_CHAINGUN;
750
	break;
751
 
752
      default:
753
	return;
754
    }
755
 
756
    mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item);
757
    mo->flags |= MF_DROPPED;	// special versions of items
758
}
759
 
760
 
761
 
762
 
763
//
764
// P_DamageMobj
765
// Damages both enemies and players
766
// "inflictor" is the thing that caused the damage
767
//  creature or missile, can be NULL (slime, etc)
768
// "source" is the thing to target after taking damage
769
//  creature or NULL
770
// Source and inflictor are the same for melee attacks.
771
// Source can be NULL for slime, barrel explosions
772
// and other environmental stuff.
773
//
774
void
775
P_DamageMobj
776
( mobj_t*	target,
777
  mobj_t*	inflictor,
778
  mobj_t*	source,
779
  int 		damage )
780
{
781
    unsigned	ang;
782
    int		saved;
783
    player_t*	player;
784
    fixed_t	thrust;
785
    int		temp;
786
 
787
    if ( !(target->flags & MF_SHOOTABLE) )
788
	return;	// shouldn't happen...
789
 
790
    if (target->health <= 0)
791
	return;
792
 
793
    if ( target->flags & MF_SKULLFLY )
794
    {
795
	target->momx = target->momy = target->momz = 0;
796
    }
797
 
798
    player = target->player;
799
    if (player && gameskill == sk_baby)
800
	damage >>= 1; 	// take half damage in trainer mode
801
 
802
 
803
    // Some close combat weapons should not
804
    // inflict thrust and push the victim out of reach,
805
    // thus kick away unless using the chainsaw.
806
    if (inflictor
807
	&& !(target->flags & MF_NOCLIP)
808
	&& (!source
809
	    || !source->player
810
	    || source->player->readyweapon != wp_chainsaw))
811
    {
812
	ang = R_PointToAngle2 ( inflictor->x,
813
				inflictor->y,
814
				target->x,
815
				target->y);
816
 
817
	thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
818
 
819
	// make fall forwards sometimes
820
	if ( damage < 40
821
	     && damage > target->health
822
	     && target->z - inflictor->z > 64*FRACUNIT
823
	     && (P_Random ()&1) )
824
	{
825
	    ang += ANG180;
826
	    thrust *= 4;
827
	}
828
 
829
	ang >>= ANGLETOFINESHIFT;
830
	target->momx += FixedMul (thrust, finecosine[ang]);
831
	target->momy += FixedMul (thrust, finesine[ang]);
832
    }
833
 
834
    // player specific
835
    if (player)
836
    {
837
	// end of game hell hack
838
	if (target->subsector->sector->special == 11
839
	    && damage >= target->health)
840
	{
841
	    damage = target->health - 1;
842
	}
843
 
844
 
845
	// Below certain threshold,
846
	// ignore damage in GOD mode, or with INVUL power.
847
	if ( damage < 1000
848
	     && ( (player->cheats&CF_GODMODE)
849
		  || player->powers[pw_invulnerability] ) )
850
	{
851
	    return;
852
	}
853
 
854
	if (player->armortype)
855
	{
856
	    if (player->armortype == 1)
857
		saved = damage/3;
858
	    else
859
		saved = damage/2;
860
 
861
	    if (player->armorpoints <= saved)
862
	    {
863
		// armor is used up
864
		saved = player->armorpoints;
865
		player->armortype = 0;
866
	    }
867
	    player->armorpoints -= saved;
868
	    damage -= saved;
869
	}
870
	player->health -= damage; 	// mirror mobj health here for Dave
871
	if (player->health < 0)
872
	    player->health = 0;
873
 
874
	player->attacker = source;
875
	player->damagecount += damage;	// add damage after armor / invuln
876
 
877
	if (player->damagecount > 100)
878
	    player->damagecount = 100;	// teleport stomp does 10k points...
879
 
880
	temp = damage < 100 ? damage : 100;
881
 
882
	if (player == &players[consoleplayer])
883
	    I_Tactile (40,10,40+temp*2);
884
    }
885
 
886
    // do the damage
887
    target->health -= damage;
888
    if (target->health <= 0)
889
    {
890
	P_KillMobj (source, target);
891
	return;
892
    }
893
 
894
    if ( (P_Random () < target->info->painchance)
895
	 && !(target->flags&MF_SKULLFLY) )
896
    {
897
	target->flags |= MF_JUSTHIT;	// fight back!
898
 
899
	P_SetMobjState (target, target->info->painstate);
900
    }
901
 
902
    target->reactiontime = 0;		// we're awake now...
903
 
904
    if ( (!target->threshold || target->type == MT_VILE)
905
	 && source && source != target
906
	 && source->type != MT_VILE)
907
    {
908
	// if not intent on another player,
909
	// chase after this one
910
	target->target = source;
911
	target->threshold = BASETHRESHOLD;
912
	if (target->state == &states[target->info->spawnstate]
913
	    && target->info->seestate != S_NULL)
914
	    P_SetMobjState (target, target->info->seestate);
915
    }
916
 
917
}
918