Merge branch 'master' of https://github.com/rheit/zdoom into z_osx_clean

This commit is contained in:
alexey.lysiuk 2014-11-02 16:00:53 +02:00
commit 1074a031a2
30 changed files with 430 additions and 153 deletions

View file

@ -344,6 +344,8 @@ enum
MF7_HARMFRIENDS = 0x00000020, // is allowed to harm friendly monsters.
MF7_BUDDHA = 0x00000040, // Behaves just like the buddha cheat.
MF7_FOILBUDDHA = 0x00000080, // Similar to FOILINVUL, foils buddha mode.
MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag.
MF7_ALLOWPAIN = 0x00000200, // Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't.
// --- mobj.renderflags ---

View file

@ -125,7 +125,7 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
bot = bot->next;
if (bot)
{
bot->inuse = false;
bot->inuse = BOTINUSE_No;
bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE;
}
if (players[i].Bot != NULL)
@ -172,7 +172,7 @@ CCMD (listbots)
while (thebot)
{
Printf ("%s%s\n", thebot->name, thebot->inuse ? " (active)" : "");
Printf ("%s%s\n", thebot->name, thebot->inuse == BOTINUSE_Yes ? " (active)" : "");
thebot = thebot->next;
count++;
}

View file

@ -60,6 +60,13 @@ struct botskill_t
FArchive &operator<< (FArchive &arc, botskill_t &skill);
enum
{
BOTINUSE_No,
BOTINUSE_Waiting,
BOTINUSE_Yes,
};
//Info about all bots in the bots.cfg
//Updated during each level start.
//Info given to bots when they're spawned.
@ -69,7 +76,7 @@ struct botinfo_t
char *name;
char *info;
botskill_t skill;
bool inuse;
int inuse;
int lastteam;
};
@ -88,7 +95,7 @@ public:
bool SpawnBot (const char *name, int color = NOCOLOR);
bool LoadBots ();
void ForgetBots ();
void DoAddBot (BYTE **stream);
void TryAddBot (BYTE **stream, int player);
void RemoveAllBots (bool fromlist);
void DestroyAllBots ();
@ -122,6 +129,9 @@ public:
bool m_Thinking;
private:
//(B_Game.c)
bool DoAddBot (BYTE *info, botskill_t skill);
//(B_Func.c)
bool Reachable (AActor *actor, AActor *target);
void Dofire (AActor *actor, ticcmd_t *cmd);

View file

