1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474 |
- // P_inter.c
- #include "DoomDef.h"
- #include "P_local.h"
- #include "soundst.h"
- #define BONUSADD 6
- int WeaponValue[] =
- {
- 1, // staff
- 3, // goldwand
- 4, // crossbow
- 5, // blaster
- 6, // skullrod
- 7, // phoenixrod
- 8, // mace
- 2, // gauntlets
- 0 // beak
- };
- int maxammo[NUMAMMO] =
- {
- 100, // gold wand
- 50, // crossbow
- 200, // blaster
- 200, // skull rod
- 20, // phoenix rod
- 150 // mace
- };
- static int GetWeaponAmmo[NUMWEAPONS] =
- {
- 0, // staff
- 25, // gold wand
- 10, // crossbow
- 30, // blaster
- 50, // skull rod
- 2, // phoenix rod
- 50, // mace
- 0, // gauntlets
- 0 // beak
- };
- static weapontype_t GetAmmoChange[] =
- {
- wp_goldwand,
- wp_crossbow,
- wp_blaster,
- wp_skullrod,
- wp_phoenixrod,
- wp_mace
- };
- /*
- static boolean GetAmmoChangePL1[NUMWEAPONS][NUMAMMO] =
- {
- // staff
- {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace},
- // gold wand
- {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace},
- // crossbow
- {-1, -1, wp_blaster, wp_skullrod, -1, -1},
- // blaster
- {-1, -1, -1, -1, -1, -1},
- // skull rod
- {-1, -1, -1, -1, -1, -1},
- // phoenix rod
- {-1, -1, -1, -1, -1, -1},
- // mace
- {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1},
- // gauntlets
- {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, wp_mace}
- };
- */
- /*
- static boolean GetAmmoChangePL2[NUMWEAPONS][NUMAMMO] =
- {
- // staff
- {wp_goldwand, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod,
- wp_mace},
- // gold wand
- {-1, wp_crossbow, wp_blaster, wp_skullrod, wp_phoenixrod, wp_mace},
- // crossbow
- {-1, -1, wp_blaster, wp_skullrod, wp_phoenixrod, -1},
- // blaster
- {-1, -1, -1, wp_skullrod, wp_phoenixrod, -1},
- // skull rod
- {-1, -1, -1, -1, -1, -1},
- // phoenix rod
- {-1, -1, -1, -1, -1, -1},
- // mace
- {-1, wp_crossbow, wp_blaster, wp_skullrod, -1, -1},
- // gauntlets
- {-1, -1, -1, wp_skullrod, wp_phoenixrod, wp_mace}
- };
- */
- //--------------------------------------------------------------------------
- //
- // PROC P_SetMessage
- //
- //--------------------------------------------------------------------------
- boolean ultimatemsg;
- void P_SetMessage(player_t *player, char *message, boolean ultmsg)
- {
- extern boolean messageson;
-
- if((ultimatemsg || !messageson) && !ultmsg)
- {
- return;
- }
- player->message = message;
- player->messageTics = MESSAGETICS;
- BorderTopRefresh = true;
- if(ultmsg)
- {
- ultimatemsg = true;
- }
- }
- //--------------------------------------------------------------------------
- //
- // FUNC P_GiveAmmo
- //
- // Returns true if the player accepted the ammo, false if it was
- // refused (player has maxammo[ammo]).
- //
- //--------------------------------------------------------------------------
- boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int count)
- {
- int prevAmmo;
- //weapontype_t changeWeapon;
- if(ammo == am_noammo)
- {
- return(false);
- }
- if(ammo < 0 || ammo > NUMAMMO)
- {
- I_Error("P_GiveAmmo: bad type %i", ammo);
- }
- if(player->ammo[ammo] == player->maxammo[ammo])
- {
- return(false);
- }
- if(gameskill == sk_baby || gameskill == sk_nightmare)
- { // extra ammo in baby mode and nightmare mode
- count += count>>1;
- }
- prevAmmo = player->ammo[ammo];
- player->ammo[ammo] += count;
- if(player->ammo[ammo] > player->maxammo[ammo])
- {
- player->ammo[ammo] = player->maxammo[ammo];
- }
- if(prevAmmo)
- {
- // Don't attempt to change weapons if the player already had
- // ammo of the type just given
- return(true);
- }
- if(player->readyweapon == wp_staff
- || player->readyweapon == wp_gauntlets)
- {
- if(player->weaponowned[GetAmmoChange[ammo]])
- {
- player->pendingweapon = GetAmmoChange[ammo];
- }
- }
- /*
- if(player->powers[pw_weaponlevel2])
- {
- changeWeapon = GetAmmoChangePL2[player->readyweapon][ammo];
- }
- else
- {
- changeWeapon = GetAmmoChangePL1[player->readyweapon][ammo];
- }
- if(changeWeapon != -1)
- {
- if(player->weaponowned[changeWeapon])
- {
- player->pendingweapon = changeWeapon;
- }
- }
- */
- return(true);
- }
- //--------------------------------------------------------------------------
- //
- // FUNC P_GiveWeapon
- //
- // Returns true if the weapon or its ammo was accepted.
- //
- //--------------------------------------------------------------------------
- boolean P_GiveWeapon(player_t *player, weapontype_t weapon)
- {
- boolean gaveAmmo;
- boolean gaveWeapon;
- if(netgame && !deathmatch)
- { // Cooperative net-game
- if(player->weaponowned[weapon])
- {
- return(false);
- }
- player->bonuscount += BONUSADD;
- player->weaponowned[weapon] = true;
- P_GiveAmmo(player, wpnlev1info[weapon].ammo,
- GetWeaponAmmo[weapon]);
- player->pendingweapon = weapon;
- if(player == &players[consoleplayer])
- {
- S_StartSound(NULL, sfx_wpnup);
- }
- return(false);
- }
- gaveAmmo = P_GiveAmmo(player, wpnlev1info[weapon].ammo,
- GetWeaponAmmo[weapon]);
- if(player->weaponowned[weapon])
- {
- gaveWeapon = false;
- }
- else
- {
- gaveWeapon = true;
- player->weaponowned[weapon] = true;
- if(WeaponValue[weapon] > WeaponValue[player->readyweapon])
- { // Only switch to more powerful weapons
- player->pendingweapon = weapon;
- }
- }
- return(gaveWeapon || gaveAmmo);
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_GiveBody
- //
- // Returns false if the body isn't needed at all.
- //
- //---------------------------------------------------------------------------
- boolean P_GiveBody(player_t *player, int num)
- {
- int max;
- max = MAXHEALTH;
- if(player->chickenTics)
- {
- max = MAXCHICKENHEALTH;
- }
- if(player->health >= max)
- {
- return(false);
- }
- player->health += num;
- if(player->health > max)
- {
- player->health = max;
- }
- player->mo->health = player->health;
- return(true);
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_GiveArmor
- //
- // Returns false if the armor is worse than the current armor.
- //
- //---------------------------------------------------------------------------
- boolean P_GiveArmor(player_t *player, int armortype)
- {
- int hits;
- hits = armortype*100;
- if(player->armorpoints >= hits)
- {
- return(false);
- }
- player->armortype = armortype;
- player->armorpoints = hits;
- return(true);
- }
- //---------------------------------------------------------------------------
- //
- // PROC P_GiveKey
- //
- //---------------------------------------------------------------------------
- void P_GiveKey(player_t *player, keytype_t key)
- {
- extern int playerkeys;
- extern vertex_t KeyPoints[];
-
- if(player->keys[key])
- {
- return;
- }
- if(player == &players[consoleplayer])
- {
- playerkeys |= 1<<key;
- KeyPoints[key].x = 0;
- KeyPoints[key].y = 0;
- }
- player->bonuscount = BONUSADD;
- player->keys[key] = true;
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_GivePower
- //
- // Returns true if power accepted.
- //
- //---------------------------------------------------------------------------
- boolean P_GivePower(player_t *player, powertype_t power)
- {
- if(power == pw_invulnerability)
- {
- if(player->powers[power] > BLINKTHRESHOLD)
- { // Already have it
- return(false);
- }
- player->powers[power] = INVULNTICS;
- return(true);
- }
- if(power == pw_weaponlevel2)
- {
- if(player->powers[power] > BLINKTHRESHOLD)
- { // Already have it
- return(false);
- }
- player->powers[power] = WPNLEV2TICS;
- return(true);
- }
- if(power == pw_invisibility)
- {
- if(player->powers[power] > BLINKTHRESHOLD)
- { // Already have it
- return(false);
- }
- player->powers[power] = INVISTICS;
- player->mo->flags |= MF_SHADOW;
- return(true);
- }
- if(power == pw_flight)
- {
- if(player->powers[power] > BLINKTHRESHOLD)
- { // Already have it
- return(false);
- }
- player->powers[power] = FLIGHTTICS;
- player->mo->flags2 |= MF2_FLY;
- player->mo->flags |= MF_NOGRAVITY;
- if(player->mo->z <= player->mo->floorz)
- {
- player->flyheight = 10; // thrust the player in the air a bit
- }
- return(true);
- }
- if(power == pw_infrared)
- {
- if(player->powers[power] > BLINKTHRESHOLD)
- { // Already have it
- return(false);
- }
- player->powers[power] = INFRATICS;
- return(true);
- }
- /*
- if(power == pw_ironfeet)
- {
- player->powers[power] = IRONTICS;
- return(true);
- }
- if(power == pw_strength)
- {
- P_GiveBody(player, 100);
- player->powers[power] = 1;
- return(true);
- }
- */
- if(player->powers[power])
- {
- return(false); // already got it
- }
- player->powers[power] = 1;
- return(true);
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_GiveArtifact
- //
- // Returns true if artifact accepted.
- //
- //---------------------------------------------------------------------------
- boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo)
- {
- int i;
- i = 0;
- while(player->inventory[i].type != arti && i < player->inventorySlotNum)
- {
- i++;
- }
- if(i == player->inventorySlotNum)
- {
- player->inventory[i].count = 1;
- player->inventory[i].type = arti;
- player->inventorySlotNum++;
- }
- else
- {
- if(player->inventory[i].count >= 16)
- { // Player already has 16 of this item
- return(false);
- }
- player->inventory[i].count++;
- }
- if(player->artifactCount == 0)
- {
- player->readyArtifact = arti;
- }
- player->artifactCount++;
- if(mo && (mo->flags&MF_COUNTITEM))
- {
- player->itemcount++;
- }
- return(true);
- }
- //---------------------------------------------------------------------------
- //
- // PROC P_SetDormantArtifact
- //
- // Removes the MF_SPECIAL flag, and initiates the artifact pickup
- // animation.
- //
- //---------------------------------------------------------------------------
- void P_SetDormantArtifact(mobj_t *arti)
- {
- arti->flags &= ~MF_SPECIAL;
- if(deathmatch && (arti->type != MT_ARTIINVULNERABILITY)
- && (arti->type != MT_ARTIINVISIBILITY))
- {
- P_SetMobjState(arti, S_DORMANTARTI1);
- }
- else
- { // Don't respawn
- P_SetMobjState(arti, S_DEADARTI1);
- }
- S_StartSound(arti, sfx_artiup);
- }
- //---------------------------------------------------------------------------
- //
- // PROC A_RestoreArtifact
- //
- //---------------------------------------------------------------------------
- void A_RestoreArtifact(mobj_t *arti)
- {
- arti->flags |= MF_SPECIAL;
- P_SetMobjState(arti, arti->info->spawnstate);
- S_StartSound(arti, sfx_respawn);
- }
- //----------------------------------------------------------------------------
- //
- // PROC P_HideSpecialThing
- //
- //----------------------------------------------------------------------------
- void P_HideSpecialThing(mobj_t *thing)
- {
- thing->flags &= ~MF_SPECIAL;
- thing->flags2 |= MF2_DONTDRAW;
- P_SetMobjState(thing, S_HIDESPECIAL1);
- }
- //---------------------------------------------------------------------------
- //
- // PROC A_RestoreSpecialThing1
- //
- // Make a special thing visible again.
- //
- //---------------------------------------------------------------------------
- void A_RestoreSpecialThing1(mobj_t *thing)
- {
- if(thing->type == MT_WMACE)
- { // Do random mace placement
- P_RepositionMace(thing);
- }
- thing->flags2 &= ~MF2_DONTDRAW;
- S_StartSound(thing, sfx_respawn);
- }
- //---------------------------------------------------------------------------
- //
- // PROC A_RestoreSpecialThing2
- //
- //---------------------------------------------------------------------------
- void A_RestoreSpecialThing2(mobj_t *thing)
- {
- thing->flags |= MF_SPECIAL;
- P_SetMobjState(thing, thing->info->spawnstate);
- }
- //---------------------------------------------------------------------------
- //
- // PROC P_TouchSpecialThing
- //
- //---------------------------------------------------------------------------
- void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
- {
- int i;
- player_t *player;
- fixed_t delta;
- int sound;
- boolean respawn;
- delta = special->z-toucher->z;
- if(delta > toucher->height || delta < -32*FRACUNIT)
- { // Out of reach
- return;
- }
- if(toucher->health <= 0)
- { // Toucher is dead
- return;
- }
- sound = sfx_itemup;
- player = toucher->player;
- respawn = true;
- switch(special->sprite)
- {
- // Items
- case SPR_PTN1: // Item_HealingPotion
- if(!P_GiveBody(player, 10))
- {
- return;
- }
- P_SetMessage(player, TXT_ITEMHEALTH, false);
- break;
- case SPR_SHLD: // Item_Shield1
- if(!P_GiveArmor(player, 1))
- {
- return;
- }
- P_SetMessage(player, TXT_ITEMSHIELD1, false);
- break;
- case SPR_SHD2: // Item_Shield2
- if(!P_GiveArmor(player, 2))
- {
- return;
- }
- P_SetMessage(player, TXT_ITEMSHIELD2, false);
- break;
- case SPR_BAGH: // Item_BagOfHolding
- if(!player->backpack)
- {
- for(i = 0; i < NUMAMMO; i++)
- {
- player->maxammo[i] *= 2;
- }
- player->backpack = true;
- }
- P_GiveAmmo(player, am_goldwand, AMMO_GWND_WIMPY);
- P_GiveAmmo(player, am_blaster, AMMO_BLSR_WIMPY);
- P_GiveAmmo(player, am_crossbow, AMMO_CBOW_WIMPY);
- P_GiveAmmo(player, am_skullrod, AMMO_SKRD_WIMPY);
- P_GiveAmmo(player, am_phoenixrod, AMMO_PHRD_WIMPY);
- P_SetMessage(player, TXT_ITEMBAGOFHOLDING, false);
- break;
- case SPR_SPMP: // Item_SuperMap
- if(!P_GivePower(player, pw_allmap))
- {
- return;
- }
- P_SetMessage(player, TXT_ITEMSUPERMAP, false);
- break;
- // Keys
- case SPR_BKYY: // Key_Blue
- if(!player->keys[key_blue])
- {
- P_SetMessage(player, TXT_GOTBLUEKEY, false);
- }
- P_GiveKey(player, key_blue);
- sound = sfx_keyup;
- if(!netgame)
- {
- break;
- }
- return;
- case SPR_CKYY: // Key_Yellow
- if(!player->keys[key_yellow])
- {
- P_SetMessage(player, TXT_GOTYELLOWKEY, false);
- }
- sound = sfx_keyup;
- P_GiveKey(player, key_yellow);
- if(!netgame)
- {
- break;
- }
- return;
- case SPR_AKYY: // Key_Green
- if(!player->keys[key_green])
- {
- P_SetMessage(player, TXT_GOTGREENKEY, false);
- }
- sound = sfx_keyup;
- P_GiveKey(player, key_green);
- if(!netgame)
- {
- break;
- }
- return;
- // Artifacts
- case SPR_PTN2: // Arti_HealingPotion
- if(P_GiveArtifact(player, arti_health, special))
- {
- P_SetMessage(player, TXT_ARTIHEALTH, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_SOAR: // Arti_Fly
- if(P_GiveArtifact(player, arti_fly, special))
- {
- P_SetMessage(player, TXT_ARTIFLY, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_INVU: // Arti_Invulnerability
- if(P_GiveArtifact(player, arti_invulnerability, special))
- {
- P_SetMessage(player, TXT_ARTIINVULNERABILITY, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_PWBK: // Arti_TomeOfPower
- if(P_GiveArtifact(player, arti_tomeofpower, special))
- {
- P_SetMessage(player, TXT_ARTITOMEOFPOWER, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_INVS: // Arti_Invisibility
- if(P_GiveArtifact(player, arti_invisibility, special))
- {
- P_SetMessage(player, TXT_ARTIINVISIBILITY, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_EGGC: // Arti_Egg
- if(P_GiveArtifact(player, arti_egg, special))
- {
- P_SetMessage(player, TXT_ARTIEGG, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_SPHL: // Arti_SuperHealth
- if(P_GiveArtifact(player, arti_superhealth, special))
- {
- P_SetMessage(player, TXT_ARTISUPERHEALTH, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_TRCH: // Arti_Torch
- if(P_GiveArtifact(player, arti_torch, special))
- {
- P_SetMessage(player, TXT_ARTITORCH, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_FBMB: // Arti_FireBomb
- if(P_GiveArtifact(player, arti_firebomb, special))
- {
- P_SetMessage(player, TXT_ARTIFIREBOMB, false);
- P_SetDormantArtifact(special);
- }
- return;
- case SPR_ATLP: // Arti_Teleport
- if(P_GiveArtifact(player, arti_teleport, special))
- {
- P_SetMessage(player, TXT_ARTITELEPORT, false);
- P_SetDormantArtifact(special);
- }
- return;
- // Ammo
- case SPR_AMG1: // Ammo_GoldWandWimpy
- if(!P_GiveAmmo(player, am_goldwand, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOGOLDWAND1, false);
- break;
- case SPR_AMG2: // Ammo_GoldWandHefty
- if(!P_GiveAmmo(player, am_goldwand, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOGOLDWAND2, false);
- break;
- case SPR_AMM1: // Ammo_MaceWimpy
- if(!P_GiveAmmo(player, am_mace, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOMACE1, false);
- break;
- case SPR_AMM2: // Ammo_MaceHefty
- if(!P_GiveAmmo(player, am_mace, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOMACE2, false);
- break;
- case SPR_AMC1: // Ammo_CrossbowWimpy
- if(!P_GiveAmmo(player, am_crossbow, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOCROSSBOW1, false);
- break;
- case SPR_AMC2: // Ammo_CrossbowHefty
- if(!P_GiveAmmo(player, am_crossbow, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOCROSSBOW2, false);
- break;
- case SPR_AMB1: // Ammo_BlasterWimpy
- if(!P_GiveAmmo(player, am_blaster, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOBLASTER1, false);
- break;
- case SPR_AMB2: // Ammo_BlasterHefty
- if(!P_GiveAmmo(player, am_blaster, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOBLASTER2, false);
- break;
- case SPR_AMS1: // Ammo_SkullRodWimpy
- if(!P_GiveAmmo(player, am_skullrod, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOSKULLROD1, false);
- break;
- case SPR_AMS2: // Ammo_SkullRodHefty
- if(!P_GiveAmmo(player, am_skullrod, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOSKULLROD2, false);
- break;
- case SPR_AMP1: // Ammo_PhoenixRodWimpy
- if(!P_GiveAmmo(player, am_phoenixrod, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOPHOENIXROD1, false);
- break;
- case SPR_AMP2: // Ammo_PhoenixRodHefty
- if(!P_GiveAmmo(player, am_phoenixrod, special->health))
- {
- return;
- }
- P_SetMessage(player, TXT_AMMOPHOENIXROD2, false);
- break;
- // Weapons
- case SPR_WMCE: // Weapon_Mace
- if(!P_GiveWeapon(player, wp_mace))
- {
- return;
- }
- P_SetMessage(player, TXT_WPNMACE, false);
- sound = sfx_wpnup;
- break;
- case SPR_WBOW: // Weapon_Crossbow
- if(!P_GiveWeapon(player, wp_crossbow))
- {
- return;
- }
- P_SetMessage(player, TXT_WPNCROSSBOW, false);
- sound = sfx_wpnup;
- break;
- case SPR_WBLS: // Weapon_Blaster
- if(!P_GiveWeapon(player, wp_blaster))
- {
- return;
- }
- P_SetMessage(player, TXT_WPNBLASTER, false);
- sound = sfx_wpnup;
- break;
- case SPR_WSKL: // Weapon_SkullRod
- if(!P_GiveWeapon(player, wp_skullrod))
- {
- return;
- }
- P_SetMessage(player, TXT_WPNSKULLROD, false);
- sound = sfx_wpnup;
- break;
- case SPR_WPHX: // Weapon_PhoenixRod
- if(!P_GiveWeapon(player, wp_phoenixrod))
- {
- return;
- }
- P_SetMessage(player, TXT_WPNPHOENIXROD, false);
- sound = sfx_wpnup;
- break;
- case SPR_WGNT: // Weapon_Gauntlets
- if(!P_GiveWeapon(player, wp_gauntlets))
- {
- return;
- }
- P_SetMessage(player, TXT_WPNGAUNTLETS, false);
- sound = sfx_wpnup;
- break;
- default:
- I_Error("P_SpecialThing: Unknown gettable thing");
- }
- if(special->flags&MF_COUNTITEM)
- {
- player->itemcount++;
- }
- if(deathmatch && respawn && !(special->flags&MF_DROPPED))
- {
- P_HideSpecialThing(special);
- }
- else
- {
- P_RemoveMobj(special);
- }
- player->bonuscount += BONUSADD;
- if(player == &players[consoleplayer])
- {
- S_StartSound(NULL, sound);
- SB_PaletteFlash();
- }
- }
- //---------------------------------------------------------------------------
- //
- // PROC P_KillMobj
- //
- //---------------------------------------------------------------------------
- void P_KillMobj(mobj_t *source, mobj_t *target)
- {
- target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY|MF_NOGRAVITY);
- target->flags |= MF_CORPSE|MF_DROPOFF;
- target->flags2 &= ~MF2_PASSMOBJ;
- target->height >>= 2;
- if(source && source->player)
- {
- if(target->flags&MF_COUNTKILL)
- { // Count for intermission
- source->player->killcount++;
- }
- if(target->player)
- { // Frag stuff
- if(target == source)
- { // Self-frag
- target->player->frags[target->player-players]--;
- }
- else
- {
- source->player->frags[target->player-players]++;
- if(source->player == &players[consoleplayer])
- {
- S_StartSound(NULL, sfx_gfrag);
- }
- if(source->player->chickenTics)
- { // Make a super chicken
- P_GivePower(source->player, pw_weaponlevel2);
- }
- }
- }
- }
- else if(!netgame && (target->flags&MF_COUNTKILL))
- { // Count all monster deaths
- players[0].killcount++;
- }
- if(target->player)
- {
- if(!source)
- { // Self-frag
- target->player->frags[target->player-players]--;
- }
- target->flags &= ~MF_SOLID;
- target->flags2 &= ~MF2_FLY;
- target->player->powers[pw_flight] = 0;
- target->player->powers[pw_weaponlevel2] = 0;
- target->player->playerstate = PST_DEAD;
- P_DropWeapon(target->player);
- if(target->flags2&MF2_FIREDAMAGE)
- { // Player flame death
- P_SetMobjState(target, S_PLAY_FDTH1);
- //S_StartSound(target, sfx_hedat1); // Burn sound
- return;
- }
- }
- if(target->health < -(target->info->spawnhealth>>1)
- && target->info->xdeathstate)
- { // Extreme death
- P_SetMobjState(target, target->info->xdeathstate);
- }
- else
- { // Normal death
- P_SetMobjState(target, target->info->deathstate);
- }
- target->tics -= P_Random()&3;
- // I_StartSound(&actor->r, actor->info->deathsound);
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_MinotaurSlam
- //
- //---------------------------------------------------------------------------
- void P_MinotaurSlam(mobj_t *source, mobj_t *target)
- {
- angle_t angle;
- fixed_t thrust;
- angle = R_PointToAngle2(source->x, source->y, target->x, target->y);
- angle >>= ANGLETOFINESHIFT;
- thrust = 16*FRACUNIT+(P_Random()<<10);
- target->momx += FixedMul(thrust, finecosine[angle]);
- target->momy += FixedMul(thrust, finesine[angle]);
- P_DamageMobj(target, NULL, NULL, HITDICE(6));
- if(target->player)
- {
- target->reactiontime = 14+(P_Random()&7);
- }
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_TouchWhirlwind
- //
- //---------------------------------------------------------------------------
- void P_TouchWhirlwind(mobj_t *target)
- {
- int randVal;
- target->angle += (P_Random()-P_Random())<<20;
- target->momx += (P_Random()-P_Random())<<10;
- target->momy += (P_Random()-P_Random())<<10;
- if(leveltime&16 && !(target->flags2&MF2_BOSS))
- {
- randVal = P_Random();
- if(randVal > 160)
- {
- randVal = 160;
- }
- target->momz += randVal<<10;
- if(target->momz > 12*FRACUNIT)
- {
- target->momz = 12*FRACUNIT;
- }
- }
- if(!(leveltime&7))
- {
- P_DamageMobj(target, NULL, NULL, 3);
- }
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_ChickenMorphPlayer
- //
- // Returns true if the player gets turned into a chicken.
- //
- //---------------------------------------------------------------------------
- boolean P_ChickenMorphPlayer(player_t *player)
- {
- mobj_t *pmo;
- mobj_t *fog;
- mobj_t *chicken;
- fixed_t x;
- fixed_t y;
- fixed_t z;
- angle_t angle;
- int oldFlags2;
- if(player->chickenTics)
- {
- if((player->chickenTics < CHICKENTICS-TICSPERSEC)
- && !player->powers[pw_weaponlevel2])
- { // Make a super chicken
- P_GivePower(player, pw_weaponlevel2);
- }
- return(false);
- }
- if(player->powers[pw_invulnerability])
- { // Immune when invulnerable
- return(false);
- }
- pmo = player->mo;
- x = pmo->x;
- y = pmo->y;
- z = pmo->z;
- angle = pmo->angle;
- oldFlags2 = pmo->flags2;
- P_SetMobjState(pmo, S_FREETARGMOBJ);
- fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
- S_StartSound(fog, sfx_telept);
- chicken = P_SpawnMobj(x, y, z, MT_CHICPLAYER);
- chicken->special1 = player->readyweapon;
- chicken->angle = angle;
- chicken->player = player;
- player->health = chicken->health = MAXCHICKENHEALTH;
- player->mo = chicken;
- player->armorpoints = player->armortype = 0;
- player->powers[pw_invisibility] = 0;
- player->powers[pw_weaponlevel2] = 0;
- if(oldFlags2&MF2_FLY)
- {
- chicken->flags2 |= MF2_FLY;
- }
- player->chickenTics = CHICKENTICS;
- P_ActivateBeak(player);
- return(true);
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_ChickenMorph
- //
- //---------------------------------------------------------------------------
- boolean P_ChickenMorph(mobj_t *actor)
- {
- mobj_t *fog;
- mobj_t *chicken;
- mobj_t *target;
- mobjtype_t moType;
- fixed_t x;
- fixed_t y;
- fixed_t z;
- angle_t angle;
- int ghost;
- if(actor->player)
- {
- return(false);
- }
- moType = actor->type;
- switch(moType)
- {
- case MT_POD:
- case MT_CHICKEN:
- case MT_HEAD:
- case MT_MINOTAUR:
- case MT_SORCERER1:
- case MT_SORCERER2:
- return(false);
- default:
- break;
- }
- x = actor->x;
- y = actor->y;
- z = actor->z;
- angle = actor->angle;
- ghost = actor->flags&MF_SHADOW;
- target = actor->target;
- P_SetMobjState(actor, S_FREETARGMOBJ);
- fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
- S_StartSound(fog, sfx_telept);
- chicken = P_SpawnMobj(x, y, z, MT_CHICKEN);
- chicken->special2 = moType;
- chicken->special1 = CHICKENTICS+P_Random();
- chicken->flags |= ghost;
- chicken->target = target;
- chicken->angle = angle;
- return(true);
- }
- //---------------------------------------------------------------------------
- //
- // FUNC P_AutoUseChaosDevice
- //
- //---------------------------------------------------------------------------
- boolean P_AutoUseChaosDevice(player_t *player)
- {
- int i;
- for(i = 0; i < player->inventorySlotNum; i++)
- {
- if(player->inventory[i].type == arti_teleport)
- {
- P_PlayerUseArtifact(player, arti_teleport);
- player->health = player->mo->health = (player->health+1)/2;
- return(true);
- }
- }
- return(false);
- }
- //---------------------------------------------------------------------------
- //
- // PROC P_AutoUseHealth
- //
- //---------------------------------------------------------------------------
- void P_AutoUseHealth(player_t *player, int saveHealth)
- {
- int i;
- int count;
- int normalCount;
- int normalSlot;
- int superCount;
- int superSlot;
- normalCount = superCount = 0;
- for(i = 0; i < player->inventorySlotNum; i++)
- {
- if(player->inventory[i].type == arti_health)
- {
- normalSlot = i;
- normalCount = player->inventory[i].count;
- }
- else if(player->inventory[i].type == arti_superhealth)
- {
- superSlot = i;
- superCount = player->inventory[i].count;
- }
- }
- if((gameskill == sk_baby) && (normalCount*25 >= saveHealth))
- { // Use quartz flasks
- count = (saveHealth+24)/25;
- for(i = 0; i < count; i++)
- {
- player->health += 25;
- P_PlayerRemoveArtifact(player, normalSlot);
- }
- }
- else if(superCount*100 >= saveHealth)
- { // Use mystic urns
- count = (saveHealth+99)/100;
- for(i = 0; i < count; i++)
- {
- player->health += 100;
- P_PlayerRemoveArtifact(player, superSlot);
- }
- }
- else if((gameskill == sk_baby)
- && (superCount*100+normalCount*25 >= saveHealth))
- { // Use mystic urns and quartz flasks
- count = (saveHealth+24)/25;
- saveHealth -= count*25;
- for(i = 0; i < count; i++)
- {
- player->health += 25;
- P_PlayerRemoveArtifact(player, normalSlot);
- }
- count = (saveHealth+99)/100;
- for(i = 0; i < count; i++)
- {
- player->health += 100;
- P_PlayerRemoveArtifact(player, normalSlot);
- }
- }
- player->mo->health = player->health;
- }
- /*
- =================
- =
- = P_DamageMobj
- =
- = Damages both enemies and players
- = inflictor is the thing that caused the damage
- = creature or missile, can be NULL (slime, etc)
- = source is the thing to target after taking damage
- = creature or NULL
- = Source and inflictor are the same for melee attacks
- = source can be null for barrel explosions and other environmental stuff
- ==================
- */
- void P_DamageMobj
- (
- mobj_t *target,
- mobj_t *inflictor,
- mobj_t *source,
- int damage
- )
- {
- unsigned ang;
- int saved;
- player_t *player;
- fixed_t thrust;
- int temp;
- if(!(target->flags&MF_SHOOTABLE))
- {
- // Shouldn't happen
- return;
- }
- if(target->health <= 0)
- {
- return;
- }
- if(target->flags&MF_SKULLFLY)
- {
- if(target->type == MT_MINOTAUR)
- { // Minotaur is invulnerable during charge attack
- return;
- }
- target->momx = target->momy = target->momz = 0;
- }
- player = target->player;
- if(player && gameskill == sk_baby)
- {
- // Take half damage in trainer mode
- damage >>= 1;
- }
- // Special damage types
- if(inflictor)
- {
- switch(inflictor->type)
- {
- case MT_EGGFX:
- if(player)
- {
- P_ChickenMorphPlayer(player);
- }
- else
- {
- P_ChickenMorph(target);
- }
- return; // Always return
- case MT_WHIRLWIND:
- P_TouchWhirlwind(target);
- return;
- case MT_MINOTAUR:
- if(inflictor->flags&MF_SKULLFLY)
- { // Slam only when in charge mode
- P_MinotaurSlam(inflictor, target);
- return;
- }
- break;
- case MT_MACEFX4: // Death ball
- if((target->flags2&MF2_BOSS) || target->type == MT_HEAD)
- { // Don't allow cheap boss kills
- break;
- }
- else if(target->player)
- { // Player specific checks
- if(target->player->powers[pw_invulnerability])
- { // Can't hurt invulnerable players
- break;
- }
- if(P_AutoUseChaosDevice(target->player))
- { // Player was saved using chaos device
- return;
- }
- }
- damage = 10000; // Something's gonna die
- break;
- case MT_PHOENIXFX2: // Flame thrower
- if(target->player && P_Random() < 128)
- { // Freeze player for a bit
- target->reactiontime += 4;
- }
- break;
- case MT_RAINPLR1: // Rain missiles
- case MT_RAINPLR2:
- case MT_RAINPLR3:
- case MT_RAINPLR4:
- if(target->flags2&MF2_BOSS)
- { // Decrease damage for bosses
- damage = (P_Random()&7)+1;
- }
- break;
- case MT_HORNRODFX2:
- case MT_PHOENIXFX1:
- if(target->type == MT_SORCERER2 && P_Random() < 96)
- { // D'Sparil teleports away
- P_DSparilTeleport(target);
- return;
- }
- break;
- case MT_BLASTERFX1:
- case MT_RIPPER:
- if(target->type == MT_HEAD)
- { // Less damage to Ironlich bosses
- damage = P_Random()&1;
- if(!damage)
- {
- return;
- }
- }
- break;
- default:
- break;
- }
- }
- // Push the target unless source is using the gauntlets
- if(inflictor && (!source || !source->player
- || source->player->readyweapon != wp_gauntlets)
- && !(inflictor->flags2&MF2_NODMGTHRUST))
- {
- ang = R_PointToAngle2(inflictor->x, inflictor->y,
- target->x, target->y);
- //thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
- thrust = damage*(FRACUNIT>>3)*150/target->info->mass;
- // make fall forwards sometimes
- if((damage < 40) && (damage > target->health)
- && (target->z-inflictor->z > 64*FRACUNIT) && (P_Random()&1))
- {
- ang += ANG180;
- thrust *= 4;
- }
- ang >>= ANGLETOFINESHIFT;
- if(source && source->player && (source == inflictor)
- && source->player->powers[pw_weaponlevel2]
- && source->player->readyweapon == wp_staff)
- {
- // Staff power level 2
- target->momx += FixedMul(10*FRACUNIT, finecosine[ang]);
- target->momy += FixedMul(10*FRACUNIT, finesine[ang]);
- if(!(target->flags&MF_NOGRAVITY))
- {
- target->momz += 5*FRACUNIT;
- }
- }
- else
- {
- target->momx += FixedMul(thrust, finecosine[ang]);
- target->momy += FixedMul(thrust, finesine[ang]);
- }
- }
- //
- // player specific
- //
- if(player)
- {
- // end of game hell hack
- //if(target->subsector->sector->special == 11
- // && damage >= target->health)
- //{
- // damage = target->health - 1;
- //}
- if(damage < 1000 && ((player->cheats&CF_GODMODE)
- || player->powers[pw_invulnerability]))
- {
- return;
- }
- if(player->armortype)
- {
- if(player->armortype == 1)
- {
- saved = damage>>1;
- }
- else
- {
- saved = (damage>>1)+(damage>>2);
- }
- if(player->armorpoints <= saved)
- {
- // armor is used up
- saved = player->armorpoints;
- player->armortype = 0;
- }
- player->armorpoints -= saved;
- damage -= saved;
- }
- if(damage >= player->health
- && ((gameskill == sk_baby) || deathmatch)
- && !player->chickenTics)
- { // Try to use some inventory health
- P_AutoUseHealth(player, damage-player->health+1);
- }
- player->health -= damage; // mirror mobj health here for Dave
- if(player->health < 0)
- {
- player->health = 0;
- }
- player->attacker = source;
- player->damagecount += damage; // add damage after armor / invuln
- if(player->damagecount > 100)
- {
- player->damagecount = 100; // teleport stomp does 10k points...
- }
- temp = damage < 100 ? damage : 100;
- if(player == &players[consoleplayer])
- {
- I_Tactile(40, 10, 40+temp*2);
- SB_PaletteFlash();
- }
- }
- //
- // do the damage
- //
- target->health -= damage;
- if(target->health <= 0)
- { // Death
- target->special1 = damage;
- if(target->type == MT_POD && source && source->type != MT_POD)
- { // Make sure players get frags for chain-reaction kills
- target->target = source;
- }
- if(player && inflictor && !player->chickenTics)
- { // Check for flame death
- if((inflictor->flags2&MF2_FIREDAMAGE)
- || ((inflictor->type == MT_PHOENIXFX1)
- && (target->health > -50) && (damage > 25)))
- {
- target->flags2 |= MF2_FIREDAMAGE;
- }
- }
- P_KillMobj(source, target);
- return;
- }
- if((P_Random() < target->info->painchance)
- && !(target->flags&MF_SKULLFLY))
- {
- target->flags |= MF_JUSTHIT; // fight back!
- P_SetMobjState(target, target->info->painstate);
- }
- target->reactiontime = 0; // we're awake now...
- if(!target->threshold && source && !(source->flags2&MF2_BOSS)
- && !(target->type == MT_SORCERER2 && source->type == MT_WIZARD))
- {
- // Target actor is not intent on another actor,
- // so make him chase after source
- target->target = source;
- target->threshold = BASETHRESHOLD;
- if(target->state == &states[target->info->spawnstate]
- && target->info->seestate != S_NULL)
- {
- P_SetMobjState(target, target->info->seestate);
- }
- }
- }
|