From f5e4677344ccc60774e975ba978b79fc373eecce Mon Sep 17 00:00:00 2001 From: danij Date: Thu, 25 Jul 2013 02:56:23 +0100 Subject: [PATCH] Fixed|libheretic: Cheats not working in multiplayer See: b9fdf4fcc9086627c0b9c30d3a3d52ebc471c3ba Todo: The cheats 'gimme', 'iddqd' and 'idkfa' require various new features and/or functionality. I'll return to these once libhexen has been updated... --- doomsday/plugins/common/src/d_netsv.c | 13 +- doomsday/plugins/heretic/include/doomdef.h | 18 +- doomsday/plugins/heretic/include/p_inter.h | 146 ++++- doomsday/plugins/heretic/include/p_local.h | 12 - doomsday/plugins/heretic/src/h_console.c | 4 +- doomsday/plugins/heretic/src/m_cheat.c | 692 ++++++++------------- doomsday/plugins/heretic/src/p_enemy.c | 25 + doomsday/plugins/heretic/src/p_inter.c | 683 +++++++++++--------- doomsday/plugins/heretic/src/p_pspr.c | 6 +- 9 files changed, 801 insertions(+), 798 deletions(-) diff --git a/doomsday/plugins/common/src/d_netsv.c b/doomsday/plugins/common/src/d_netsv.c index 5cf1d2ffc5..4bee3a0f3d 100644 --- a/doomsday/plugins/common/src/d_netsv.c +++ b/doomsday/plugins/common/src/d_netsv.c @@ -1305,7 +1305,7 @@ void NetSv_SendJumpPower(int target, float power) Net_SendPacket(target, GPT_JUMP_POWER, Writer_Data(writer), Writer_Size(writer)); } -void NetSv_ExecuteCheat(int player, const char* command) +void NetSv_ExecuteCheat(int player, char const *command) { // Killing self is always allowed. /// @todo fixme: really? Even in deathmatch?? @@ -1322,9 +1322,14 @@ void NetSv_ExecuteCheat(int player, const char* command) } /// @todo Can't we use the multipurpose cheat command here? - if(!strnicmp(command, "god", 3) || - !strnicmp(command, "noclip", 6) || - !strnicmp(command, "give", 4)) + if(!strnicmp(command, "god", 3) + || !strnicmp(command, "noclip", 6) + || !strnicmp(command, "give", 4) +#ifdef __JHERETIC__ + || !strnicmp(command, "kill", 4) + || !strnicmp(command, "chicken", 7) +#endif + ) { DD_Executef(false, "%s %i", command, player); } diff --git a/doomsday/plugins/heretic/include/doomdef.h b/doomsday/plugins/heretic/include/doomdef.h index 50355e0886..351fb459b8 100644 --- a/doomsday/plugins/heretic/include/doomdef.h +++ b/doomsday/plugins/heretic/include/doomdef.h @@ -207,25 +207,13 @@ typedef enum { AT_NOAMMO // Takes no ammo, used for staff, gauntlets. } ammotype_t; -#define AMMO_GWND_WIMPY 10 -#define AMMO_GWND_HEFTY 50 -#define AMMO_CBOW_WIMPY 5 -#define AMMO_CBOW_HEFTY 20 -#define AMMO_BLSR_WIMPY 10 -#define AMMO_BLSR_HEFTY 25 -#define AMMO_SKRD_WIMPY 20 -#define AMMO_SKRD_HEFTY 100 -#define AMMO_PHRD_WIMPY 1 -#define AMMO_PHRD_HEFTY 10 -#define AMMO_MACE_WIMPY 20 -#define AMMO_MACE_HEFTY 100 - /** * Powers, bestowable upon players only. */ typedef enum { - PT_NONE, - PT_INVULNERABILITY, + PT_NONE, /// @todo Remove me (index from zero). + PT_FIRST, + PT_INVULNERABILITY = PT_FIRST, PT_INVISIBILITY, PT_ALLMAP, PT_INFRARED, diff --git a/doomsday/plugins/heretic/include/p_inter.h b/doomsday/plugins/heretic/include/p_inter.h index c974beaf40..4ea1f2d8af 100644 --- a/doomsday/plugins/heretic/include/p_inter.h +++ b/doomsday/plugins/heretic/include/p_inter.h @@ -1,37 +1,133 @@ -/**\file - *\section License - * License: GPL - * Online License Link: http://www.gnu.org/licenses/gpl.html +/** @file p_inter.h * - *\author Copyright © 2009-2013 Daniel Swanson + * @authors Copyright © 2009-2013 Daniel Swanson * - * 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. + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html * - * 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. + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef LIBHERETIC_P_INTER_H +#define LIBHERETIC_P_INTER_H + +#ifndef __JHERETIC__ +# error "Using jHeretic headers without __JHERETIC__" +#endif + +#include "doomdef.h" +#include "p_player.h" + +DENG_EXTERN_C int maxAmmo[NUM_AMMO_TYPES]; +DENG_EXTERN_C int clipAmmo[NUM_AMMO_TYPES]; + +/** + * @return @c true if power accepted. + */ +boolean P_GivePower(player_t *player, powertype_t powerType); + +/** + * @param player Player to relieve of the power. + * @param powerType Power type to take. * - * 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., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA + * @return @c true iff the power was taken. */ +boolean P_TakePower(player_t *player, powertype_t powerType); /** - * p_inter.h: Handling interactions (i.e., collisions). + * @param player Player to toggle a power for. + * @param powerType Power type to toggle. + * + * @return @c true iff the power was toggled. */ +boolean P_TogglePower(player_t *player, powertype_t powerType); -#ifndef __P_INTER_H__ -#define __P_INTER_H__ +/** + * Give key(s) to the specified player. If a key is successfully given a short + * "bonus flash" screen tint animation is played and a HUE_ON_PICKUP_KEY event + * is generated (which optionally reveals the HUD if hidden). If the specified + * key(s) are already owned then nothing will happen (and false is returned). + * + * @param player Player to receive the key(s). + * @param keyType Key type to give. Use @c NUM_KEY_TYPES to give ALL keys. + * + * @return @c true iff at least one new key was given (not already owned). + */ +boolean P_GiveKey(player_t *player, keytype_t keyType); -#ifndef __JHERETIC__ -# error "Using jHeretic headers without __JHERETIC__" -#endif +/** + * Give ammo(s) to the specified player. If a ammo is successfully given the + * player 'brain' may decide to change weapon (depends on the user's config) + * and a HUE_ON_PICKUP_AMMO event is generated (which optionally reveals the + * HUD if hidden). If the specified ammo(s) are already owned then nothing will + * happen (and false is returned). + * + * @note The final number of rounds the player will receive depends on both the + * ammount given and how many the player can carry. Use @ref P_GiveBackpack() + * to equip the player with a backpack, thereby increasing this capacity. + * + * @param player Player to receive the ammo(s). + * @param ammoType Ammo type to give. Use @c NUM_AMMO_TYPES to give ALL ammos. + * Giving the special 'unlimited ammo' type @c AT_NOAMMO will + * always succeed, however no sideeffects will occur. + * @param numRounds Number of rounds to give. Use @c -1 to give as many rounds + * as necessary to fully replenish stock. + * + * @return @c true iff at least one new round was given (not already owned). + */ +boolean P_GiveAmmo(player_t *player, ammotype_t ammoType, int numRounds); -boolean P_GiveArmor(player_t* plr, int type, int points); +/** + * @param player Player to receive the health. + * @param amount Amount of health to give. Use @c -1 to fully replenish. + * + * @return @c true iff at least some of the health was given. + */ +boolean P_GiveHealth(player_t *player, int amount); -#endif +/** + * @param player Player to receive the backpack. + */ +void P_GiveBackpack(player_t *player); + +/** + * @return @c true if the weapon or its ammo was accepted. + */ +boolean P_GiveWeapon(player_t *player, weapontype_t weaponType); + +/** + * @return @c true iff the armor was given. + */ +boolean P_GiveArmor(player_t *player, int armorType, int armorPoints); + +void P_TouchSpecialMobj(mobj_t *special, mobj_t *toucher); + +/** + * @return @c true, if the player is morphed. + */ +boolean P_MorphPlayer(player_t *player); + +/** + * Damages both enemies and players. + * + * @param inflictor Mobj that caused the damage creature or missile, + * can be NULL (slime, etc) + * @param source Mobj to target after taking damage. Can be @c NULL + * for barrel explosions and other environmental stuff. + * Source and inflictor are the same for melee attacks. + * + * @return Actual amount of damage done. + */ +int P_DamageMobj2(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damageP, boolean stomping, boolean skipNetworkCheck); +int P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damageP, boolean stomping/*, boolean skipNetworkCheck = false*/); + +#endif // LIBHERETIC_P_INTER_H diff --git a/doomsday/plugins/heretic/include/p_local.h b/doomsday/plugins/heretic/include/p_local.h index 7b2cd0e882..fddfa77b50 100644 --- a/doomsday/plugins/heretic/include/p_local.h +++ b/doomsday/plugins/heretic/include/p_local.h @@ -99,9 +99,6 @@ DENG_EXTERN_C mobjtype_t puffType; DENG_EXTERN_C mobj_t* missileMobj; DENG_EXTERN_C float turboMul; -DENG_EXTERN_C int maxAmmo[NUM_AMMO_TYPES]; -DENG_EXTERN_C int clipAmmo[NUM_AMMO_TYPES]; -DENG_EXTERN_C int maxAmmo[NUM_AMMO_TYPES]; #ifdef __cplusplus extern "C" { @@ -142,15 +139,6 @@ void P_ExplodeMissile(mobj_t* mo); const char* P_GetMapName(uint episode, uint map); const char* P_GetShortMapName(uint episode, uint map); -void P_GiveKey(player_t* player, keytype_t key); -void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher); -int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage, boolean stomping); -int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage, boolean stomping, boolean skipNetworkCheck); -boolean P_GiveAmmo(player_t* player, ammotype_t ammo, int count); -boolean P_GiveBody(player_t* player, int num); -boolean P_GivePower(player_t* player, powertype_t power); -boolean P_MorphPlayer(player_t* player); - void Draw_BeginZoom(float s, float originX, float originY); void Draw_EndZoom(void); diff --git a/doomsday/plugins/heretic/src/h_console.c b/doomsday/plugins/heretic/src/h_console.c index 73ec5bfd5f..f0f3f099a1 100644 --- a/doomsday/plugins/heretic/src/h_console.c +++ b/doomsday/plugins/heretic/src/h_console.c @@ -34,7 +34,7 @@ D_CMD(CheatReveal); D_CMD(CheatGive); D_CMD(CheatMassacre); D_CMD(CheatWhere); -D_CMD(CheatPig); +D_CMD(CheatMorph); D_CMD(CheatLeaveMap); D_CMD(CheatSuicide); @@ -186,7 +186,7 @@ ccmdtemplate_t gameCCmds[] = { {"viewmode", NULL, CCmdSetViewMode}, // Heretic specific - {"chicken", "", CCmdCheatPig}, + {"chicken", "", CCmdCheatMorph}, {NULL} }; diff --git a/doomsday/plugins/heretic/src/m_cheat.c b/doomsday/plugins/heretic/src/m_cheat.c index 6de021fb88..410496d707 100644 --- a/doomsday/plugins/heretic/src/m_cheat.c +++ b/doomsday/plugins/heretic/src/m_cheat.c @@ -1,10 +1,8 @@ -/** - * @file m_cheat.c - * Cheats. @ingroup libheretic +/** @file m_cheat.c Cheat code sequences * - * @author Copyright © 2003-2013 Jaakko Keränen - * @author Copyright © 2005-2013 Daniel Swanson - * @author Copyright © 1999 Activision + * @authors Copyright © 2003-2013 Jaakko Keränen + * @authors Copyright © 2005-2013 Daniel Swanson + * @authors Copyright © 1999 Activision * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -22,25 +20,16 @@ */ #include -#include -#include -#include -#ifdef UNIX -# include -#endif +#include #include "jheretic.h" #include "d_net.h" -#include "g_common.h" #include "p_player.h" #include "am_map.h" -#include "hu_inventory.h" -#include "hu_menu.h" #include "hu_msg.h" #include "dmu_lib.h" #include "p_user.h" -#include "p_start.h" #include "p_inventory.h" #include "g_eventsequence.h" @@ -58,305 +47,65 @@ typedef eventsequencehandler_t cheatfunc_t; /// Helper macro for registering new cheat event sequence command handlers. #define ADDCHEATCMD(name, cmdTemplate) G_AddEventSequenceCommand((name), cmdTemplate) -CHEAT_FUNC(God); -CHEAT_FUNC(NoClip); -CHEAT_FUNC(Weapons); -CHEAT_FUNC(Powerup); -CHEAT_FUNC(Health); -CHEAT_FUNC(GiveKeys); CHEAT_FUNC(InvItem); CHEAT_FUNC(InvItem2); CHEAT_FUNC(InvItem3); -CHEAT_FUNC(Chicken); -CHEAT_FUNC(Massacre); CHEAT_FUNC(IDKFA); CHEAT_FUNC(IDDQD); -CHEAT_FUNC(Sound); -CHEAT_FUNC(Ticker); +CHEAT_FUNC(NoOp); // Play a sound but otherwise ignore. CHEAT_FUNC(Reveal); -static boolean cheatsEnabled(void) -{ - return !IS_NETGAME; -} - void G_RegisterCheats(void) { - ADDCHEAT("cockadoodledoo", Chicken); - ADDCHEATCMD("engage%1%2", "warp %1%2"); - ADDCHEAT("gimme%1%2", InvItem3); // Final stage. - ADDCHEAT("gimme%1", InvItem2); // 2nd stage (ask for count). - ADDCHEAT("gimme", InvItem); // 1st stage (ask for type). - ADDCHEAT("iddqd", IDDQD); - ADDCHEAT("idkfa", IDKFA); - ADDCHEAT("kitty", NoClip); - ADDCHEAT("massacre", Massacre); - ADDCHEAT("noise", Sound); - ADDCHEAT("ponce", Health); - ADDCHEAT("quicken", God); - ADDCHEAT("rambo", Weapons); - ADDCHEAT("ravmap", Reveal); - ADDCHEAT("shazam", Powerup); - ADDCHEAT("skel", GiveKeys); - ADDCHEAT("ticker", Ticker); -} - -CHEAT_FUNC(God) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - plr->cheats ^= CF_GODMODE; - plr->update |= PSF_STATE; - - P_SetMessage(plr, LMF_NO_HIDE, ((P_GetPlayerCheats(plr) & CF_GODMODE) ? TXT_CHEATGODON : TXT_CHEATGODOFF)); - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -static void giveArmor(player_t* plr) -{ - plr->update |= PSF_ARMOR_POINTS | PSF_STATE; - plr->armorPoints = 200; - plr->armorType = 2; -} - -static void giveWeapons(player_t* plr) -{ - int i; - - plr->update |= PSF_OWNED_WEAPONS; - for(i = 0; i < NUM_WEAPON_TYPES; ++i) - { - if(weaponInfo[i][0].mode[0].gameModeBits & gameModeBits) - plr->weapons[i].owned = true; - } -} - -static void giveAmmo(player_t* plr) -{ - int i; - - plr->update |= PSF_MAX_AMMO | PSF_AMMO; - if(!plr->backpack) - { - for(i = 0; i < NUM_AMMO_TYPES; ++i) - { - plr->ammo[i].max *= 2; - } - plr->backpack = true; - } - - for(i = 0; i < NUM_AMMO_TYPES; ++i) - { - plr->ammo[i].owned = plr->ammo[i].max; - } -} - -CHEAT_FUNC(Weapons) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - giveWeapons(plr); - giveAmmo(plr); - giveArmor(plr); - - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATWEAPONS); - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -CHEAT_FUNC(GiveKeys) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - plr->update |= PSF_KEYS; - plr->keys[KT_YELLOW] = true; - plr->keys[KT_GREEN] = true; - plr->keys[KT_BLUE] = true; - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATKEYS); - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -CHEAT_FUNC(NoClip) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - plr->cheats ^= CF_NOCLIP; - plr->update |= PSF_STATE; - P_SetMessage(plr, LMF_NO_HIDE, ((P_GetPlayerCheats(plr) & CF_NOCLIP) ? TXT_CHEATNOCLIPON : TXT_CHEATNOCLIPOFF)); - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -CHEAT_FUNC(Powerup) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - plr->update |= PSF_POWERS; - if(plr->powers[PT_WEAPONLEVEL2]) - { - plr->powers[PT_WEAPONLEVEL2] = 0; - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATPOWEROFF); - } - else - { - int plrnum = plr - players; - - P_InventoryGive(plrnum, IIT_TOMBOFPOWER, true); - P_InventoryUse(plrnum, IIT_TOMBOFPOWER, true); - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATPOWERON); - } - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -static void printDebugInfo(int player) -{ - player_t* plr = &players[player]; - char textBuffer[256]; - BspLeaf* sub; - AutoStr* path, *mapPath; - Uri* uri, *mapUri; - - if(!plr->plr->mo || !userGame) return; - - mapUri = G_ComposeMapUri(gameEpisode, gameMap); - mapPath = Uri_ToString(mapUri); - sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", - Str_Text(mapPath), plr->plr->mo->origin[VX], plr->plr->mo->origin[VY], - plr->plr->mo->origin[VZ]); - P_SetMessage(plr, LMF_NO_HIDE, textBuffer); - Uri_Delete(mapUri); - - // Also print some information to the console. - Con_Message("%s", textBuffer); - sub = plr->plr->mo->bspLeaf; - Con_Message("BspLeaf %i:", P_ToIndex(sub)); - - uri = Materials_ComposeUri(P_GetIntp(sub, DMU_FLOOR_MATERIAL)); - path = Uri_ToString(uri); - Con_Message(" FloorZ:%g Material:%s", P_GetDoublep(sub, DMU_FLOOR_HEIGHT), Str_Text(path)); - Uri_Delete(uri); - - uri = Materials_ComposeUri(P_GetIntp(sub, DMU_CEILING_MATERIAL)); - path = Uri_ToString(uri); - Con_Message(" CeilingZ:%g Material:%s", P_GetDoublep(sub, DMU_CEILING_HEIGHT), Str_Text(path)); - Uri_Delete(uri); - - Con_Message("Player height:%g Player radius:%g", - plr->plr->mo->height, plr->plr->mo->radius); -} - -CHEAT_FUNC(Health) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - plr->update |= PSF_HEALTH; - if(plr->morphTics) - { - plr->health = plr->plr->mo->health = MAXCHICKENHEALTH; - } - else - { - plr->health = plr->plr->mo->health = maxHealth; - } - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATHEALTH); - S_LocalSound(SFX_DORCLS, NULL); - return true; + ADDCHEATCMD("cockadoodledoo", "chicken %p"); + ADDCHEATCMD("engage%1%2", "warp %1%2"); + ADDCHEAT("gimme%1%2", InvItem3); // Final stage. + ADDCHEAT("gimme%1", InvItem2); // 2nd stage (ask for count). + ADDCHEAT("gimme", InvItem); // 1st stage (ask for type). + ADDCHEAT("iddqd", IDDQD); + ADDCHEAT("idkfa", IDKFA); + ADDCHEATCMD("kitty", "noclip %p"); + ADDCHEATCMD("massacre", "kill"); + ADDCHEAT("noise", NoOp); + ADDCHEATCMD("ponce", "give h %p"); + ADDCHEATCMD("quicken", "god %p"); + ADDCHEATCMD("rambo", "give wpar2 %p"); + ADDCHEAT("ravmap", Reveal); + ADDCHEATCMD("shazam", "give t %p"); + ADDCHEATCMD("skel", "give k %p"); + ADDCHEAT("ticker", NoOp); } CHEAT_FUNC(InvItem) { - player_t* plr = &players[player]; - DENG_UNUSED(args); DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATINVITEMS1); + P_SetMessage(&players[player], LMF_NO_HIDE, TXT_CHEATINVITEMS1); S_LocalSound(SFX_DORCLS, NULL); + return true; } CHEAT_FUNC(InvItem2) { - player_t* plr = &players[player]; - DENG_UNUSED(args); DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATINVITEMS2); + P_SetMessage(&players[player], LMF_NO_HIDE, TXT_CHEATINVITEMS2); S_LocalSound(SFX_DORCLS, NULL); + return true; } CHEAT_FUNC(InvItem3) { - player_t* plr = &players[player]; + player_t *plr = &players[player]; inventoryitemtype_t type; int count; DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; @@ -379,140 +128,65 @@ CHEAT_FUNC(InvItem3) P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATINVITEMS3); } else - { // Bad input - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATITEMSFAIL); - } - - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -CHEAT_FUNC(Chicken) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - if(plr->morphTics) - { - if(P_UndoPlayerMorph(plr)) - { - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATCHICKENOFF); - } - } - else if(P_MorphPlayer(plr)) { - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATCHICKENON); + // Bad input + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATITEMSFAIL); } S_LocalSound(SFX_DORCLS, NULL); return true; } -CHEAT_FUNC(Massacre) -{ - player_t* plr = &players[player]; - - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - P_Massacre(); - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATMASSACRE); - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - CHEAT_FUNC(IDKFA) { - player_t* plr = &players[player]; + player_t *plr = &players[player]; int i; DENG_UNUSED(args); DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; if(plr->morphTics) return false; + plr->update |= PSF_OWNED_WEAPONS; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { plr->weapons[i].owned = false; } - plr->pendingWeapon = WT_FIRST; + //plr->pendingWeapon = WT_FIRST; + P_MaybeChangeWeapon(plr, WT_FIRST, NOAMMO, true /*force*/); + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATIDKFA); S_LocalSound(SFX_DORCLS, NULL); + return true; } CHEAT_FUNC(IDDQD) { - player_t* plr = &players[player]; + player_t *plr = &players[player]; DENG_UNUSED(args); DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; P_DamageMobj(plr->plr->mo, NULL, plr->plr->mo, 10000, false); - P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATIDDQD); - S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -CHEAT_FUNC(Sound) -{ - player_t* plr = &players[player]; - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - // Otherwise ignored. + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATIDDQD); S_LocalSound(SFX_DORCLS, NULL); - return true; -} - -CHEAT_FUNC(Ticker) -{ - player_t* plr = &players[player]; - DENG_UNUSED(args); - DENG_ASSERT(player >= 0 && player < MAXPLAYERS); - - if(IS_NETGAME) return false; - if(gameSkill == SM_NIGHTMARE) return false; - // Dead players can't cheat. - if(plr->health <= 0) return false; - - // Otherwise ignored. - S_LocalSound(SFX_DORCLS, NULL); return true; } CHEAT_FUNC(Reveal) { - player_t* plr = &players[player]; + player_t *plr = &players[player]; DENG_UNUSED(args); DENG_ASSERT(player >= 0 && player < MAXPLAYERS); @@ -528,6 +202,15 @@ CHEAT_FUNC(Reveal) return true; } +CHEAT_FUNC(NoOp) +{ + DENG_UNUSED(args); + DENG_UNUSED(player); + + S_LocalSound(SFX_DORCLS, NULL); + return true; +} + /** * The multipurpose cheat ccmd. */ @@ -555,11 +238,14 @@ D_CMD(CheatGod) { NetCl_CheatRequest("god"); } + else if((IS_NETGAME && !netSvAllowCheats) || gameSkill == SM_NIGHTMARE) + { + return false; + } else { int player = CONSOLEPLAYER; - - if(IS_NETGAME && !netSvAllowCheats) return false; + player_t *plr; if(argc == 2) { @@ -567,9 +253,17 @@ D_CMD(CheatGod) if(player < 0 || player >= MAXPLAYERS) return false; } - if(!players[player].plr->inGame) return false; + plr = &players[player]; + if(!plr->plr->inGame) return false; + + // Dead players can't cheat. + if(plr->health <= 0) return false; - CHEAT(God)(player, 0/*no args*/, 0/*no args*/); + plr->cheats ^= CF_GODMODE; + plr->update |= PSF_STATE; + + P_SetMessage(plr, LMF_NO_HIDE, ((P_GetPlayerCheats(plr) & CF_GODMODE) ? TXT_CHEATGODON : TXT_CHEATGODOFF)); + S_LocalSound(SFX_DORCLS, NULL); } } return true; @@ -583,11 +277,14 @@ D_CMD(CheatNoClip) { NetCl_CheatRequest("noclip"); } + else if((IS_NETGAME && !netSvAllowCheats) || gameSkill == SM_NIGHTMARE) + { + return false; + } else { int player = CONSOLEPLAYER; - - if(IS_NETGAME && !netSvAllowCheats) return false; + player_t *plr; if(argc == 2) { @@ -595,15 +292,23 @@ D_CMD(CheatNoClip) if(player < 0 || player >= MAXPLAYERS) return false; } - if(!players[player].plr->inGame) return false; + plr = &players[player]; + if(!plr->plr->inGame) return false; + + // Dead players can't cheat. + if(plr->health <= 0) return false; - CHEAT(NoClip)(player, 0/*no args*/, 0/*no args*/); + plr->cheats ^= CF_NOCLIP; + plr->update |= PSF_STATE; + + P_SetMessage(plr, LMF_NO_HIDE, ((P_GetPlayerCheats(plr) & CF_NOCLIP) ? TXT_CHEATNOCLIPON : TXT_CHEATNOCLIPOFF)); + S_LocalSound(SFX_DORCLS, NULL); } } return true; } -static int suicideResponse(msgresponse_t response, int userValue, void* userPointer) +static int suicideResponse(msgresponse_t response, int userValue, void *userPointer) { if(response == MSG_YES) { @@ -613,7 +318,7 @@ static int suicideResponse(msgresponse_t response, int userValue, void* userPoin } else { - player_t* plr = &players[CONSOLEPLAYER]; + player_t *plr = &players[CONSOLEPLAYER]; P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); } } @@ -624,7 +329,7 @@ D_CMD(CheatSuicide) { if(G_GameState() == GS_MAP) { - player_t* plr; + player_t *plr; if(IS_NETGAME && !netSvAllowCheats) return false; @@ -663,7 +368,9 @@ D_CMD(CheatReveal) { int option, i; - if(!cheatsEnabled()) return false; + // Server operator can always reveal. + if(IS_NETGAME && !IS_NETWORK_SERVER) + return false; option = atoi(argv[1]); if(option < 0 || option > 3) return false; @@ -687,22 +394,17 @@ D_CMD(CheatReveal) D_CMD(CheatGive) { + char buf[100]; int player = CONSOLEPLAYER; + player_t *plr; size_t i, stuffLen; - player_t* plr; - char buf[100]; - if(IS_CLIENT) + if(G_GameState() != GS_MAP) { - if(argc != 2) return false; - - sprintf(buf, "give %s", argv[1]); - NetCl_CheatRequest(buf); + Con_Printf("Can only \"give\" when in a game!\n"); return true; } - if(IS_NETGAME && !netSvAllowCheats) return false; - if(argc != 2 && argc != 3) { Con_Printf("Usage:\n give (stuff)\n"); @@ -725,20 +427,29 @@ D_CMD(CheatGive) if(argc == 3) { player = atoi(argv[2]); - if(player < 0 || player >= MAXPLAYERS) - return false; + if(player < 0 || player >= MAXPLAYERS) return false; } - if(G_GameState() != GS_MAP) + if(IS_CLIENT) { - Con_Printf("Can only \"give\" when in a game!\n"); + if(argc != 2) return false; + + sprintf(buf, "give %s", argv[1]); + NetCl_CheatRequest(buf); return true; } - if(!players[player].plr->inGame) - return true; // Can't give to a plr who's not playing. + if((IS_NETGAME && !netSvAllowCheats) || gameSkill == SM_NIGHTMARE) + return false; + plr = &players[player]; + // Can't give to a player who's not in the game. + if(!plr->plr->inGame) return false; + + // Can't give to a dead player. + if(plr->health <= 0) return false; + strcpy(buf, argv[1]); // Stuff is the 2nd arg. strlwr(buf); stuffLen = strlen(buf); @@ -749,7 +460,7 @@ D_CMD(CheatGive) case 'a': if(i < stuffLen) { - char* end; + char *end; long idx; errno = 0; idx = strtol(&buf[i+1], &end, 0); @@ -764,18 +475,13 @@ D_CMD(CheatGive) } // Give one specific ammo type. - plr->update |= PSF_AMMO; - plr->ammo[idx].owned = plr->ammo[idx].max; + P_GiveAmmo(plr, (ammotype_t) idx, -1 /*fully replenish*/); break; } } // Give all ammo. - plr->update |= PSF_AMMO; - { int j; - for(j = 0; j < NUM_AMMO_TYPES; ++j) - plr->ammo[j].owned = plr->ammo[j].max; - } + P_GiveAmmo(plr, NUM_AMMO_TYPES, -1 /*fully replenish*/); break; case 'i': // Inventory items. @@ -823,7 +529,9 @@ D_CMD(CheatGive) break; case 'h': - CHEAT(Health)(player, 0/*no args*/, 0/*no args*/); + P_GiveHealth(plr, -1 /*maximum amount*/); + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATHEALTH); + S_LocalSound(SFX_DORCLS, NULL); break; case 'k': @@ -844,42 +552,60 @@ D_CMD(CheatGive) } // Give one specific key. - plr->update |= PSF_KEYS; - plr->keys[idx] = true; + P_GiveKey(plr, (keytype_t)idx); break; } } // Give all keys. - CHEAT(GiveKeys)(player, 0/*no args*/, 0/*no args*/); + P_GiveKey(plr, NUM_KEY_TYPES /*all types*/); + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATKEYS); + S_LocalSound(SFX_DORCLS, NULL); break; case 'p': - if(!plr->backpack) + P_GiveBackpack(plr); + break; + + case 'r': { + int armorType = 2; + + if(i < stuffLen) { - int j; - for(j = AT_FIRST; j < NUM_AMMO_TYPES; ++j) - plr->ammo[j].max *= 2; - plr->backpack = true; - plr->update |= PSF_MAX_AMMO; - } + char *end; + long idx; + errno = 0; + idx = strtol(&buf[i+1], &end, 0); + if(end != &buf[i+1] && errno != ERANGE) + { + i += end - &buf[i+1]; + if(idx < 0 || idx >= 3) + { + Con_Printf("Unknown armor type #%d (valid range %d-%d).\n", + (int)idx, 0, 3-1); + break; + } - // Set all ammo to max. - plr->update |= PSF_AMMO; - { int j; - for(j = 0; j < NUM_AMMO_TYPES; ++j) - plr->ammo[j].owned = plr->ammo[j].max; + armorType = idx; + } } - break; - case 'r': - plr->update |= PSF_ARMOR_POINTS; - plr->armorPoints = 200; - plr->armorType = 2; - break; + P_GiveArmor(plr, armorType, armorType * 100); + break; } case 't': - CHEAT(Powerup)(player, 0/*no args*/, 0/*no args*/); + if(plr->powers[PT_WEAPONLEVEL2]) + { + P_TakePower(plr, PT_WEAPONLEVEL2); + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATPOWEROFF); + } + else + { + P_InventoryGive(player, IIT_TOMBOFPOWER, true /*silent*/); + P_InventoryUse(player, IIT_TOMBOFPOWER, true /*silent*/); + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATPOWERON); + } + S_LocalSound(SFX_DORCLS, NULL); break; case 'w': @@ -900,17 +626,13 @@ D_CMD(CheatGive) } // Give one specific weapon. - if(weaponInfo[idx][0].mode[0].gameModeBits & gameModeBits) - { - plr->update |= PSF_OWNED_WEAPONS; - plr->weapons[idx].owned = true; - } + P_GiveWeapon(plr, (weapontype_t) idx); break; } } // Give all weapons. - giveWeapons(plr); + P_GiveWeapon(plr, NUM_WEAPON_TYPES /*all types*/); break; default: // Unrecognized. @@ -919,18 +641,76 @@ D_CMD(CheatGive) } } + // If the give expression matches that of a vanilla cheat code print the + // associated confirmation message to the player's log. + /// @todo fixme: Somewhat of kludge... + if(!strcmp(buf, "wpar2")) + { + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATWEAPONS); + S_LocalSound(SFX_DORCLS, NULL); + } + return true; } D_CMD(CheatMassacre) { - CHEAT(Massacre)(CONSOLEPLAYER, 0/*no args*/, 0/*no args*/); + if(G_GameState() == GS_MAP) + { + if(IS_CLIENT) + { + NetCl_CheatRequest("kill"); + } + else if((IS_NETGAME && !netSvAllowCheats) || gameSkill == SM_NIGHTMARE) + { + return false; + } + else + { + P_Massacre(); + P_SetMessage(&players[CONSOLEPLAYER], LMF_NO_HIDE, TXT_CHEATMASSACRE); + S_LocalSound(SFX_DORCLS, NULL); + } + } return true; } D_CMD(CheatWhere) { - printDebugInfo(CONSOLEPLAYER); + player_t *plr = &players[CONSOLEPLAYER]; + char textBuffer[256]; + BspLeaf *sub; + AutoStr *path, *mapPath; + Uri *uri, *mapUri; + + if(!plr->plr->mo || !userGame) return true; + + mapUri = G_ComposeMapUri(gameEpisode, gameMap); + mapPath = Uri_ToString(mapUri); + sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", + Str_Text(mapPath), plr->plr->mo->origin[VX], plr->plr->mo->origin[VY], + plr->plr->mo->origin[VZ]); + P_SetMessage(plr, LMF_NO_HIDE, textBuffer); + Uri_Delete(mapUri); + + // Also print some information to the console. + Con_Message("%s", textBuffer); + sub = plr->plr->mo->bspLeaf; + Con_Message("BspLeaf %i:", P_ToIndex(sub)); + + uri = Materials_ComposeUri(P_GetIntp(sub, DMU_FLOOR_MATERIAL)); + path = Uri_ToString(uri); + Con_Message(" FloorZ:%g Material:%s", P_GetDoublep(sub, DMU_FLOOR_HEIGHT), Str_Text(path)); + Uri_Delete(uri); + + uri = Materials_ComposeUri(P_GetIntp(sub, DMU_CEILING_MATERIAL)); + path = Uri_ToString(uri); + Con_Message(" CeilingZ:%g Material:%s", P_GetDoublep(sub, DMU_CEILING_HEIGHT), Str_Text(path)); + Uri_Delete(uri); + + Con_Message("Player height:%g Player radius:%g", + plr->plr->mo->height, plr->plr->mo->radius); + return true; } @@ -939,7 +719,9 @@ D_CMD(CheatWhere) */ D_CMD(CheatLeaveMap) { - if(!cheatsEnabled()) return false; + // Only the server operator can end the map this way. + if(IS_NETGAME && !IS_NETWORK_SERVER) + return false; if(G_GameState() != GS_MAP) { @@ -952,12 +734,48 @@ D_CMD(CheatLeaveMap) return true; } -D_CMD(CheatPig) +D_CMD(CheatMorph) { - if(IS_NETGAME || !userGame) return false; - if(gameSkill == SM_NIGHTMARE) return false; - if(players[CONSOLEPLAYER].health <= 0) return false; + if(G_GameState() == GS_MAP) + { + if(IS_CLIENT) + { + NetCl_CheatRequest("chicken"); + } + else if((IS_NETGAME && !netSvAllowCheats) || gameSkill == SM_NIGHTMARE) + { + return false; + } + else + { + int player = CONSOLEPLAYER; + player_t *plr; + + if(argc == 2) + { + player = atoi(argv[1]); + if(player < 0 || player >= MAXPLAYERS) return false; + } + + plr = &players[player]; + if(!plr->plr->inGame) return false; + + // Dead players can't cheat. + if(plr->health <= 0) return false; - CHEAT(Chicken)(CONSOLEPLAYER, 0/*no args*/, 0/*no args*/); + if(plr->morphTics) + { + if(P_UndoPlayerMorph(plr)) + { + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATCHICKENOFF); + } + } + else if(P_MorphPlayer(plr)) + { + P_SetMessage(plr, LMF_NO_HIDE, TXT_CHEATCHICKENON); + } + S_LocalSound(SFX_DORCLS, NULL); + } + } return true; } diff --git a/doomsday/plugins/heretic/src/p_enemy.c b/doomsday/plugins/heretic/src/p_enemy.c index d9980ab2b6..4fe3f86850 100644 --- a/doomsday/plugins/heretic/src/p_enemy.c +++ b/doomsday/plugins/heretic/src/p_enemy.c @@ -2016,6 +2016,31 @@ void C_DECL A_MakePod(mobj_t* actor) return; } +void C_DECL A_RestoreArtifact(mobj_t* mo) +{ + mo->flags |= MF_SPECIAL; + P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN)); + S_StartSound(SFX_RESPAWN, mo); +} + +void C_DECL A_RestoreSpecialThing1(mobj_t *mo) +{ + if(mo->type == MT_WMACE) + { + // Do random mace placement. + P_RepositionMace(mo); + } + + mo->flags2 &= ~MF2_DONTDRAW; + S_StartSound(SFX_RESPAWN, mo); +} + +void C_DECL A_RestoreSpecialThing2(mobj_t* thing) +{ + thing->flags |= MF_SPECIAL; + P_MobjChangeState(thing, P_GetState(thing->type, SN_SPAWN)); +} + static int massacreMobj(thinker_t* th, void* context) { int* count = (int*) context; diff --git a/doomsday/plugins/heretic/src/p_inter.c b/doomsday/plugins/heretic/src/p_inter.c index ce9ef71c49..20a39090db 100644 --- a/doomsday/plugins/heretic/src/p_inter.c +++ b/doomsday/plugins/heretic/src/p_inter.c @@ -23,12 +23,6 @@ * Boston, MA 02110-1301 USA */ -/** - * p_inter.c: Handling interactions (i.e., collisions). - */ - -// HEADER FILES ------------------------------------------------------------ - #include #include "jheretic.h" @@ -43,194 +37,178 @@ #include "p_user.h" #include "p_mapsetup.h" -// MACROS ------------------------------------------------------------------ - #define BONUSADD (6) -// TYPES ------------------------------------------------------------------- - -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- - -// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- - -// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- +// Maximum number of rounds for each ammo type. +int maxAmmo[NUM_AMMO_TYPES] = { 100, 50, 200, 200, 20, 150 }; -// EXTERNAL DATA DECLARATIONS ---------------------------------------------- +// Numer of rounds to give with a backpack for each ammo type. +int backpackAmmo[NUM_AMMO_TYPES] = { 10, 5, 10, 20, 1, 0 }; -// PUBLIC DATA DEFINITIONS ------------------------------------------------- +// Number of rounds to give for each weapon type. +int getWeaponAmmo[NUM_WEAPON_TYPES] = { 0, 25, 10, 30, 50, 2, 50, 0 }; -int maxAmmo[NUM_AMMO_TYPES] = { - 100, // gold wand - 50, // crossbow - 200, // blaster - 200, // skull rod - 20, // phoenix rod - 150 // mace -}; - -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - -static int getWeaponAmmo[NUM_WEAPON_TYPES] = { - 0, // staff - 25, // gold wand - 10, // crossbow - 30, // blaster - 50, // skull rod - 2, // phoenix rod - 50, // mace - 0 // gauntlets -}; +static boolean giveOneAmmo(player_t *plr, ammotype_t ammoType, int numRounds) +{ + DENG_ASSERT(plr != 0); + DENG_ASSERT((ammoType >= 0 && ammoType < NUM_AMMO_TYPES) || ammoType == AT_NOAMMO); -// CODE -------------------------------------------------------------------- + // Giving the special 'unlimited ammo' type always succeeds. + if(ammoType == AT_NOAMMO) + return true; -/** - * 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 num) -{ - if(ammo == AT_NOAMMO) + // Already fully stocked? + if(plr->ammo[ammoType].owned >= plr->ammo[ammoType].max) return false; - if(ammo < 0 || ammo > NUM_AMMO_TYPES) - Con_Error("P_GiveAmmo: bad type %i", ammo); - - if(!(player->ammo[ammo].owned < player->ammo[ammo].max)) + if(numRounds == 0) + { return false; + } + else if(numRounds < 0) + { + // Fully replenish. + numRounds = plr->ammo[ammoType].max; + } + // Give extra rounds at easy/nightmare skill levels. if(gameSkill == SM_BABY || gameSkill == SM_NIGHTMARE) - { // Extra ammo in baby mode and nightmare mode. - num += num / 1; + { + numRounds += numRounds / 1; } - // We are about to receive some more ammo. Does the player want to - // change weapon automatically? - P_MaybeChangeWeapon(player, WT_NOCHANGE, ammo, false); + // Given the new ammo the player may want to change weapon automatically. + P_MaybeChangeWeapon(plr, WT_NOCHANGE, ammoType, false /*don't force*/); - if(player->ammo[ammo].owned + num > player->ammo[ammo].max) - player->ammo[ammo].owned = player->ammo[ammo].max; - else - player->ammo[ammo].owned += num; - player->update |= PSF_AMMO; + // Restock the player. + plr->ammo[ammoType].owned = MIN_OF(plr->ammo[ammoType].max, + plr->ammo[ammoType].owned + numRounds); + plr->update |= PSF_AMMO; // Maybe unhide the HUD? - ST_HUDUnHide(player - players, HUE_ON_PICKUP_AMMO); + ST_HUDUnHide(plr - players, HUE_ON_PICKUP_AMMO); return true; } -/** - * @return @c true, if the weapon or its ammo was accepted. - */ -boolean P_GiveWeapon(player_t *player, weapontype_t weapon, const char* pickupMessage, int pickupSound) +boolean P_GiveAmmo(player_t *plr, ammotype_t ammoType, int numRounds) { - int i; - int lvl = (player->powers[PT_WEAPONLEVEL2]? 1 : 0); - boolean gaveAmmo = false; - boolean gaveWeapon = false; + int gaveAmmos = 0; - if(IS_NETGAME && !deathmatch) + if(ammoType == NUM_AMMO_TYPES) { - // Leave placed weapons forever on net games. - if(player->weapons[weapon].owned) - return false; - - player->bonusCount += BONUSADD; - player->weapons[weapon].owned = true; - player->update |= PSF_OWNED_WEAPONS; - - // Give some of each of the ammo types used by this weapon. + // Give all ammos. + int i = 0; for(i = 0; i < NUM_AMMO_TYPES; ++i) { - if(!weaponInfo[weapon][player->class_].mode[lvl].ammoType[i]) - continue; // Weapon does not take this type of ammo. - - if(P_GiveAmmo(player, i, getWeaponAmmo[weapon])) - gaveAmmo = true; // At least ONE type of ammo was given. + gaveAmmos |= (int)giveOneAmmo(plr, (ammotype_t) i, numRounds) << i; } + } + else + { + // Give a single ammo. + gaveAmmos |= (int)giveOneAmmo(plr, ammoType, numRounds) << (int)ammoType; + } - // Should we change weapon automatically? - P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false); + return gaveAmmos != 0; +} - // Maybe unhide the HUD? - ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); +static boolean giveOneWeapon(player_t *plr, weapontype_t weaponType) +{ + int lvl = (plr->powers[PT_WEAPONLEVEL2]? 1 : 0); + boolean gaveAmmo = false, gaveWeapon = false; + weaponinfo_t const *wpnInfo; + ammotype_t i; + + DENG_ASSERT(plr != 0); + DENG_ASSERT(weaponType >= WT_FIRST && weaponType < NUM_WEAPON_TYPES); - // Notify the player. - S_ConsoleSound(pickupSound, NULL, player - players); - if(pickupMessage) + wpnInfo = &weaponInfo[weaponType][plr->class_]; + + // Do not give weapons unavailable for the current mode. + if(!(wpnInfo->mode[lvl].gameModeBits & gameModeBits)) + return false; + + // Give some of each of the ammo types used by this weapon. + for(i = 0; i < NUM_AMMO_TYPES; ++i) + { + // Is this ammo type usable?. + if(!wpnInfo->mode[lvl].ammoType[i]) + continue; + + if(P_GiveAmmo(plr, i, getWeaponAmmo[weaponType])) { - P_SetMessage(player, 0, pickupMessage); + gaveAmmo = true; } - return false; } - else + + if(!plr->weapons[weaponType].owned) { - // Give some of each of the ammo types used by this weapon. - for(i = 0; i < NUM_AMMO_TYPES; ++i) - { - if(!weaponInfo[weapon][player->class_].mode[lvl].ammoType[i]) - continue; // Weapon does not take this type of ammo. + gaveWeapon = true; - if(P_GiveAmmo(player, i, getWeaponAmmo[weapon])) - gaveAmmo = true; // At least ONE type of ammo was given. - } + plr->weapons[weaponType].owned = true; + plr->update |= PSF_OWNED_WEAPONS; - if(player->weapons[weapon].owned) - gaveWeapon = false; - else + // Animated a pickup bonus flash? + if(IS_NETGAME && !deathmatch) { - gaveWeapon = true; - player->weapons[weapon].owned = true; - player->update |= PSF_OWNED_WEAPONS; - - // Should we change weapon automatically? - P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false); + plr->bonusCount += BONUSADD; } + // Given the new weapon the player may want to change automatically. + P_MaybeChangeWeapon(plr, weaponType, AT_NOAMMO, false); + // Maybe unhide the HUD? - if(gaveWeapon) - { - ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); - } + ST_HUDUnHide(plr - players, HUE_ON_PICKUP_WEAPON); + } + + return (gaveWeapon || gaveAmmo); +} + +boolean P_GiveWeapon(player_t *plr, weapontype_t weaponType) +{ + int gaveWeapons = 0; - if(gaveWeapon || gaveAmmo) + if(weaponType == NUM_WEAPON_TYPES) + { + // Give all weapons. + int i = 0; + for(i = 0; i < NUM_WEAPON_TYPES; ++i) { - // Notify the player. - S_ConsoleSound(pickupSound, NULL, player - players); - if(pickupMessage) - { - P_SetMessage(player, 0, pickupMessage); - } + gaveWeapons |= (int)giveOneWeapon(plr, (weapontype_t) i) << i; } - return (gaveWeapon || gaveAmmo); } + else + { + // Give a single weapon. + gaveWeapons |= (int)giveOneWeapon(plr, weaponType) << (int)weaponType; + } + + return gaveWeapons != 0; } -/** - * @return @c false, if the body isn't needed at all. - */ -boolean P_GiveBody(player_t *player, int num) +static int maxPlayerHealth(boolean morphed) { - int max; + return morphed? MAXCHICKENHEALTH : maxHealth; +} - if(player->morphTics) - max = MAXCHICKENHEALTH; - else - max = maxHealth; +boolean P_GiveHealth(player_t *player, int amount) +{ + int healthLimit = maxPlayerHealth(player->morphTics != 0); - if(player->health >= max) - { + // Already at capacity? + if(player->health >= healthLimit) return false; - } - player->health += num; - if(player->health > max) + if(amount < 0) { - player->health = max; + // Fully replenish. + amount = healthLimit; } + player->health = + player->plr->mo->health = MIN_OF(player->health + amount, healthLimit); player->update |= PSF_HEALTH; - player->plr->mo->health = player->health; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_HEALTH); @@ -238,76 +216,128 @@ boolean P_GiveBody(player_t *player, int num) return true; } -/** - * @return @c true, iff the armor was given. - */ -boolean P_GiveArmor(player_t* plr, int type, int points) +boolean P_GiveArmor(player_t *player, int armorType, int armorPoints) { - if(plr->armorPoints >= points) + DENG_ASSERT(player != 0); + + if(player->armorPoints >= armorPoints) return false; - P_PlayerSetArmorType(plr, type); - P_PlayerGiveArmorBonus(plr, points - plr->armorPoints); + P_PlayerSetArmorType(player, armorType); + P_PlayerGiveArmorBonus(player, armorPoints - player->armorPoints); // Maybe unhide the HUD? - ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); + ST_HUDUnHide(player - players, HUE_ON_PICKUP_ARMOR); return true; } -void P_GiveKey(player_t* player, keytype_t key) +static boolean giveOneKey(player_t *plr, keytype_t keyType) { - if(player->keys[key]) - return; + DENG_ASSERT(plr != 0); + DENG_ASSERT(keyType >= KT_FIRST && keyType < NUM_KEY_TYPES); + + // Already owned? + if(plr->keys[keyType]) return false; - player->bonusCount = BONUSADD; - player->keys[key] = true; - player->update |= PSF_KEYS; + plr->keys[keyType] = true; + plr->bonusCount = BONUSADD; + plr->update |= PSF_KEYS; // Maybe unhide the HUD? - ST_HUDUnHide(player - players, HUE_ON_PICKUP_KEY); + ST_HUDUnHide(plr - players, HUE_ON_PICKUP_KEY); + + return true; } -/** - * @return @c true, if power accepted. - */ -boolean P_GivePower(player_t* player, powertype_t power) +boolean P_GiveKey(player_t *plr, keytype_t keyType) { - mobj_t* plrmo = player->plr->mo; - boolean retval = false; + int gaveKeys = 0; + + if(keyType == NUM_KEY_TYPES) + { + // Give all keys. + int i = 0; + for(i = 0; i < NUM_KEY_TYPES; ++i) + { + gaveKeys |= (int)giveOneKey(plr, (keytype_t) i) << i; + } + } + else + { + // Give a single key. + gaveKeys |= (int)giveOneKey(plr, keyType) << (int)keyType; + } + + return gaveKeys != 0; +} + +void P_GiveBackpack(player_t *plr) +{ + int i; + + if(!plr->backpack) + { + plr->update |= PSF_MAX_AMMO; + for(i = 0; i < NUM_AMMO_TYPES; ++i) + { + plr->ammo[i].max *= 2; + } + + plr->backpack = true; + } + + for(i = 0; i < NUM_AMMO_TYPES; ++i) + { + P_GiveAmmo(plr, i, backpackAmmo[i]); + } + + P_SetMessage(plr, 0, TXT_ITEMBAGOFHOLDING); +} + +boolean P_GivePower(player_t *player, powertype_t powerType) +{ + boolean retval = false; + + DENG_ASSERT(player != 0); + DENG_ASSERT(powerType >= PT_FIRST && powerType < NUM_POWER_TYPES); player->update |= PSF_POWERS; - switch(power) + switch(powerType) { case PT_INVULNERABILITY: - if(!(player->powers[power] > BLINKTHRESHOLD)) + if(!(player->powers[powerType] > BLINKTHRESHOLD)) { - player->powers[power] = INVULNTICS; + player->powers[powerType] = INVULNTICS; retval = true; } break; case PT_WEAPONLEVEL2: - if(!(player->powers[power] > BLINKTHRESHOLD)) + if(!(player->powers[powerType] > BLINKTHRESHOLD)) { - player->powers[power] = WPNLEV2TICS; + player->powers[powerType] = WPNLEV2TICS; retval = true; } break; case PT_INVISIBILITY: - if(!(player->powers[power] > BLINKTHRESHOLD)) + if(!(player->powers[powerType] > BLINKTHRESHOLD)) { - player->powers[power] = INVISTICS; + mobj_t *plrmo = player->plr->mo; + + player->powers[powerType] = INVISTICS; plrmo->flags |= MF_SHADOW; retval = true; } break; case PT_FLIGHT: - if(!(player->powers[power] > BLINKTHRESHOLD)) + if(!(player->powers[powerType] > BLINKTHRESHOLD)) { - player->powers[power] = FLIGHTTICS; + mobj_t *plrmo = player->plr->mo; + + player->powers[powerType] = FLIGHTTICS; plrmo->flags2 |= MF2_FLY; plrmo->flags |= MF_NOGRAVITY; if(plrmo->origin[VZ] <= plrmo->floorZ) @@ -320,17 +350,17 @@ boolean P_GivePower(player_t* player, powertype_t power) break; case PT_INFRARED: - if(!(player->powers[power] > BLINKTHRESHOLD)) + if(!(player->powers[powerType] > BLINKTHRESHOLD)) { - player->powers[power] = INFRATICS; + player->powers[powerType] = INFRATICS; retval = true; } break; default: - if(!player->powers[power]) + if(!player->powers[powerType]) { - player->powers[power] = 1; + player->powers[powerType] = 1; retval = true; } break; @@ -338,13 +368,63 @@ boolean P_GivePower(player_t* player, powertype_t power) if(retval) { - if(power == PT_ALLMAP) + if(powerType == PT_ALLMAP) ST_RevealAutomap(player - players, true); } return retval; } +boolean P_TakePower(player_t *player, powertype_t powerType) +{ + DENG_ASSERT(player != 0); + DENG_ASSERT(powerType >= PT_FIRST && powerType < NUM_POWER_TYPES); + + if(!player->powers[powerType]) + return false; // Dont got it. + + switch(powerType) + { + case PT_ALLMAP: + ST_RevealAutomap(player - players, false); + break; + + case PT_FLIGHT: { + mobj_t *plrmo = player->plr->mo; + + if(plrmo->origin[VZ] != plrmo->floorZ && cfg.lookSpring) + { + player->centering = true; + } + + plrmo->flags2 &= ~MF2_FLY; + plrmo->flags &= ~MF_NOGRAVITY; + break; } + + default: break; + } + + player->powers[powerType] = 0; + player->update |= PSF_POWERS; + + return true; +} + +boolean P_TogglePower(player_t *player, powertype_t powerType) +{ + DENG_ASSERT(player != 0); + DENG_ASSERT(powerType >= PT_FIRST && powerType < NUM_POWER_TYPES); + + if(!player->powers[powerType]) + { + return P_GivePower(player, powerType); + } + else + { + return P_TakePower(player, powerType); + } +} + /** * Removes the MF_SPECIAL flag, and initiates the item pickup animation. */ @@ -363,38 +443,6 @@ static void setDormantItem(mobj_t* mo) } } -void C_DECL A_RestoreArtifact(mobj_t* mo) -{ - mo->flags |= MF_SPECIAL; - P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN)); - S_StartSound(SFX_RESPAWN, mo); -} - -void P_HideSpecialThing(mobj_t* thing) -{ - thing->flags &= ~MF_SPECIAL; - thing->flags2 |= MF2_DONTDRAW; - P_MobjChangeState(thing, S_HIDESPECIAL1); -} - -void C_DECL A_RestoreSpecialThing1(mobj_t *mo) -{ - if(mo->type == MT_WMACE) - { - // Do random mace placement. - P_RepositionMace(mo); - } - - mo->flags2 &= ~MF2_DONTDRAW; - S_StartSound(SFX_RESPAWN, mo); -} - -void C_DECL A_RestoreSpecialThing2(mobj_t* thing) -{ - thing->flags |= MF_SPECIAL; - P_MobjChangeState(thing, P_GetState(thing->type, SN_SPAWN)); -} - typedef enum { IT_NONE = 0, IT_HEALTH_POTION, @@ -438,9 +486,10 @@ typedef enum { static itemtype_t getItemTypeBySprite(spritetype_e sprite) { static const struct item_s { - itemtype_t type; - spritetype_e sprite; - } items[] = { + itemtype_t type; + spritetype_e sprite; + } items[] = + { { IT_HEALTH_POTION, SPR_PTN1 }, { IT_SHIELD1, SPR_SHLD }, { IT_SHIELD2, SPR_SHD2 }, @@ -479,16 +528,64 @@ static itemtype_t getItemTypeBySprite(spritetype_e sprite) { IT_WEAPON_GAUNTLETS, SPR_WGNT }, { IT_NONE, 0 }, }; - uint i; - + int i; for(i = 0; items[i].type != IT_NONE; ++i) + { if(items[i].sprite == sprite) return items[i].type; - + } return IT_NONE; } -static boolean giveItem(player_t* plr, itemtype_t item, int quantity) +/** + * Attempt to pickup the found weapon type. + * + * @param plr Player to attempt the pickup. + * @param weaponType Weapon type to pickup. + * @param pickupMessage Message to display if picked up. + * + * @return @c true if the player picked up the weapon. + */ +static boolean pickupWeapon(player_t *plr, weapontype_t weaponType, + char const *pickupMessage) +{ + boolean pickedWeapon; + + DENG_ASSERT(plr != 0); + DENG_ASSERT(weaponType >= WT_FIRST && weaponType < NUM_WEAPON_TYPES); + + // Depending on the game rules the player should ignore the weapon. + if(plr->weapons[weaponType].owned) + { + // Leave placed weapons forever on net games. + if(IS_NETGAME && !deathmatch) + return false; + } + + // Attempt the pickup. + pickedWeapon = P_GiveWeapon(plr, weaponType); + if(pickedWeapon) + { + // Notify the user. + P_SetMessage(plr, 0, pickupMessage); + + if(!mapSetup) // Pickup sounds are not played during map setup. + { + S_ConsoleSound(SFX_WPNUP, NULL, plr - players); + } + } + + return pickedWeapon; +} + +/** + * @param plr Player being given item. + * @param item Type of item being given. + * @param quantity ? + * + * @return @c true iff the item should be destroyed. + */ +static boolean pickupItem(player_t *plr, itemtype_t item, int quantity) { if(!plr) return false; @@ -496,7 +593,7 @@ static boolean giveItem(player_t* plr, itemtype_t item, int quantity) switch(item) { case IT_HEALTH_POTION: - if(!P_GiveBody(plr, 10)) + if(!P_GiveHealth(plr, 10)) return false; P_SetMessage(plr, 0, TXT_ITEMHEALTH); @@ -523,22 +620,7 @@ static boolean giveItem(player_t* plr, itemtype_t item, int quantity) break; case IT_BAGOFHOLDING: - if(!plr->backpack) - { - int i; - for(i = 0; i < NUM_AMMO_TYPES; ++i) - { - plr->ammo[i].max *= 2; - } - plr->backpack = true; - } - - P_GiveAmmo(plr, AT_CRYSTAL, AMMO_GWND_WIMPY); - P_GiveAmmo(plr, AT_ORB, AMMO_BLSR_WIMPY); - P_GiveAmmo(plr, AT_ARROW, AMMO_CBOW_WIMPY); - P_GiveAmmo(plr, AT_RUNE, AMMO_SKRD_WIMPY); - P_GiveAmmo(plr, AT_FIREORB, AMMO_PHRD_WIMPY); - P_SetMessage(plr, 0, TXT_ITEMBAGOFHOLDING); + P_GiveBackpack(plr); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; @@ -790,34 +872,22 @@ static boolean giveItem(player_t* plr, itemtype_t item, int quantity) break; case IT_WEAPON_MACE: - if(!P_GiveWeapon(plr, WT_SEVENTH, TXT_WPNMACE, !mapSetup? SFX_WPNUP : 0)) - return false; - break; + return pickupWeapon(plr, WT_SEVENTH, TXT_WPNMACE); case IT_WEAPON_CROSSBOW: - if(!P_GiveWeapon(plr, WT_THIRD, TXT_WPNCROSSBOW, !mapSetup? SFX_WPNUP : 0)) - return false; - break; + return pickupWeapon(plr, WT_THIRD, TXT_WPNCROSSBOW); case IT_WEAPON_BLASTER: - if(!P_GiveWeapon(plr, WT_FOURTH, TXT_WPNBLASTER, !mapSetup? SFX_WPNUP : 0)) - return false; - break; + return pickupWeapon(plr, WT_FOURTH, TXT_WPNBLASTER); case IT_WEAPON_SKULLROD: - if(!P_GiveWeapon(plr, WT_FIFTH, TXT_WPNSKULLROD, !mapSetup? SFX_WPNUP : 0)) - return false; - break; + return pickupWeapon(plr, WT_FIFTH, TXT_WPNSKULLROD); case IT_WEAPON_PHOENIXROD: - if(!P_GiveWeapon(plr, WT_SIXTH, TXT_WPNPHOENIXROD, !mapSetup? SFX_WPNUP : 0)) - return false; - break; + return pickupWeapon(plr, WT_SIXTH, TXT_WPNPHOENIXROD); case IT_WEAPON_GAUNTLETS: - if(!P_GiveWeapon(plr, WT_EIGHTH, TXT_WPNGAUNTLETS, !mapSetup? SFX_WPNUP : 0)) - return false; - break; + return pickupWeapon(plr, WT_EIGHTH, TXT_WPNGAUNTLETS); default: Con_Error("giveItem: Unknown item %i.", (int) item); @@ -826,12 +896,15 @@ static boolean giveItem(player_t* plr, itemtype_t item, int quantity) return true; } -void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) +void P_TouchSpecialMobj(mobj_t *special, mobj_t *toucher) { - player_t* player; + player_t *player; coord_t delta; itemtype_t item; + DENG_ASSERT(special != 0); + DENG_ASSERT(toucher != 0); + delta = special->origin[VZ] - toucher->origin[VZ]; if(delta > toucher->height || delta < -32) { @@ -847,7 +920,11 @@ void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) // Identify by sprite. if((item = getItemTypeBySprite(special->sprite)) != IT_NONE) { - if(!giveItem(player, item, special->health)) + // In Heretic the number of rounds to give for an ammo type is defined + // by the 'health' of the mobj. + int quantity = MAX_OF(special->health, 0); + + if(!pickupItem(player, item, quantity)) return; // Don't destroy the item. } else @@ -879,9 +956,15 @@ void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) default: if(deathmatch && !(special->flags & MF_DROPPED)) - P_HideSpecialThing(special); + { + special->flags &= ~MF_SPECIAL; + special->flags2 |= MF2_DONTDRAW; + P_MobjChangeState(special, S_HIDESPECIAL1); + } else + { P_MobjRemove(special, false); + } if(!mapSetup) player->bonusCount += BONUSADD; @@ -889,9 +972,9 @@ void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) } } -void P_KillMobj(mobj_t* source, mobj_t* target) +static void killMobj(mobj_t *source, mobj_t *target) { - statenum_t state; + statenum_t state; if(!target) // Nothing to kill. return; @@ -968,27 +1051,28 @@ void P_KillMobj(mobj_t* source, mobj_t* target) if((state = P_GetState(target->type, SN_XDEATH)) != S_NULL && target->health < -(target->info->spawnHealth / 2)) - { // Extreme death. + { + // Extreme death. P_MobjChangeState(target, state); } else - { // Normal death. + { + // Normal death. P_MobjChangeState(target, P_GetState(target->type, SN_DEATH)); } target->tics -= P_Random() & 3; } -/** - * @return @c true, if the player is morphed. - */ -boolean P_MorphPlayer(player_t* player) +boolean P_MorphPlayer(player_t *player) { - mobj_t* pmo, *fog, *chicken; + mobj_t *pmo, *fog, *chicken; coord_t pos[3]; angle_t angle; int oldFlags2; + DENG_ASSERT(player != 0); + #ifdef _DEBUG Con_Message("P_MorphPlayer: Player %i.", (int)(player - players)); #endif @@ -1044,14 +1128,16 @@ boolean P_MorphPlayer(player_t* player) return true; } -boolean P_MorphMonster(mobj_t* actor) +static boolean morphMonster(mobj_t *actor) { - mobj_t* fog, *chicken, *target; + mobj_t *fog, *chicken, *target; mobjtype_t moType; coord_t pos[3]; angle_t angle; int ghost; + DENG_ASSERT(actor != 0); + if(actor->player) return false; @@ -1092,11 +1178,13 @@ boolean P_MorphMonster(mobj_t* actor) return true; } -boolean P_AutoUseChaosDevice(player_t* player) +static boolean autoUseChaosDevice(player_t *player) { - int plrnum = player - players; + int plrnum = player - players; - //// \todo Do this in the inventory code? + DENG_ASSERT(player != 0); + + /// @todo Do this in the inventory code? if(P_InventoryCount(plrnum, IIT_TELEPORT)) { P_InventoryUse(plrnum, IIT_TELEPORT, false); @@ -1108,16 +1196,18 @@ boolean P_AutoUseChaosDevice(player_t* player) return false; } -void P_AutoUseHealth(player_t* player, int saveHealth) +static void autoUseHealth(player_t *player, int saveHealth) { - uint i, count; - int plrnum = player - players; - int normalCount = P_InventoryCount(plrnum, IIT_HEALTH); - int superCount = P_InventoryCount(plrnum, IIT_SUPERHEALTH); + uint i, count; + int plrnum = player - players; + int normalCount = P_InventoryCount(plrnum, IIT_HEALTH); + int superCount = P_InventoryCount(plrnum, IIT_SUPERHEALTH); + + DENG_ASSERT(player != 0); if(!player->plr->mo) return; - //// \todo Do this in the inventory code? + /// @todo Do this in the inventory code? if(gameSkill == SM_BABY && normalCount * 25 >= saveHealth) { // Use quartz flasks. @@ -1161,29 +1251,13 @@ void P_AutoUseHealth(player_t* player, int saveHealth) player->plr->mo->health = player->health; } -int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, - int damageP, boolean stomping) -{ - return P_DamageMobj2(target, inflictor, source, damageP, stomping, false); -} - -/** - * Damages both enemies and players. - * - * @param inflictor Mobj that caused the damage creature or missile, - * can be NULL (slime, etc) - * @param source Mobj to target after taking damage. Can be @c NULL - * for barrel explosions and other environmental stuff. - * Source and inflictor are the same for melee attacks. - * @return Actual amount of damage done. - */ -int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, +int P_DamageMobj2(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damageP, boolean stomping, boolean skipNetworkCheck) { - angle_t angle; - int saved, originalHealth; - player_t* player; - int temp, damage; + angle_t angle; + int saved, originalHealth; + player_t *player; + int temp, damage; if(!target) return 0; // Wha? @@ -1273,7 +1347,7 @@ int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, } else { - P_MorphMonster(target); + morphMonster(target); } return 0; // Does no actual "damage" but health IS modified. @@ -1349,7 +1423,7 @@ int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, // Does the player have a Chaos Device he can use to get // him out of trouble? - if(P_AutoUseChaosDevice(target->player)) + if(autoUseChaosDevice(target->player)) return originalHealth - target->health; // He's lucky... this time. } @@ -1477,8 +1551,9 @@ int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, if(damage >= player->health && ((gameSkill == SM_BABY) || deathmatch) && !player->morphTics) - { // Try to use some inventory health. - P_AutoUseHealth(player, damage - player->health + 1); + { + // Try to use some inventory health. + autoUseHealth(player, damage - player->health + 1); } player->health -= damage; @@ -1505,7 +1580,8 @@ int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, // Do the damage. target->health -= damage; if(target->health > 0) - { // Still alive, phew! + { + // Still alive, phew! if((P_Random() < target->info->painChance) && !(target->flags & MF_SKULLFLY)) { @@ -1538,7 +1614,8 @@ int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, } } else - { // Death. + { + // Death. target->special1 = damage; if(target->type == MT_POD && source && source->type != MT_POD) { @@ -1557,10 +1634,16 @@ int P_DamageMobj2(mobj_t* target, mobj_t* inflictor, mobj_t* source, } } - P_KillMobj(source, target); + killMobj(source, target); } return originalHealth - target->health; #undef BASETHRESHOLD } + +int P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, + int damageP, boolean stomping) +{ + return P_DamageMobj2(target, inflictor, source, damageP, stomping, false); +} diff --git a/doomsday/plugins/heretic/src/p_pspr.c b/doomsday/plugins/heretic/src/p_pspr.c index c89dfb30b2..1213c74bc4 100644 --- a/doomsday/plugins/heretic/src/p_pspr.c +++ b/doomsday/plugins/heretic/src/p_pspr.c @@ -1775,7 +1775,7 @@ void C_DECL A_GauntletAttack(player_t* player, pspdef_t* psp) if(player->powers[PT_WEAPONLEVEL2]) { - P_GiveBody(player, damage / 2); + P_GiveHealth(player, damage / 2); S_StartSoundEx(SFX_GNTPOW, player->plr->mo); } else @@ -1986,7 +1986,7 @@ void C_DECL A_Health(mobj_t* mo) if(!mo->player) return; - didUseItem = P_GiveBody(mo->player, 25); + didUseItem = P_GiveHealth(mo->player, 25); } void C_DECL A_SuperHealth(mobj_t* mo) @@ -1994,7 +1994,7 @@ void C_DECL A_SuperHealth(mobj_t* mo) if(!mo->player) return; - didUseItem = P_GiveBody(mo->player, 100); + didUseItem = P_GiveHealth(mo->player, 100); } void C_DECL A_Invisibility(mobj_t* mo)