@ -89,8 +89,6 @@ enum
BOTCFG_TEAM
};
static bool waitingforspawn[MAXPLAYERS];
FCajunMaster::~FCajunMaster()
{
ForgetBots();
@ -162,8 +160,6 @@ void FCajunMaster::Main (int buf)
void FCajunMaster::Init ()
{
int i;
botnum = 0;
firstthing = NULL;
spawn_tries = 0;
@ -172,11 +168,6 @@ void FCajunMaster::Init ()
body1 = NULL;
body2 = NULL;
for (i = 0; i < MAXPLAYERS; i++)
{
waitingforspawn[i] = false;
}
if (ctf && teamplay == false)
teamplay = true; //Need teamplay for ctf. (which is not done yet)
@ -192,7 +183,7 @@ void FCajunMaster::Init ()
while (thebot != NULL)
{
thebot->inuse = false;
thebot->inuse = BOTINUSE_No;
thebot = thebot->next;
}
}
@ -232,12 +223,10 @@ void FCajunMaster::End ()
//The color parameter can be either a
//color (range from 0-10), or = NOCOLOR.
//The color parameter overides bots
//induvidual colors if not = NOCOLOR.
//individual colors if not = NOCOLOR.
bool FCajunMaster::SpawnBot (const char *name, int color)
{
int playernumber;
//COLORS
static const char colors[11][17] =
{
@ -254,36 +243,31 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
"\\color\\cf df 90" //10 = Bleached Bone
};
for (playernumber = 0; playernumber < MAXPLAYERS; playernumber++)
{
if (!playeringame[playernumber] && !waitingforspawn[playernumber])
{
break;
}
}
if (playernumber == MAXPLAYERS)
{
Printf ("The maximum of %d players/bots has been reached\n", MAXPLAYERS);
return false;
}
botinfo_t *thebot;
int botshift;
if (name)
{
thebot = botinfo;
// Check if exist or already in the game.
botshift = 0;
while (thebot && stricmp (name, thebot->name))
{
thebot = thebot->next;
botshift++;
}
if (thebot == NULL)
{
Printf ("couldn't find %s in %s\n", name, BOTFILENAME);
return false;
}
else if (thebot->inuse)
else if (thebot->inuse == BOTINUSE_Waiting)
{
return false;
}
else if (thebot->inuse == BOTINUSE_Yes)
{
Printf ("%s is already in the thick\n", name);
return false;
@ -296,9 +280,13 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
{
int rnum = (pr_botspawn() % loaded_bots);
thebot = botinfo;
botshift = 0;
while (rnum)
{
--rnum, thebot = thebot->next;
if (!thebot->inuse)
botshift++;
}
if (thebot->inuse == BOTINUSE_No)
vacant = true;
}
}
@ -308,10 +296,10 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
return false;
}
waitingforspawn[playernumber] = true;
thebot->inuse = BOTINUSE_Waiting;
Net_WriteByte (DEM_ADDBOT);
Net_WriteByte (playernumber);
Net_WriteByte (botshift);
{
//Set color.
char concat[512];
@ -332,61 +320,104 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
Net_WriteByte(thebot->skill.reaction);
Net_WriteByte(thebot->skill.isp);
thebot->inuse = true;
//Increment this.
botnum++;
return true;
}
void FCajunMaster::DoAddBot (BYTE **stream)
void FCajunMaster::TryAddBot (BYTE **stream, int player)
{
int bnum = ReadByte (stream);
int botshift = ReadByte (stream);
char *info = ReadString (stream);
BYTE *infob = (BYTE *)info;
botskill_t skill;
skill.aiming = ReadByte (stream);
skill.perfection = ReadByte (stream);
skill.reaction = ReadByte (stream);
skill.isp = ReadByte (stream);
D_ReadUserInfoStrings (bnum, &infob, false);
botinfo_t *thebot = NULL;
if (consoleplayer == player)
{
thebot = botinfo;
while (botshift > 0)
{
thebot = thebot->next;
botshift--;
}
}
if (DoAddBot ((BYTE *)info, skill))
{
if (consoleplayer == Net_Arbitrator)
{
//Increment this.
botnum++;
}
if (thebot != NULL)
{
thebot->inuse = BOTINUSE_Yes;
}
}
else
{
if (thebot != NULL)
{
thebot->inuse = BOTINUSE_No;
}
}
delete[] info;
}
bool FCajunMaster::DoAddBot (BYTE *info, botskill_t skill)
{
int bnum;
for (bnum = 0; bnum < MAXPLAYERS; bnum++)
{
if (!playeringame[bnum])
{
break;
}
}
if (bnum == MAXPLAYERS)
{
Printf ("The maximum of %d players/bots has been reached\n", MAXPLAYERS);
return false;
}
D_ReadUserInfoStrings (bnum, &info, false);
if (!deathmatch && playerstarts[bnum].type == 0)
{
Printf ("%s tried to join, but there was no player %d start\n",
players[bnum].userinfo.GetName(), bnum+1);
ClearPlayer (bnum, false); // Make the bot inactive again
if (botnum > 0)
{
botnum--;
}
return false;
}
multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost).
players[bnum].Bot = new DBot;
GC::WriteBarrier (players[bnum].Bot);
players[bnum].Bot->skill = skill;
playeringame[bnum] = true;
players[bnum].mo = NULL;
players[bnum].playerstate = PST_ENTER;
if (teamplay)
Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName());
else
Printf ("%s joined the game\n", players[bnum].userinfo.GetName());
G_DoReborn (bnum, true);
if (StatusBar != NULL)
{
multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost).
players[bnum].Bot = new DBot;
GC::WriteBarrier (players[bnum].Bot);
players[bnum].Bot->skill = skill;
playeringame[bnum] = true;
players[bnum].mo = NULL;
players[bnum].playerstate = PST_ENTER;
if (teamplay)
Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName());
else
Printf ("%s joined the game\n", players[bnum].userinfo.GetName());
G_DoReborn (bnum, true);
if (StatusBar != NULL)
{
StatusBar->MultiplayerChanged ();
}
StatusBar->MultiplayerChanged ();
}
waitingforspawn[bnum] = false;
return true;
}
void FCajunMaster::RemoveAllBots (bool fromlist)
@ -421,8 +452,6 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
if (fromlist)
{
wanted_botnum = 0;
for (i = 0; i < MAXPLAYERS; i++)
waitingforspawn[i] = false;
}
botnum = 0;
}

View file

@ -61,6 +61,7 @@ typedef enum
ga_loadlevel,
ga_newgame,
ga_newgame2,
ga_recordgame,
ga_loadgame,
ga_loadgamehidecon,
ga_loadgameplaydemo,

View file

@ -1338,6 +1338,7 @@ CCMD (endgame)
{
gameaction = ga_fullconsole;
demosequence = -1;
G_CheckDemoStatus();
}
}

View file

@ -2250,7 +2250,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
break;
case DEM_ADDBOT:
bglobal.DoAddBot (stream);
bglobal.TryAddBot (stream, player);
break;
case DEM_KILLBOTS:

View file

@ -112,7 +112,7 @@ enum EDemoCommand
DEM_DROPPLAYER, // 13 Not implemented, takes a byte
DEM_CHANGEMAP, // 14 Name of map to change to
DEM_SUICIDE, // 15 Player wants to die
DEM_ADDBOT, // 16 Byte: player#, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp)
DEM_ADDBOT, // 16 Byte: botshift, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp)
DEM_KILLBOTS, // 17 Remove all bots from the world
DEM_INVUSEALL, // 18 Use every item (panic!)
DEM_INVUSE, // 19 4 bytes: ID of item to use

View file

@ -136,6 +136,8 @@ extern int consoleplayer;
// Disable save/end game?
extern bool usergame;
extern FString newdemoname;
extern FString newdemomap;
extern bool demoplayback;
extern bool demorecording;
extern int demover;

View file

@ -162,6 +162,8 @@ int consoleplayer; // player taking events
int gametic;
CVAR(Bool, demo_compress, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
FString newdemoname;
FString newdemomap;
FString demoname;
bool demorecording;
bool demoplayback;
@ -1048,6 +1050,10 @@ void G_Ticker ()
case ga_loadlevel:
G_DoLoadLevel (-1, false);
break;
case ga_recordgame:
G_CheckDemoStatus();
G_RecordDemo(newdemoname);
G_BeginRecording(newdemomap);
case ga_newgame2: // Silence GCC (see above)
case ga_newgame:
G_DoNewGame ();
@ -2434,6 +2440,16 @@ void G_DeferedPlayDemo (const char *name)
CCMD (playdemo)
{
if (netgame)
{
Printf("End your current netgame first!");
return;
}
if (demorecording)
{
Printf("End your current demo first!");
return;
}
if (argv.argc() > 1)
{
G_DeferedPlayDemo (argv[1]);

View file

@ -28,10 +28,14 @@ int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype)
{
int randVal;
target->angle += pr_foo.Random2() << 20;
target->velx += pr_foo.Random2() << 10;
target->vely += pr_foo.Random2() << 10;
if ((level.time & 16) && !(target->flags2 & MF2_BOSS))
if (!(target->flags7 & MF7_DONTTHRUST))
{
target->angle += pr_foo.Random2() << 20;
target->velx += pr_foo.Random2() << 10;
target->vely += pr_foo.Random2() << 10;
}
if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_DONTTHRUST))
{
randVal = pr_foo();
if (randVal > 160)

View file

@ -199,6 +199,46 @@ CCMD (map)
//
//==========================================================================
CCMD(recordmap)
{
if (netgame)
{
Printf("You cannot record a new game while in a netgame.");
return;
}
if (argv.argc() > 2)
{
try
{
if (!P_CheckMapData(argv[2]))
{
Printf("No map %s\n", argv[2]);
}
else
{
G_DeferedInitNew(argv[2]);
gameaction = ga_recordgame;
newdemoname = argv[1];
newdemomap = argv[2];
}
}
catch (CRecoverableError &error)
{
if (error.GetMessage())
Printf("%s", error.GetMessage());
}
}
else
{
Printf("Usage: recordmap <filename> <map name>\n");
}
}
//==========================================================================
//
//
//==========================================================================
CCMD (open)
{
if (netgame)
@ -236,6 +276,18 @@ void G_NewInit ()
{
int i;
// Destory all old player refrences that may still exist
TThinkerIterator<APlayerPawn> it(STAT_TRAVELLING);
APlayerPawn *pawn, *next;
next = it.Next();
while ((pawn = next) != NULL)
{
next = it.Next();
pawn->flags |= MF_NOSECTOR | MF_NOBLOCKMAP;
pawn->Destroy();
}
G_ClearSnapshots ();
ST_SetNeedRefresh();
netgame = false;

View file

@ -293,7 +293,6 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_STRING(mCheatKey, "cheatKey")
GAMEINFOKEY_STRING(mEasyKey, "easyKey")
GAMEINFOKEY_STRING(TitlePage, "titlePage")
GAMEINFOKEY_STRING(TitlePage, "titlePage")
GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false)
GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true)
GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false)

View file

@ -3161,7 +3161,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die)
ACTION_PARAM_START(1);
ACTION_PARAM_NAME(damagetype, 0);
P_DamageMobj (self, NULL, NULL, self->health, damagetype, DMG_FORCED);
if (self->flags & MF_MISSILE)
P_ExplodeMissile(self, NULL, NULL);
else
P_DamageMobj (self, NULL, NULL, self->health, damagetype, DMG_FORCED);
}
//

View file

@ -938,6 +938,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
FState * woundstate = NULL;
PainChanceList * pc = NULL;
bool justhit = false;
bool plrDontThrust = false;
bool invulpain = false;
int fakeDamage = 0;
int holdDamage = 0;
if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE)))
{ // Shouldn't happen
@ -972,7 +976,14 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
if (inflictor == NULL || (!(inflictor->flags3 & MF3_FOILINVUL) && !(flags & DMG_FOILINVUL)))
{
return -1;
if (target->flags7 & MF7_ALLOWPAIN)
{
invulpain = true; //This returns -1 later.
fakeDamage = damage;
goto fakepain; //The label is above the massive pile of checks.
}
else
return -1;
}
}
else
@ -980,11 +991,21 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// Players are optionally excluded from getting thrust by damage.
if (static_cast<APlayerPawn *>(target)->PlayerFlags & PPF_NOTHRUSTWHENINVUL)
{
return -1;
if (target->flags7 & MF7_ALLOWPAIN)
plrDontThrust = 1;
else
return -1;
}
}
}
if ((target->flags7 & MF7_ALLOWPAIN) && (damage < TELEFRAG_DAMAGE))
{
//Intentionally do not jump to fakepain because the damage hasn't been dished out yet.
//Once it's dished out, THEN we can disregard damage factors affecting pain chances.
fakeDamage = damage;
}
if (inflictor != NULL)
{
if (inflictor->flags5 & MF5_PIERCEARMOR)
@ -1010,6 +1031,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// Invulnerable, and won't wake up
return -1;
}
player = target->player;
if (player && damage > 1 && damage < TELEFRAG_DAMAGE)
{
@ -1032,10 +1054,13 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
return -1;
}
}
if (damage > 0)
damage = inflictor->DoSpecialDamage (target, damage, mod);
damage = inflictor->DoSpecialDamage (target, damage, mod);
if (damage == -1)
{
if (target->flags7 & MF7_ALLOWPAIN) //Hold off ending the function before we can deal the pain chances.
goto fakepain;
return -1;
}
}
@ -1053,17 +1078,20 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
return -1;
}
}
// Handle passive damage modifiers (e.g. PowerProtection)
if (target->Inventory != NULL)
// Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers.
if ((target->Inventory != NULL) && !(flags & DMG_NO_PROTECT))
{
int olddam = damage;
target->Inventory->ModifyDamage(olddam, mod, damage, true);
if (olddam != damage && damage <= 0)
{ // Still allow FORCEPAIN
if (((target->flags7 & MF7_ALLOWPAIN) && (fakeDamage <= 0)) || (olddam != damage && damage <= 0))
{ // Still allow FORCEPAIN and make sure we're still passing along fake damage to hit enemies for their pain states.
if (MustForcePain(target, inflictor))
{
goto dopain;
}
else if (target->flags7 & MF7_ALLOWPAIN)
goto fakepain;
return -1;
}
}
@ -1081,22 +1109,29 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
goto dopain;
}
else if (target->flags7 & MF7_ALLOWPAIN)
goto fakepain;
return -1;
}
}
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
if (damage > 0)
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
}
if (damage == -1)
{
if (target->flags7 & MF7_ALLOWPAIN)
goto fakepain;
return -1;
}
// Push the target unless the source's weapon's kickback is 0.
// (i.e. Gauntlets/Chainsaw)
if (inflictor && inflictor != target // [RH] Not if hurting own self
if (!(plrDontThrust) && inflictor && inflictor != target // [RH] Not if hurting own self
&& !(target->flags & MF_NOCLIP)
&& !(inflictor->flags2 & MF2_NODMGTHRUST)
&& !(flags & DMG_THRUSTLESS)
&& !(target->flags7 & MF7_DONTTHRUST)
&& (source == NULL || source->player == NULL || !(source->flags2 & MF2_NODMGTHRUST)))
{
int kickback;
@ -1133,11 +1168,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust);
}
thrust = FLOAT2FIXED(fltthrust);
// Don't apply ultra-small damage thrust
if (thrust < FRACUNIT/100) thrust = 0;
// Don't apply ultra-small damage thrust.
if (thrust < FRACUNIT / 100)
thrust = 0;
// make fall forwards sometimes
if ((damage < 40) && (damage > target->health)
@ -1146,8 +1180,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// [RH] But only if not too fast and not flying
&& thrust < 10*FRACUNIT
&& !(target->flags & MF_NOGRAVITY)
&& (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL))
)
&& (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL)))
{
ang += ANG180;
thrust *= 4;
@ -1214,6 +1247,12 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
(player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE))
//Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2.
{ // player is invulnerable, so don't hurt him
if (player->mo->flags7 & MF7_ALLOWPAIN)
{
invulpain = true;
fakeDamage = damage;
goto fakepain;
}
return -1;
}
@ -1231,7 +1270,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
// If MF6_FORCEPAIN is set, make the player enter the pain state.
if (!(target->flags5 & MF5_NOPAIN) && inflictor != NULL &&
(inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS))
(inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS) &&
(!(player->mo->flags2 & MF2_INVULNERABLE)))
{
goto dopain;
}
@ -1295,7 +1335,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
damage = newdam;
if (damage <= 0)
{
return damage;
if (target->flags7 & MF7_ALLOWPAIN)
goto fakepain;
else
return damage;
}
}
@ -1324,7 +1367,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (target->health <= 0)
{
if ((target->flags7 & MF7_BUDDHA) && (damage < TELEFRAG_DAMAGE) && (!(inflictor->flags3 & MF7_FOILBUDDHA) && !(flags & DMG_FOILBUDDHA)))
{ //Make sure FOILINVUL flags work here too for monsters. Or perhaps consider a FOILBUDDHA flag...
{ //FOILBUDDHA or Telefrag damage must kill it.
target->health = 1;
}
else
@ -1382,6 +1425,12 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
}
}
fakepain: //Needed so we can skip the rest of the above, but still obey the original rules.
if (target->flags7 & MF7_ALLOWPAIN && (fakeDamage != damage))
{
holdDamage = damage;
damage = fakeDamage;
}
if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) &&
(target->player != NULL || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY))
@ -1473,6 +1522,14 @@ dopain:
if (justhit && (target->target == source || !target->target || !target->IsFriend(target->target)))
target->flags |= MF_JUSTHIT; // fight back!
if (invulpain) //Note that this takes into account all the cheats a player has, in terms of invulnerability.
{
return -1; //NOW we return -1!
}
else if (target->flags7 & MF7_ALLOWPAIN)
{
return holdDamage;
}
return damage;
}
@ -1591,7 +1648,7 @@ bool AActor::OkayToSwitchTarget (AActor *other)
bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poison)
{
if((player->cheats&CF_GODMODE) || (player->mo->flags2 & MF2_INVULNERABLE))
if((player->cheats&CF_GODMODE) || (player->mo->flags2 & MF2_INVULNERABLE) || (player->cheats & CF_GODMODE2))
{
return false;
}
@ -1642,8 +1699,8 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage,
{
return;
}
if (damage < TELEFRAG_DAMAGE && ((target->flags2 & MF2_INVULNERABLE) ||
(player->cheats & CF_GODMODE)))
if ((damage < TELEFRAG_DAMAGE && ((target->flags2 & MF2_INVULNERABLE) ||
(player->cheats & CF_GODMODE))) || (player->cheats & CF_GODMODE2))
{ // target is invulnerable
return;
}

View file

@ -560,6 +560,7 @@ enum EDmgFlags
DMG_PLAYERATTACK = 32,
DMG_FOILINVUL = 64,
DMG_FOILBUDDHA = 128,
DMG_NO_PROTECT = 256,
};

View file

@ -4679,7 +4679,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
if (!(flags & RADF_NODAMAGE))
newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod);
else if (thing->player == NULL && !(flags & RADF_NOIMPACTDAMAGE))
else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE) && !(thing->flags7 & MF7_DONTTHRUST)))
thing->flags2 |= MF2_BLASTED;
if (!(thing->flags & MF_ICECORPSE))
@ -4691,25 +4691,29 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
{
if (bombsource == NULL || !(bombsource->flags2 & MF2_NODMGTHRUST))
{
thrust = points * 0.5f / (double)thing->Mass;
if (bombsource == thing)
if (!(thing->flags7 & MF7_DONTTHRUST))
{
thrust *= selfthrustscale;
thrust = points * 0.5f / (double)thing->Mass;
if (bombsource == thing)
{
thrust *= selfthrustscale;
}
velz = (double)(thing->z + (thing->height >> 1) - bombspot->z) * thrust;
if (bombsource != thing)
{
velz *= 0.5f;
}
else
{
velz *= 0.8f;
}
angle_t ang = R_PointToAngle2(bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT;
thing->velx += fixed_t(finecosine[ang] * thrust);
thing->vely += fixed_t(finesine[ang] * thrust);
if (!(flags & RADF_NODAMAGE))
thing->velz += (fixed_t)velz; // this really doesn't work well
}
velz = (double)(thing->z + (thing->height >> 1) - bombspot->z) * thrust;
if (bombsource != thing)
{
velz *= 0.5f;
}
else
{
velz *= 0.8f;
}
angle_t ang = R_PointToAngle2(bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT;
thing->velx += fixed_t(finecosine[ang] * thrust);
thing->vely += fixed_t(finesine[ang] * thrust);
if (!(flags & RADF_NODAMAGE))
thing->velz += (fixed_t)velz; // this really doesn't work well
}
}
}

View file

@ -1167,7 +1167,7 @@ bool AActor::Massacre ()
P_DamageMobj (this, NULL, NULL, TELEFRAG_DAMAGE, NAME_Massacre);
}
while (health != prevhealth && health > 0); //abort if the actor wasn't hurt.
return true;
return health <= 0;
}
return false;
}
@ -5986,7 +5986,7 @@ bool AActor::IsHostile (AActor *other)
int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype)
{
if (target->player && target->player->mo == target && damage < 1000 &&
(target->player->cheats & CF_GODMODE))
(target->player->cheats & CF_GODMODE || target->player->cheats & CF_GODMODE2))
{
return -1;
}

View file

@ -280,7 +280,7 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name)
}
if (thebot)
{
thebot->inuse = true;
thebot->inuse = BOTINUSE_Yes;
}
bglobal.botnum++;
dst->userinfo.TransferFrom(uibackup2);

View file

@ -714,6 +714,7 @@ void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass,
//============================================================================
CVAR(Bool, showsecretsector, false, 0)
CVAR(Bool, cl_showsecretmessage, true, CVAR_ARCHIVE)
void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum)
{
@ -723,7 +724,7 @@ void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornu
{
actor->player->secretcount++;
}
if (actor->CheckLocalView (consoleplayer))
if (cl_showsecretmessage && actor->CheckLocalView(consoleplayer))
{
if (printmessage)
{

View file

@ -402,10 +402,14 @@ void P_RemoveThing(AActor * actor)
// Don't remove live players.
if (actor->player == NULL || actor != actor->player->mo)
{
// Don't also remove owned inventory items
if (actor->IsKindOf(RUNTIME_CLASS(AInventory)) && static_cast<AInventory*>(actor)->Owner != NULL) return;
// be friendly to the level statistics. ;)
actor->ClearCounters();
actor->Destroy ();
}
}
bool P_Thing_Raise(AActor *thing)

View file

@ -696,6 +696,7 @@ public:
case NAME_FillColor:
th->fillcolor = CheckInt(key);
break;
case NAME_Health:
th->health = CheckInt(key);
@ -1540,11 +1541,11 @@ public:
double ulen = TVector3<double>(cp[0], cp[1], cp[2]).Length();
// normalize the vector, it must have a length of 1
sec->floorplane.a = FLOAT2FIXED(cp[0] / ulen);
sec->floorplane.b = FLOAT2FIXED(cp[1] / ulen);
sec->floorplane.c = FLOAT2FIXED(cp[2] / ulen);
sec->floorplane.d = FLOAT2FIXED(cp[3] / ulen);
sec->floorplane.ic = FLOAT2FIXED(ulen / cp[2]);
sec->ceilingplane.a = FLOAT2FIXED(cp[0] / ulen);
sec->ceilingplane.b = FLOAT2FIXED(cp[1] / ulen);
sec->ceilingplane.c = FLOAT2FIXED(cp[2] / ulen);
sec->ceilingplane.d = FLOAT2FIXED(cp[3] / ulen);
sec->ceilingplane.ic = FLOAT2FIXED(ulen / cp[2]);
}
if (lightcolor == -1 && fadecolor == -1 && desaturation == -1)

View file

@ -2588,7 +2588,8 @@ void P_PlayerThink (player_t *player)
{
if (player->mo->waterlevel < 3 ||
(player->mo->flags2 & MF2_INVULNERABLE) ||
(player->cheats & (CF_GODMODE | CF_NOCLIP2)))
(player->cheats & (CF_GODMODE | CF_NOCLIP2)) ||
(player->cheats & CF_GODMODE2))
{
player->mo->ResetAirSupply ();
}

View file

@ -1677,6 +1677,31 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToTarget)
DoGiveInventory(self->target, PUSH_PARAMINFO);
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren)
{
TThinkerIterator<AActor> it;
AActor * mo;
while ((mo = it.Next()))
{
if (mo->master == self) DoGiveInventory(mo, PUSH_PARAMINFO);
}
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings)
{
TThinkerIterator<AActor> it;
AActor * mo;
if (self->master != NULL)
{
while ((mo = it.Next()))
{
if (mo->master == self->master && mo != self) DoGiveInventory(mo, PUSH_PARAMINFO);
}
}
}
//===========================================================================
//
// A_TakeInventory
@ -1737,6 +1762,31 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromTarget)
DoTakeInventory(self->target, PUSH_PARAMINFO);
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromChildren)
{
TThinkerIterator<AActor> it;
AActor * mo;
while ((mo = it.Next()))
{
if (mo->master == self) DoTakeInventory(mo, PUSH_PARAMINFO);
}
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromSiblings)
{
TThinkerIterator<AActor> it;
AActor * mo;
if (self->master != NULL)
{
while ((mo = it.Next()))
{
if (mo->master == self->master && mo != self) DoTakeInventory(mo, PUSH_PARAMINFO);
}
}
}
//===========================================================================
//
// Common code for A_SpawnItem and A_SpawnItemEx
@ -4004,6 +4054,7 @@ enum T_Flags
{
TF_TELEFRAG = 1, // Allow telefrag in order to teleport.
TF_RANDOMDECIDE = 2, // Randomly fail based on health. (A_Srcr2Decide)
TF_FORCED = 4, // Forget what's in the way. TF_Telefrag takes precedence though.
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
@ -4053,7 +4104,20 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
fixed_t prevX = self->x;
fixed_t prevY = self->y;
fixed_t prevZ = self->z;
if (P_TeleportMove (self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG))
bool teleResult = false;
//Take precedence and cooperate with telefragging first.
if (P_TeleportMove(self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG))
teleResult = true;
if ((!(teleResult)) && (Flags & TF_FORCED))
{
//If for some reason the original move didn't work, regardless of telefrag, force it to move.
self->SetOrigin(spot->x, spot->y, spot->z);
teleResult = true;
}
if (teleResult)
{
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
@ -4459,7 +4523,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
self->PrevY = self->y + reference->PrevY - reference->y;
self->PrevZ = self->z + reference->PrevZ - reference->z;
}
else if (! (flags & WARPF_INTERPOLATE))
else if (!(flags & WARPF_INTERPOLATE))
{
self->PrevX = self->x;
self->PrevY = self->y;
@ -4608,17 +4672,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedTerminate)
//==========================================================================
enum RadiusGiveFlags
{
RGF_GIVESELF = 1,
RGF_PLAYERS = 2,
RGF_MONSTERS = 4,
RGF_OBJECTS = 8,
RGF_VOODOO = 16,
RGF_CORPSES = 32,
RGF_MASK = 63,
RGF_NOTARGET = 64,
RGF_NOTRACER = 128,
RGF_NOMASTER = 256,
RGF_CUBE = 512,
RGF_GIVESELF = 1 << 0,
RGF_PLAYERS = 1 << 1,
RGF_MONSTERS = 1 << 2,
RGF_OBJECTS = 1 << 3,
RGF_VOODOO = 1 << 4,
RGF_CORPSES = 1 << 5,
RGF_MASK = 63,
RGF_NOTARGET = 1 << 6,
RGF_NOTRACER = 1 << 7,
RGF_NOMASTER = 1 << 8,
RGF_CUBE = 1 << 9,
RGF_NOSIGHT = 1 << 10,
RGF_MISSILES = 1 << 11,
};
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
@ -4699,6 +4765,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
continue;
}
}
else if (thing->flags & MF_MISSILE)
{
if (!(flags & RGF_MISSILES))
{
continue;
}
}
else
{
continue;
@ -4724,8 +4797,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
}
fixed_t dz = abs ((thing->z + thing->height/2) - (self->z + self->height/2));
if (P_CheckSight (thing, self, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY))
{ // OK to give; target is in direct path
if ((flags & RGF_NOSIGHT) || P_CheckSight (thing, self, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY))
{ // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight.
AInventory *gift = static_cast<AInventory *>(Spawn (item, 0, 0, 0, NO_REPLACE));
if (gift->IsKindOf(RUNTIME_CLASS(AHealth)))
{
@ -4832,6 +4905,7 @@ enum DMSS
DMSS_KILL = 4,
DMSS_NOFACTOR = 8,
DMSS_FOILBUDDHA = 16,
DMSS_NOPROTECT = 32,
};
static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags)
@ -4847,6 +4921,8 @@ static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageTy
dmgFlags += DMG_NO_ARMOR;
if (flags & DMSS_KILL) //Kill adds the value of the damage done to it. Allows for more controlled extreme death types.
amount += dmgtarget->health;
if (flags & DMSS_NOPROTECT) //Ignore PowerProtection.
dmgFlags += DMG_NO_PROTECT;
if (amount > 0)
P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine.

View file

@ -244,6 +244,8 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7),
DEFINE_FLAG(MF7, BUDDHA, AActor, flags7),
DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7),
DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7),
DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -767,7 +767,7 @@ void FHexenStartupScreen::NetProgress(int count)
y = ST_NETPROGRESS_Y;
ST_Util_DrawBlock (StartupBitmap, NetNotchBits, x, y, ST_NETNOTCH_WIDTH / 2, ST_NETNOTCH_HEIGHT);
}
S_Sound (CHAN_BODY, "Drip", 1, ATTN_NONE);
S_Sound (CHAN_BODY, "misc/netnotch", 1, ATTN_NONE);
I_GetEvent ();
}
}

View file

@ -312,6 +312,10 @@ ACTOR Actor native //: Thinker
action native A_RemoveTarget(int flags = 0);
action native A_RemoveTracer(int flags = 0);
action native A_Remove(int removee, int flags = 0);
action native A_GiveToChildren(class<Inventory> itemtype, int amount = 0);
action native A_GiveToSiblings(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromChildren(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromSiblings(class<Inventory> itemtype, int amount = 0);
action native A_CheckSightOrRange(float distance, state label);
action native A_CheckRange(float distance, state label);

View file

@ -181,7 +181,9 @@ const int FPF_AIMATANGLE = 1;
const int FPF_TRANSFERTRANSLATION = 2;
// Flags for A_Teleport
const int TF_TELEFRAG = 1;const int TF_RANDOMDECIDE = 2;
const int TF_TELEFRAG = 1;
const int TF_RANDOMDECIDE = 2;
const int TF_FORCED = 4;
// Flags for A_WolfAttack
const int WAF_NORANDOM = 1;
@ -191,15 +193,17 @@ const int WAF_USEPUFF = 2;
enum
{
RGF_GIVESELF = 1,
RGF_PLAYERS = 2,
RGF_MONSTERS = 4,
RGF_OBJECTS = 8,
RGF_VOODOO = 16,
RGF_CORPSES = 32,
RGF_NOTARGET = 64,
RGF_NOTRACER = 128,
RGF_NOMASTER = 256,
RGF_CUBE = 512,
RGF_PLAYERS = 1 << 1,
RGF_MONSTERS = 1 << 2,
RGF_OBJECTS = 1 << 3,
RGF_VOODOO = 1 << 4,
RGF_CORPSES = 1 << 5,
RGF_NOTARGET = 1 << 6,
RGF_NOTRACER = 1 << 7,
RGF_NOMASTER = 1 << 8,
RGF_CUBE = 1 << 9,
RGF_NOSIGHT = 1 << 10,
RGF_MISSILES = 1 << 11,
};
// Activation flags
@ -383,6 +387,7 @@ const int DMSS_AFFECTARMOR = 2;
const int DMSS_KILL = 4;
const int DMSS_NOFACTOR = 8;
const int DMSS_FOILBUDDHA = 16;
const int DMSS_NOPROTECT = 32;
// Flags for A_AlertMonsters
const int AMF_TARGETEMITTER = 1;

View file

@ -1098,6 +1098,7 @@ OptionMenu MessageOptions
Title "MESSAGES"
Option "Show messages", "show_messages", "OnOff"
Option "Show obituaries", "show_obituaries", "OnOff"
Option "Show secret notifications", "cl_showsecretmessage", "OnOff"
Option "Scale text in high res", "con_scaletext", "ScaleValues"
Option "Minimum message level", "msg", "MessageLevels"
Option "Center messages", "con_centernotify", "OnOff"

View file

@ -985,6 +985,7 @@ $alias menu/clear PlatformStop
// Hexen does not have ripslop sound like Heretic
misc/ripslop dsempty
misc/netnotch blddrp1
$alias intermission/cooptotal *death
$alias intermission/nextstage DoorCloseLight