mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-24 04:51:41 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom into z_osx_clean
This commit is contained in:
commit
d1c4215fb5
65 changed files with 903 additions and 596 deletions
|
@ -341,6 +341,9 @@ enum
|
||||||
MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings.
|
MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings.
|
||||||
MF7_HANDLENODELAY = 0x00000008, // respect NoDelay state flag
|
MF7_HANDLENODELAY = 0x00000008, // respect NoDelay state flag
|
||||||
MF7_WEAPONSPAWN = 0x00000010, // subject to DF_NO_COOP_WEAPON_SPAWN dmflag
|
MF7_WEAPONSPAWN = 0x00000010, // subject to DF_NO_COOP_WEAPON_SPAWN dmflag
|
||||||
|
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.
|
||||||
|
|
||||||
// --- mobj.renderflags ---
|
// --- mobj.renderflags ---
|
||||||
|
|
||||||
|
@ -713,6 +716,9 @@ public:
|
||||||
// Transforms the actor into a finely-ground paste
|
// Transforms the actor into a finely-ground paste
|
||||||
virtual bool Grind(bool items);
|
virtual bool Grind(bool items);
|
||||||
|
|
||||||
|
// Get this actor's team
|
||||||
|
int GetTeam();
|
||||||
|
|
||||||
// Is the other actor on my team?
|
// Is the other actor on my team?
|
||||||
bool IsTeammate (AActor *other);
|
bool IsTeammate (AActor *other);
|
||||||
|
|
||||||
|
|
|
@ -908,8 +908,8 @@ void AM_StaticInit()
|
||||||
|
|
||||||
if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow);
|
if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow);
|
||||||
if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow);
|
if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow);
|
||||||
AM_ParseArrow(CheatKey, "maparrows/key.txt");
|
AM_ParseArrow(CheatKey, gameinfo.mCheatKey);
|
||||||
AM_ParseArrow(EasyKey, "maparrows/ravenkey.txt");
|
AM_ParseArrow(EasyKey, gameinfo.mEasyKey);
|
||||||
if (MapArrow.Size() == 0) I_FatalError("No automap arrow defined");
|
if (MapArrow.Size() == 0) I_FatalError("No automap arrow defined");
|
||||||
|
|
||||||
char namebuf[9];
|
char namebuf[9];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Cajun bot console commands.
|
// Cajun bot
|
||||||
//
|
//
|
||||||
// [RH] Moved out of d_netcmd.c (in Cajun source), because they don't really
|
// [RH] Moved console commands out of d_netcmd.c (in Cajun source), because
|
||||||
// belong there.
|
// they don't really belong there.
|
||||||
|
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
@ -14,6 +14,76 @@
|
||||||
#include "d_net.h"
|
#include "d_net.h"
|
||||||
#include "farchive.h"
|
#include "farchive.h"
|
||||||
|
|
||||||
|
IMPLEMENT_POINTY_CLASS(DBot)
|
||||||
|
DECLARE_POINTER(dest)
|
||||||
|
DECLARE_POINTER(prev)
|
||||||
|
DECLARE_POINTER(enemy)
|
||||||
|
DECLARE_POINTER(missile)
|
||||||
|
DECLARE_POINTER(mate)
|
||||||
|
DECLARE_POINTER(last_mate)
|
||||||
|
END_POINTERS
|
||||||
|
|
||||||
|
DBot::DBot ()
|
||||||
|
{
|
||||||
|
Clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBot::Clear ()
|
||||||
|
{
|
||||||
|
savedyaw = 0;
|
||||||
|
savedpitch = 0;
|
||||||
|
angle = 0;
|
||||||
|
dest = NULL;
|
||||||
|
prev = NULL;
|
||||||
|
enemy = NULL;
|
||||||
|
missile = NULL;
|
||||||
|
mate = NULL;
|
||||||
|
last_mate = NULL;
|
||||||
|
memset(&skill, 0, sizeof(skill));
|
||||||
|
t_active = 0;
|
||||||
|
t_respawn = 0;
|
||||||
|
t_strafe = 0;
|
||||||
|
t_react = 0;
|
||||||
|
t_fight = 0;
|
||||||
|
t_roam = 0;
|
||||||
|
t_rocket = 0;
|
||||||
|
first_shot = true;
|
||||||
|
sleft = false;
|
||||||
|
allround = false;
|
||||||
|
increase = false;
|
||||||
|
oldx = 0;
|
||||||
|
oldy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBot::Serialize (FArchive &arc)
|
||||||
|
{
|
||||||
|
Super::Serialize (arc);
|
||||||
|
|
||||||
|
arc << savedyaw
|
||||||
|
<< savedpitch
|
||||||
|
<< angle
|
||||||
|
<< dest
|
||||||
|
<< prev
|
||||||
|
<< enemy
|
||||||
|
<< missile
|
||||||
|
<< mate
|
||||||
|
<< last_mate
|
||||||
|
<< skill
|
||||||
|
<< t_active
|
||||||
|
<< t_respawn
|
||||||
|
<< t_strafe
|
||||||
|
<< t_react
|
||||||
|
<< t_fight
|
||||||
|
<< t_roam
|
||||||
|
<< t_rocket
|
||||||
|
<< first_shot
|
||||||
|
<< sleft
|
||||||
|
<< allround
|
||||||
|
<< increase
|
||||||
|
<< oldx
|
||||||
|
<< oldy;
|
||||||
|
}
|
||||||
|
|
||||||
CVAR (Int, bot_next_color, 11, 0)
|
CVAR (Int, bot_next_color, 11, 0)
|
||||||
CVAR (Bool, bot_observer, false, 0)
|
CVAR (Bool, bot_observer, false, 0)
|
||||||
|
|
||||||
|
@ -58,6 +128,11 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
|
||||||
bot->inuse = false;
|
bot->inuse = false;
|
||||||
bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE;
|
bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE;
|
||||||
}
|
}
|
||||||
|
if (players[i].Bot != NULL)
|
||||||
|
{
|
||||||
|
players[i].Bot->Destroy ();
|
||||||
|
players[i].Bot = NULL;
|
||||||
|
}
|
||||||
players[i].~player_t();
|
players[i].~player_t();
|
||||||
::new(&players[i]) player_t;
|
::new(&players[i]) player_t;
|
||||||
players[i].userinfo.Reset();
|
players[i].userinfo.Reset();
|
||||||
|
@ -66,6 +141,12 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
|
||||||
|
|
||||||
CCMD (removebots)
|
CCMD (removebots)
|
||||||
{
|
{
|
||||||
|
if (!players[consoleplayer].settings_controller)
|
||||||
|
{
|
||||||
|
Printf ("Only setting controllers can remove bots\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Net_WriteByte (DEM_KILLBOTS);
|
Net_WriteByte (DEM_KILLBOTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
56
src/b_bot.h
56
src/b_bot.h
|
@ -85,12 +85,12 @@ public:
|
||||||
void Main (int buf);
|
void Main (int buf);
|
||||||
void Init ();
|
void Init ();
|
||||||
void End();
|
void End();
|
||||||
void CleanBotstuff (player_t *p);
|
|
||||||
bool SpawnBot (const char *name, int color = NOCOLOR);
|
bool SpawnBot (const char *name, int color = NOCOLOR);
|
||||||
bool LoadBots ();
|
bool LoadBots ();
|
||||||
void ForgetBots ();
|
void ForgetBots ();
|
||||||
void DoAddBot (int bnum, char *info);
|
void DoAddBot (BYTE **stream);
|
||||||
void RemoveAllBots (bool fromlist);
|
void RemoveAllBots (bool fromlist);
|
||||||
|
void DestroyAllBots ();
|
||||||
|
|
||||||
//(B_Func.c)
|
//(B_Func.c)
|
||||||
bool Check_LOS (AActor *mobj1, AActor *mobj2, angle_t vangle);
|
bool Check_LOS (AActor *mobj1, AActor *mobj2, angle_t vangle);
|
||||||
|
@ -109,7 +109,6 @@ public:
|
||||||
bool IsDangerous (sector_t *sec);
|
bool IsDangerous (sector_t *sec);
|
||||||
|
|
||||||
TArray<FString> getspawned; //Array of bots (their names) which should be spawned when starting a game.
|
TArray<FString> getspawned; //Array of bots (their names) which should be spawned when starting a game.
|
||||||
bool botingame[MAXPLAYERS];
|
|
||||||
BYTE freeze:1; //Game in freeze mode.
|
BYTE freeze:1; //Game in freeze mode.
|
||||||
BYTE changefreeze:1; //Game wants to change freeze mode.
|
BYTE changefreeze:1; //Game wants to change freeze mode.
|
||||||
int botnum;
|
int botnum;
|
||||||
|
@ -126,6 +125,7 @@ private:
|
||||||
//(B_Func.c)
|
//(B_Func.c)
|
||||||
bool Reachable (AActor *actor, AActor *target);
|
bool Reachable (AActor *actor, AActor *target);
|
||||||
void Dofire (AActor *actor, ticcmd_t *cmd);
|
void Dofire (AActor *actor, ticcmd_t *cmd);
|
||||||
|
bool IsLeader (player_t *player);
|
||||||
AActor *Choose_Mate (AActor *bot);
|
AActor *Choose_Mate (AActor *bot);
|
||||||
AActor *Find_enemy (AActor *bot);
|
AActor *Find_enemy (AActor *bot);
|
||||||
void SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum);
|
void SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum);
|
||||||
|
@ -145,6 +145,56 @@ protected:
|
||||||
bool observer; //Consoleplayer is observer.
|
bool observer; //Consoleplayer is observer.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DBot : public DObject
|
||||||
|
{
|
||||||
|
DECLARE_CLASS(DBot,DObject)
|
||||||
|
HAS_OBJECT_POINTERS
|
||||||
|
public:
|
||||||
|
DBot ();
|
||||||
|
|
||||||
|
void Clear ();
|
||||||
|
void Serialize (FArchive &arc);
|
||||||
|
|
||||||
|
angle_t savedyaw;
|
||||||
|
int savedpitch;
|
||||||
|
|
||||||
|
angle_t angle; // The wanted angle that the bot try to get every tic.
|
||||||
|
// (used to get a smooth view movement)
|
||||||
|
TObjPtr<AActor> dest; // Move Destination.
|
||||||
|
TObjPtr<AActor> prev; // Previous move destination.
|
||||||
|
|
||||||
|
|
||||||
|
TObjPtr<AActor> enemy; // The dead meat.
|
||||||
|
TObjPtr<AActor> missile; // A threatening missile that needs to be avoided.
|
||||||
|
TObjPtr<AActor> mate; // Friend (used for grouping in teamplay or coop).
|
||||||
|
TObjPtr<AActor> last_mate; // If bots mate disappeared (not if died) that mate is
|
||||||
|
// pointed to by this. Allows bot to roam to it if
|
||||||
|
// necessary.
|
||||||
|
|
||||||
|
//Skills
|
||||||
|
struct botskill_t skill;
|
||||||
|
|
||||||
|
//Tickers
|
||||||
|
int t_active; // Open door, lower lift stuff, door must open and
|
||||||
|
// lift must go down before bot does anything
|
||||||
|
// radical like try a stuckmove
|
||||||
|
int t_respawn;
|
||||||
|
int t_strafe;
|
||||||
|
int t_react;
|
||||||
|
int t_fight;
|
||||||
|
int t_roam;
|
||||||
|
int t_rocket;
|
||||||
|
|
||||||
|
//Misc booleans
|
||||||
|
bool first_shot; // Used for reaction skill.
|
||||||
|
bool sleft; // If false, strafe is right.
|
||||||
|
bool allround;
|
||||||
|
bool increase;
|
||||||
|
|
||||||
|
fixed_t oldx;
|
||||||
|
fixed_t oldy;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//Externs
|
//Externs
|
||||||
extern FCajunMaster bglobal;
|
extern FCajunMaster bglobal;
|
||||||
|
|
|
@ -140,8 +140,7 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
|
||||||
fixed_t dist;
|
fixed_t dist;
|
||||||
angle_t an;
|
angle_t an;
|
||||||
int m;
|
int m;
|
||||||
static bool inc[MAXPLAYERS];
|
AActor *enemy = actor->player->Bot->enemy;
|
||||||
AActor *enemy = actor->player->enemy;
|
|
||||||
|
|
||||||
if (!enemy || !(enemy->flags & MF_SHOOTABLE) || enemy->health <= 0)
|
if (!enemy || !(enemy->flags & MF_SHOOTABLE) || enemy->health <= 0)
|
||||||
return;
|
return;
|
||||||
|
@ -149,20 +148,20 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
|
||||||
if (actor->player->ReadyWeapon == NULL)
|
if (actor->player->ReadyWeapon == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (actor->player->damagecount > actor->player->skill.isp)
|
if (actor->player->damagecount > actor->player->Bot->skill.isp)
|
||||||
{
|
{
|
||||||
actor->player->first_shot = true;
|
actor->player->Bot->first_shot = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Reaction skill thing.
|
//Reaction skill thing.
|
||||||
if (actor->player->first_shot &&
|
if (actor->player->Bot->first_shot &&
|
||||||
!(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING))
|
!(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING))
|
||||||
{
|
{
|
||||||
actor->player->t_react = (100-actor->player->skill.reaction+1)/((pr_botdofire()%3)+3);
|
actor->player->Bot->t_react = (100-actor->player->Bot->skill.reaction+1)/((pr_botdofire()%3)+3);
|
||||||
}
|
}
|
||||||
actor->player->first_shot = false;
|
actor->player->Bot->first_shot = false;
|
||||||
if (actor->player->t_react)
|
if (actor->player->Bot->t_react)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//MAKEME: Decrease the rocket suicides even more.
|
//MAKEME: Decrease the rocket suicides even more.
|
||||||
|
@ -199,8 +198,8 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
|
||||||
else if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_BFG)
|
else if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_BFG)
|
||||||
{
|
{
|
||||||
//MAKEME: This should be smarter.
|
//MAKEME: This should be smarter.
|
||||||
if ((pr_botdofire()%200)<=actor->player->skill.reaction)
|
if ((pr_botdofire()%200)<=actor->player->Bot->skill.reaction)
|
||||||
if(Check_LOS(actor, actor->player->enemy, SHOOTFOV))
|
if(Check_LOS(actor, actor->player->Bot->enemy, SHOOTFOV))
|
||||||
no_fire = false;
|
no_fire = false;
|
||||||
}
|
}
|
||||||
else if (actor->player->ReadyWeapon->ProjectileType != NULL)
|
else if (actor->player->ReadyWeapon->ProjectileType != NULL)
|
||||||
|
@ -211,11 +210,11 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
|
||||||
an = FireRox (actor, enemy, cmd);
|
an = FireRox (actor, enemy, cmd);
|
||||||
if(an)
|
if(an)
|
||||||
{
|
{
|
||||||
actor->player->angle = an;
|
actor->player->Bot->angle = an;
|
||||||
//have to be somewhat precise. to avoid suicide.
|
//have to be somewhat precise. to avoid suicide.
|
||||||
if (abs (actor->player->angle - actor->angle) < 12*ANGLE_1)
|
if (abs (actor->player->Bot->angle - actor->angle) < 12*ANGLE_1)
|
||||||
{
|
{
|
||||||
actor->player->t_rocket = 9;
|
actor->player->Bot->t_rocket = 9;
|
||||||
no_fire = false;
|
no_fire = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,14 +224,14 @@ shootmissile:
|
||||||
dist = P_AproxDistance (actor->x - enemy->x, actor->y - enemy->y);
|
dist = P_AproxDistance (actor->x - enemy->x, actor->y - enemy->y);
|
||||||
m = dist / GetDefaultByType (actor->player->ReadyWeapon->ProjectileType)->Speed;
|
m = dist / GetDefaultByType (actor->player->ReadyWeapon->ProjectileType)->Speed;
|
||||||
SetBodyAt (enemy->x + enemy->velx*m*2, enemy->y + enemy->vely*m*2, enemy->z, 1);
|
SetBodyAt (enemy->x + enemy->velx*m*2, enemy->y + enemy->vely*m*2, enemy->z, 1);
|
||||||
actor->player->angle = R_PointToAngle2 (actor->x, actor->y, body1->x, body1->y);
|
actor->player->Bot->angle = R_PointToAngle2 (actor->x, actor->y, body1->x, body1->y);
|
||||||
if (Check_LOS (actor, enemy, SHOOTFOV))
|
if (Check_LOS (actor, enemy, SHOOTFOV))
|
||||||
no_fire = false;
|
no_fire = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Other weapons, mostly instant hit stuff.
|
//Other weapons, mostly instant hit stuff.
|
||||||
actor->player->angle = R_PointToAngle2 (actor->x, actor->y, enemy->x, enemy->y);
|
actor->player->Bot->angle = R_PointToAngle2 (actor->x, actor->y, enemy->x, enemy->y);
|
||||||
aiming_penalty = 0;
|
aiming_penalty = 0;
|
||||||
if (enemy->flags & MF_SHADOW)
|
if (enemy->flags & MF_SHADOW)
|
||||||
aiming_penalty += (pr_botdofire()%25)+10;
|
aiming_penalty += (pr_botdofire()%25)+10;
|
||||||
|
@ -240,7 +239,7 @@ shootmissile:
|
||||||
aiming_penalty += pr_botdofire()%40;//Dark
|
aiming_penalty += pr_botdofire()%40;//Dark
|
||||||
if (actor->player->damagecount)
|
if (actor->player->damagecount)
|
||||||
aiming_penalty += actor->player->damagecount; //Blood in face makes it hard to aim
|
aiming_penalty += actor->player->damagecount; //Blood in face makes it hard to aim
|
||||||
aiming_value = actor->player->skill.aiming - aiming_penalty;
|
aiming_value = actor->player->Bot->skill.aiming - aiming_penalty;
|
||||||
if (aiming_value <= 0)
|
if (aiming_value <= 0)
|
||||||
aiming_value = 1;
|
aiming_value = 1;
|
||||||
m = ((SHOOTFOV/2)-(aiming_value*SHOOTFOV/200)); //Higher skill is more accurate
|
m = ((SHOOTFOV/2)-(aiming_value*SHOOTFOV/200)); //Higher skill is more accurate
|
||||||
|
@ -249,15 +248,15 @@ shootmissile:
|
||||||
|
|
||||||
if (m)
|
if (m)
|
||||||
{
|
{
|
||||||
if (inc[actor->player - players])
|
if (actor->player->Bot->increase)
|
||||||
actor->player->angle += m;
|
actor->player->Bot->angle += m;
|
||||||
else
|
else
|
||||||
actor->player->angle -= m;
|
actor->player->Bot->angle -= m;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abs (actor->player->angle - actor->angle) < 4*ANGLE_1)
|
if (abs (actor->player->Bot->angle - actor->angle) < 4*ANGLE_1)
|
||||||
{
|
{
|
||||||
inc[actor->player - players] = !inc[actor->player - players];
|
actor->player->Bot->increase = !actor->player->Bot->increase;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Check_LOS (actor, enemy, (SHOOTFOV/2)))
|
if (Check_LOS (actor, enemy, (SHOOTFOV/2)))
|
||||||
|
@ -271,6 +270,19 @@ shootmissile:
|
||||||
//actor->angle = R_PointToAngle2(actor->x, actor->y, actor->player->enemy->x, actor->player->enemy->y);
|
//actor->angle = R_PointToAngle2(actor->x, actor->y, actor->player->enemy->x, actor->player->enemy->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FCajunMaster::IsLeader (player_t *player)
|
||||||
|
{
|
||||||
|
for (int count = 0; count < MAXPLAYERS; count++)
|
||||||
|
{
|
||||||
|
if (players[count].Bot != NULL
|
||||||
|
&& players[count].Bot->mate == player->mo)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//This function is called every
|
//This function is called every
|
||||||
//tick (for each bot) to set
|
//tick (for each bot) to set
|
||||||
|
@ -278,43 +290,25 @@ shootmissile:
|
||||||
AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
int count2;
|
|
||||||
fixed_t closest_dist, test;
|
fixed_t closest_dist, test;
|
||||||
AActor *target;
|
AActor *target;
|
||||||
AActor *observer;
|
AActor *observer;
|
||||||
bool p_leader[MAXPLAYERS];
|
|
||||||
|
|
||||||
//is mate alive?
|
//is mate alive?
|
||||||
if (bot->player->mate)
|
if (bot->player->Bot->mate)
|
||||||
{
|
{
|
||||||
if (bot->player->mate->health <= 0)
|
if (bot->player->Bot->mate->health <= 0)
|
||||||
bot->player->mate = NULL;
|
bot->player->Bot->mate = NULL;
|
||||||
else
|
else
|
||||||
bot->player->last_mate = bot->player->mate;
|
bot->player->Bot->last_mate = bot->player->Bot->mate;
|
||||||
}
|
}
|
||||||
if (bot->player->mate) //Still is..
|
if (bot->player->Bot->mate) //Still is..
|
||||||
return bot->player->mate;
|
return bot->player->Bot->mate;
|
||||||
|
|
||||||
//Check old_mates status.
|
//Check old_mates status.
|
||||||
if (bot->player->last_mate)
|
if (bot->player->Bot->last_mate)
|
||||||
if (bot->player->last_mate->health <= 0)
|
if (bot->player->Bot->last_mate->health <= 0)
|
||||||
bot->player->last_mate = NULL;
|
bot->player->Bot->last_mate = NULL;
|
||||||
|
|
||||||
for (count = 0; count < MAXPLAYERS; count++)
|
|
||||||
{
|
|
||||||
if (!playeringame[count])
|
|
||||||
continue;
|
|
||||||
p_leader[count] = false;
|
|
||||||
for (count2 = 0; count2 < MAXPLAYERS; count2++)
|
|
||||||
{
|
|
||||||
if (players[count].isbot
|
|
||||||
&& players[count2].mate == players[count].mo)
|
|
||||||
{
|
|
||||||
p_leader[count] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
target = NULL;
|
target = NULL;
|
||||||
closest_dist = FIXED_MAX;
|
closest_dist = FIXED_MAX;
|
||||||
|
@ -335,9 +329,8 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
||||||
&& client->mo->health > 0
|
&& client->mo->health > 0
|
||||||
&& client->mo != observer
|
&& client->mo != observer
|
||||||
&& ((bot->health/2) <= client->mo->health || !deathmatch)
|
&& ((bot->health/2) <= client->mo->health || !deathmatch)
|
||||||
&& !p_leader[count]) //taken?
|
&& !IsLeader(client)) //taken?
|
||||||
{
|
{
|
||||||
|
|
||||||
if (P_CheckSight (bot, client->mo, SF_IGNOREVISIBILITY))
|
if (P_CheckSight (bot, client->mo, SF_IGNOREVISIBILITY))
|
||||||
{
|
{
|
||||||
test = P_AproxDistance (client->mo->x - bot->x,
|
test = P_AproxDistance (client->mo->x - bot->x,
|
||||||
|
@ -386,11 +379,11 @@ AActor *FCajunMaster::Find_enemy (AActor *bot)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Note: It's hard to ambush a bot who is not alone
|
//Note: It's hard to ambush a bot who is not alone
|
||||||
if (bot->player->allround || bot->player->mate)
|
if (bot->player->Bot->allround || bot->player->Bot->mate)
|
||||||
vangle = ANGLE_MAX;
|
vangle = ANGLE_MAX;
|
||||||
else
|
else
|
||||||
vangle = ENEMY_SCAN_FOV;
|
vangle = ENEMY_SCAN_FOV;
|
||||||
bot->player->allround = false;
|
bot->player->Bot->allround = false;
|
||||||
|
|
||||||
target = NULL;
|
target = NULL;
|
||||||
closest_dist = FIXED_MAX;
|
closest_dist = FIXED_MAX;
|
||||||
|
|
|
@ -118,7 +118,7 @@ void FCajunMaster::Main (int buf)
|
||||||
BotThinkCycles.Clock();
|
BotThinkCycles.Clock();
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && players[i].mo && !freeze && players[i].isbot)
|
if (playeringame[i] && players[i].mo && !freeze && players[i].Bot != NULL)
|
||||||
Think (players[i].mo, &netcmds[i][buf]);
|
Think (players[i].mo, &netcmds[i][buf]);
|
||||||
}
|
}
|
||||||
BotThinkCycles.Unclock();
|
BotThinkCycles.Unclock();
|
||||||
|
@ -172,16 +172,9 @@ void FCajunMaster::Init ()
|
||||||
body1 = NULL;
|
body1 = NULL;
|
||||||
body2 = NULL;
|
body2 = NULL;
|
||||||
|
|
||||||
//Remove all bots upon each level start, they'll get spawned instead.
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
waitingforspawn[i] = false;
|
waitingforspawn[i] = false;
|
||||||
if (playeringame[i] && players[i].isbot)
|
|
||||||
{
|
|
||||||
CleanBotstuff (&players[i]);
|
|
||||||
players[i].isbot = false;
|
|
||||||
botingame[i] = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctf && teamplay == false)
|
if (ctf && teamplay == false)
|
||||||
|
@ -214,13 +207,12 @@ void FCajunMaster::End ()
|
||||||
getspawned.Clear();
|
getspawned.Clear();
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && players[i].isbot)
|
if (playeringame[i] && players[i].Bot != NULL)
|
||||||
{
|
{
|
||||||
if (deathmatch)
|
if (deathmatch)
|
||||||
{
|
{
|
||||||
getspawned.Push(players[i].userinfo.GetName());
|
getspawned.Push(players[i].userinfo.GetName());
|
||||||
}
|
}
|
||||||
CleanBotstuff (&players[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (deathmatch)
|
if (deathmatch)
|
||||||
|
@ -335,8 +327,10 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
|
||||||
}
|
}
|
||||||
Net_WriteString (concat);
|
Net_WriteString (concat);
|
||||||
}
|
}
|
||||||
|
Net_WriteByte(thebot->skill.aiming);
|
||||||
players[playernumber].skill = thebot->skill;
|
Net_WriteByte(thebot->skill.perfection);
|
||||||
|
Net_WriteByte(thebot->skill.reaction);
|
||||||
|
Net_WriteByte(thebot->skill.isp);
|
||||||
|
|
||||||
thebot->inuse = true;
|
thebot->inuse = true;
|
||||||
|
|
||||||
|
@ -346,10 +340,21 @@ bool FCajunMaster::SpawnBot (const char *name, int color)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCajunMaster::DoAddBot (int bnum, char *info)
|
void FCajunMaster::DoAddBot (BYTE **stream)
|
||||||
{
|
{
|
||||||
|
int bnum = ReadByte (stream);
|
||||||
|
char *info = ReadString (stream);
|
||||||
BYTE *infob = (BYTE *)info;
|
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);
|
D_ReadUserInfoStrings (bnum, &infob, false);
|
||||||
|
|
||||||
|
delete[] info;
|
||||||
|
|
||||||
if (!deathmatch && playerstarts[bnum].type == 0)
|
if (!deathmatch && playerstarts[bnum].type == 0)
|
||||||
{
|
{
|
||||||
Printf ("%s tried to join, but there was no player %d start\n",
|
Printf ("%s tried to join, but there was no player %d start\n",
|
||||||
|
@ -363,11 +368,12 @@ void FCajunMaster::DoAddBot (int bnum, char *info)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost).
|
multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost).
|
||||||
players[bnum].isbot = true;
|
players[bnum].Bot = new DBot;
|
||||||
|
GC::WriteBarrier (players[bnum].Bot);
|
||||||
|
players[bnum].Bot->skill = skill;
|
||||||
playeringame[bnum] = true;
|
playeringame[bnum] = true;
|
||||||
players[bnum].mo = NULL;
|
players[bnum].mo = NULL;
|
||||||
players[bnum].playerstate = PST_ENTER;
|
players[bnum].playerstate = PST_ENTER;
|
||||||
botingame[bnum] = true;
|
|
||||||
|
|
||||||
if (teamplay)
|
if (teamplay)
|
||||||
Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName());
|
Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName());
|
||||||
|
@ -389,13 +395,13 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; ++i)
|
for (i = 0; i < MAXPLAYERS; ++i)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && botingame[i])
|
if (playeringame[i] && players[i].Bot != NULL)
|
||||||
{
|
{
|
||||||
// If a player is looking through this bot's eyes, make him
|
// If a player is looking through this bot's eyes, make him
|
||||||
// look through his own eyes instead.
|
// look through his own eyes instead.
|
||||||
for (j = 0; j < MAXPLAYERS; ++j)
|
for (j = 0; j < MAXPLAYERS; ++j)
|
||||||
{
|
{
|
||||||
if (i != j && playeringame[j] && !botingame[j])
|
if (i != j && playeringame[j] && players[j].Bot == NULL)
|
||||||
{
|
{
|
||||||
if (players[j].camera == players[i].mo)
|
if (players[j].camera == players[i].mo)
|
||||||
{
|
{
|
||||||
|
@ -421,26 +427,16 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
|
||||||
botnum = 0;
|
botnum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clean the bot part of the player_t
|
void FCajunMaster::DestroyAllBots ()
|
||||||
//Used when bots are respawned or at level starts.
|
|
||||||
void FCajunMaster::CleanBotstuff (player_t *p)
|
|
||||||
{
|
{
|
||||||
p->angle = ANG45;
|
for (int i = 0; i < MAXPLAYERS; ++i)
|
||||||
p->dest = NULL;
|
{
|
||||||
p->enemy = NULL; //The dead meat.
|
if (players[i].Bot != NULL)
|
||||||
p->missile = NULL; //A threatening missile that needs to be avoided.
|
{
|
||||||
p->mate = NULL; //Friend (used for grouping in templay or coop.
|
players[i].Bot->Destroy ();
|
||||||
p->last_mate = NULL; //If bot's mate dissapeared (not if died) that mate is pointed to by this. Allows bot to roam to it if necessary.
|
players[i].Bot = NULL;
|
||||||
//Tickers
|
}
|
||||||
p->t_active = 0; //Open door, lower lift stuff, door must open and lift must go down before bot does anything radical like try a stuckmove
|
}
|
||||||
p->t_respawn = 0;
|
|
||||||
p->t_strafe = 0;
|
|
||||||
p->t_react = 0;
|
|
||||||
//Misc bools
|
|
||||||
p->isbot = true; //Important.
|
|
||||||
p->first_shot = true; //Used for reaction skill.
|
|
||||||
p->sleft = false; //If false, strafe is right.
|
|
||||||
p->allround = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,19 +33,19 @@ void FCajunMaster::Roam (AActor *actor, ticcmd_t *cmd)
|
||||||
{
|
{
|
||||||
int delta;
|
int delta;
|
||||||
|
|
||||||
if (Reachable(actor, actor->player->dest))
|
if (Reachable(actor, actor->player->Bot->dest))
|
||||||
{ // Straight towards it.
|
{ // Straight towards it.
|
||||||
actor->player->angle = R_PointToAngle2(actor->x, actor->y, actor->player->dest->x, actor->player->dest->y);
|
actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, actor->player->Bot->dest->x, actor->player->Bot->dest->y);
|
||||||
}
|
}
|
||||||
else if (actor->movedir < 8) // turn towards movement direction if not there yet
|
else if (actor->movedir < 8) // turn towards movement direction if not there yet
|
||||||
{
|
{
|
||||||
actor->player->angle &= (angle_t)(7<<29);
|
actor->player->Bot->angle &= (angle_t)(7<<29);
|
||||||
delta = actor->player->angle - (actor->movedir << 29);
|
delta = actor->player->Bot->angle - (actor->movedir << 29);
|
||||||
|
|
||||||
if (delta > 0)
|
if (delta > 0)
|
||||||
actor->player->angle -= ANG45;
|
actor->player->Bot->angle -= ANG45;
|
||||||
else if (delta < 0)
|
else if (delta < 0)
|
||||||
actor->player->angle += ANG45;
|
actor->player->Bot->angle += ANG45;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chase towards destination.
|
// chase towards destination.
|
||||||
|
@ -134,7 +134,7 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
||||||
|
|
||||||
dirtype_t turnaround;
|
dirtype_t turnaround;
|
||||||
|
|
||||||
if (!actor->player->dest)
|
if (!actor->player->Bot->dest)
|
||||||
{
|
{
|
||||||
#ifndef BOT_RELEASE_COMPILE
|
#ifndef BOT_RELEASE_COMPILE
|
||||||
Printf ("Bot tried move without destination\n");
|
Printf ("Bot tried move without destination\n");
|
||||||
|
@ -145,8 +145,8 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
||||||
olddir = (dirtype_t)actor->movedir;
|
olddir = (dirtype_t)actor->movedir;
|
||||||
turnaround = opposite[olddir];
|
turnaround = opposite[olddir];
|
||||||
|
|
||||||
deltax = actor->player->dest->x - actor->x;
|
deltax = actor->player->Bot->dest->x - actor->x;
|
||||||
deltay = actor->player->dest->y - actor->y;
|
deltay = actor->player->Bot->dest->y - actor->y;
|
||||||
|
|
||||||
if (deltax > 10*FRACUNIT)
|
if (deltax > 10*FRACUNIT)
|
||||||
d[1] = DI_EAST;
|
d[1] = DI_EAST;
|
||||||
|
@ -315,23 +315,23 @@ void FCajunMaster::TurnToAng (AActor *actor)
|
||||||
{
|
{
|
||||||
if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
|
if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
|
||||||
{
|
{
|
||||||
if (actor->player->t_roam && !actor->player->missile)
|
if (actor->player->Bot->t_roam && !actor->player->Bot->missile)
|
||||||
{ //Keep angle that where when shot where decided.
|
{ //Keep angle that where when shot where decided.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(actor->player->enemy)
|
if(actor->player->Bot->enemy)
|
||||||
if(!actor->player->dest) //happens when running after item in combat situations, or normal, prevents weak turns
|
if(!actor->player->Bot->dest) //happens when running after item in combat situations, or normal, prevents weak turns
|
||||||
if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON))
|
if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON))
|
||||||
if(Check_LOS(actor, actor->player->enemy, SHOOTFOV+5*ANGLE_1))
|
if(Check_LOS(actor, actor->player->Bot->enemy, SHOOTFOV+5*ANGLE_1))
|
||||||
maxturn = 3;
|
maxturn = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
int distance = actor->player->angle - actor->angle;
|
int distance = actor->player->Bot->angle - actor->angle;
|
||||||
|
|
||||||
if (abs (distance) < OKAYRANGE && !actor->player->enemy)
|
if (abs (distance) < OKAYRANGE && !actor->player->Bot->enemy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
distance /= TURNSENS;
|
distance /= TURNSENS;
|
||||||
|
|
172
src/b_think.cpp
172
src/b_think.cpp
|
@ -28,13 +28,13 @@ void FCajunMaster::Think (AActor *actor, ticcmd_t *cmd)
|
||||||
{
|
{
|
||||||
memset (cmd, 0, sizeof(*cmd));
|
memset (cmd, 0, sizeof(*cmd));
|
||||||
|
|
||||||
if (actor->player->enemy && actor->player->enemy->health <= 0)
|
if (actor->player->Bot->enemy && actor->player->Bot->enemy->health <= 0)
|
||||||
actor->player->enemy = NULL;
|
actor->player->Bot->enemy = NULL;
|
||||||
|
|
||||||
if (actor->health > 0) //Still alive
|
if (actor->health > 0) //Still alive
|
||||||
{
|
{
|
||||||
if (teamplay || !deathmatch)
|
if (teamplay || !deathmatch)
|
||||||
actor->player->mate = Choose_Mate (actor);
|
actor->player->Bot->mate = Choose_Mate (actor);
|
||||||
|
|
||||||
angle_t oldyaw = actor->angle;
|
angle_t oldyaw = actor->angle;
|
||||||
int oldpitch = actor->pitch;
|
int oldpitch = actor->pitch;
|
||||||
|
@ -52,17 +52,17 @@ void FCajunMaster::Think (AActor *actor, ticcmd_t *cmd)
|
||||||
actor->pitch = oldpitch - (cmd->ucmd.pitch << 16) * ticdup;
|
actor->pitch = oldpitch - (cmd->ucmd.pitch << 16) * ticdup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor->player->t_active) actor->player->t_active--;
|
if (actor->player->Bot->t_active) actor->player->Bot->t_active--;
|
||||||
if (actor->player->t_strafe) actor->player->t_strafe--;
|
if (actor->player->Bot->t_strafe) actor->player->Bot->t_strafe--;
|
||||||
if (actor->player->t_react) actor->player->t_react--;
|
if (actor->player->Bot->t_react) actor->player->Bot->t_react--;
|
||||||
if (actor->player->t_fight) actor->player->t_fight--;
|
if (actor->player->Bot->t_fight) actor->player->Bot->t_fight--;
|
||||||
if (actor->player->t_rocket) actor->player->t_rocket--;
|
if (actor->player->Bot->t_rocket) actor->player->Bot->t_rocket--;
|
||||||
if (actor->player->t_roam) actor->player->t_roam--;
|
if (actor->player->Bot->t_roam) actor->player->Bot->t_roam--;
|
||||||
|
|
||||||
//Respawn ticker
|
//Respawn ticker
|
||||||
if (actor->player->t_respawn)
|
if (actor->player->Bot->t_respawn)
|
||||||
{
|
{
|
||||||
actor->player->t_respawn--;
|
actor->player->Bot->t_respawn--;
|
||||||
}
|
}
|
||||||
else if (actor->health <= 0)
|
else if (actor->health <= 0)
|
||||||
{ // Time to respawn
|
{ // Time to respawn
|
||||||
|
@ -80,17 +80,17 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
b = actor->player;
|
b = actor->player;
|
||||||
if (!b->isbot)
|
if (b->Bot == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
stuck = false;
|
stuck = false;
|
||||||
dist = b->dest ? P_AproxDistance(actor->x-b->dest->x, actor->y-b->dest->y) : 0;
|
dist = b->Bot->dest ? P_AproxDistance(actor->x-b->Bot->dest->x, actor->y-b->Bot->dest->y) : 0;
|
||||||
|
|
||||||
if (b->missile &&
|
if (b->Bot->missile &&
|
||||||
((!b->missile->velx || !b->missile->vely) || !Check_LOS(actor, b->missile, SHOOTFOV*3/2)))
|
((!b->Bot->missile->velx || !b->Bot->missile->vely) || !Check_LOS(actor, b->Bot->missile, SHOOTFOV*3/2)))
|
||||||
{
|
{
|
||||||
b->sleft = !b->sleft;
|
b->Bot->sleft = !b->Bot->sleft;
|
||||||
b->missile = NULL; //Probably ended its travel.
|
b->Bot->missile = NULL; //Probably ended its travel.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor->pitch > 0)
|
if (actor->pitch > 0)
|
||||||
|
@ -99,35 +99,35 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
||||||
actor->pitch += 80;
|
actor->pitch += 80;
|
||||||
|
|
||||||
//HOW TO MOVE:
|
//HOW TO MOVE:
|
||||||
if (b->missile && (P_AproxDistance(actor->x-b->missile->x, actor->y-b->missile->y)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
|
if (b->Bot->missile && (P_AproxDistance(actor->x-b->Bot->missile->x, actor->y-b->Bot->missile->y)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
|
||||||
{
|
{
|
||||||
Pitch (actor, b->missile);
|
Pitch (actor, b->Bot->missile);
|
||||||
actor->player->angle = R_PointToAngle2(actor->x, actor->y, b->missile->x, b->missile->y);
|
actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->missile->x, b->Bot->missile->y);
|
||||||
cmd->ucmd.sidemove = b->sleft ? -SIDERUN : SIDERUN;
|
cmd->ucmd.sidemove = b->Bot->sleft ? -SIDERUN : SIDERUN;
|
||||||
cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best.
|
cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best.
|
||||||
|
|
||||||
if ((P_AproxDistance(actor->x-b->oldx, actor->y-b->oldy)<50000)
|
if ((P_AproxDistance(actor->x-b->Bot->oldx, actor->y-b->Bot->oldy)<50000)
|
||||||
&& b->t_strafe<=0)
|
&& b->Bot->t_strafe<=0)
|
||||||
{
|
{
|
||||||
b->t_strafe = 5;
|
b->Bot->t_strafe = 5;
|
||||||
b->sleft = !b->sleft;
|
b->Bot->sleft = !b->Bot->sleft;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If able to see enemy while avoiding missile, still fire at enemy.
|
//If able to see enemy while avoiding missile, still fire at enemy.
|
||||||
if (b->enemy && Check_LOS (actor, b->enemy, SHOOTFOV))
|
if (b->Bot->enemy && Check_LOS (actor, b->Bot->enemy, SHOOTFOV))
|
||||||
Dofire (actor, cmd); //Order bot to fire current weapon
|
Dofire (actor, cmd); //Order bot to fire current weapon
|
||||||
}
|
}
|
||||||
else if (b->enemy && P_CheckSight (actor, b->enemy, 0)) //Fight!
|
else if (b->Bot->enemy && P_CheckSight (actor, b->Bot->enemy, 0)) //Fight!
|
||||||
{
|
{
|
||||||
Pitch (actor, b->enemy);
|
Pitch (actor, b->Bot->enemy);
|
||||||
|
|
||||||
//Check if it's more important to get an item than fight.
|
//Check if it's more important to get an item than fight.
|
||||||
if (b->dest && (b->dest->flags&MF_SPECIAL)) //Must be an item, that is close enough.
|
if (b->Bot->dest && (b->Bot->dest->flags&MF_SPECIAL)) //Must be an item, that is close enough.
|
||||||
{
|
{
|
||||||
#define is(x) b->dest->IsKindOf (PClass::FindClass (#x))
|
#define is(x) b->Bot->dest->IsKindOf (PClass::FindClass (#x))
|
||||||
if (
|
if (
|
||||||
(
|
(
|
||||||
(actor->health < b->skill.isp &&
|
(actor->health < b->Bot->skill.isp &&
|
||||||
(is (Medikit) ||
|
(is (Medikit) ||
|
||||||
is (Stimpack) ||
|
is (Stimpack) ||
|
||||||
is (Soulsphere) ||
|
is (Soulsphere) ||
|
||||||
|
@ -143,75 +143,75 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
||||||
(b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)
|
(b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)
|
||||||
)
|
)
|
||||||
&& (dist < GETINCOMBAT || (b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
&& (dist < GETINCOMBAT || (b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||||
&& Reachable (actor, b->dest))
|
&& Reachable (actor, b->Bot->dest))
|
||||||
#undef is
|
#undef is
|
||||||
{
|
{
|
||||||
goto roam; //Pick it up, no matter the situation. All bonuses are nice close up.
|
goto roam; //Pick it up, no matter the situation. All bonuses are nice close up.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b->dest = NULL; //To let bot turn right
|
b->Bot->dest = NULL; //To let bot turn right
|
||||||
|
|
||||||
if (b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
if (b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||||
actor->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting.
|
actor->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting.
|
||||||
|
|
||||||
if (!(b->enemy->flags3 & MF3_ISMONSTER))
|
if (!(b->Bot->enemy->flags3 & MF3_ISMONSTER))
|
||||||
b->t_fight = AFTERTICS;
|
b->Bot->t_fight = AFTERTICS;
|
||||||
|
|
||||||
if (b->t_strafe <= 0 &&
|
if (b->Bot->t_strafe <= 0 &&
|
||||||
(P_AproxDistance(actor->x-b->oldx, actor->y-b->oldy)<50000
|
(P_AproxDistance(actor->x-b->Bot->oldx, actor->y-b->Bot->oldy)<50000
|
||||||
|| ((pr_botmove()%30)==10))
|
|| ((pr_botmove()%30)==10))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
stuck = true;
|
stuck = true;
|
||||||
b->t_strafe = 5;
|
b->Bot->t_strafe = 5;
|
||||||
b->sleft = !b->sleft;
|
b->Bot->sleft = !b->Bot->sleft;
|
||||||
}
|
}
|
||||||
|
|
||||||
b->angle = R_PointToAngle2(actor->x, actor->y, b->enemy->x, b->enemy->y);
|
b->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->enemy->x, b->Bot->enemy->y);
|
||||||
|
|
||||||
if (b->ReadyWeapon == NULL ||
|
if (b->ReadyWeapon == NULL ||
|
||||||
P_AproxDistance(actor->x-b->enemy->x, actor->y-b->enemy->y) >
|
P_AproxDistance(actor->x-b->Bot->enemy->x, actor->y-b->Bot->enemy->y) >
|
||||||
b->ReadyWeapon->MoveCombatDist)
|
b->ReadyWeapon->MoveCombatDist)
|
||||||
{
|
{
|
||||||
// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
|
// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
|
||||||
cmd->ucmd.forwardmove = (b->enemy->flags3 & MF3_ISMONSTER) ? FORWARDWALK : FORWARDRUN;
|
cmd->ucmd.forwardmove = (b->Bot->enemy->flags3 & MF3_ISMONSTER) ? FORWARDWALK : FORWARDRUN;
|
||||||
}
|
}
|
||||||
else if (!stuck) //Too close, so move away.
|
else if (!stuck) //Too close, so move away.
|
||||||
{
|
{
|
||||||
// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
|
// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
|
||||||
cmd->ucmd.forwardmove = (b->enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN;
|
cmd->ucmd.forwardmove = (b->Bot->enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Strafing.
|
//Strafing.
|
||||||
if (b->enemy->flags3 & MF3_ISMONSTER) //It's just a monster so take it down cool.
|
if (b->Bot->enemy->flags3 & MF3_ISMONSTER) //It's just a monster so take it down cool.
|
||||||
{
|
{
|
||||||
cmd->ucmd.sidemove = b->sleft ? -SIDEWALK : SIDEWALK;
|
cmd->ucmd.sidemove = b->Bot->sleft ? -SIDEWALK : SIDEWALK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cmd->ucmd.sidemove = b->sleft ? -SIDERUN : SIDERUN;
|
cmd->ucmd.sidemove = b->Bot->sleft ? -SIDERUN : SIDERUN;
|
||||||
}
|
}
|
||||||
Dofire (actor, cmd); //Order bot to fire current weapon
|
Dofire (actor, cmd); //Order bot to fire current weapon
|
||||||
}
|
}
|
||||||
else if (b->mate && !b->enemy && (!b->dest || b->dest==b->mate)) //Follow mate move.
|
else if (b->Bot->mate && !b->Bot->enemy && (!b->Bot->dest || b->Bot->dest==b->Bot->mate)) //Follow mate move.
|
||||||
{
|
{
|
||||||
fixed_t matedist;
|
fixed_t matedist;
|
||||||
|
|
||||||
Pitch (actor, b->mate);
|
Pitch (actor, b->Bot->mate);
|
||||||
|
|
||||||
if (!Reachable (actor, b->mate))
|
if (!Reachable (actor, b->Bot->mate))
|
||||||
{
|
{
|
||||||
if (b->mate == b->dest && pr_botmove.Random() < 32)
|
if (b->Bot->mate == b->Bot->dest && pr_botmove.Random() < 32)
|
||||||
{ // [RH] If the mate is the dest, pick a new dest sometimes
|
{ // [RH] If the mate is the dest, pick a new dest sometimes
|
||||||
b->dest = NULL;
|
b->Bot->dest = NULL;
|
||||||
}
|
}
|
||||||
goto roam;
|
goto roam;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor->player->angle = R_PointToAngle2(actor->x, actor->y, b->mate->x, b->mate->y);
|
actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->mate->x, b->Bot->mate->y);
|
||||||
|
|
||||||
matedist = P_AproxDistance(actor->x - b->mate->x, actor->y - b->mate->y);
|
matedist = P_AproxDistance(actor->x - b->Bot->mate->x, actor->y - b->Bot->mate->y);
|
||||||
if (matedist > (FRIEND_DIST*2))
|
if (matedist > (FRIEND_DIST*2))
|
||||||
cmd->ucmd.forwardmove = FORWARDRUN;
|
cmd->ucmd.forwardmove = FORWARDRUN;
|
||||||
else if (matedist > FRIEND_DIST)
|
else if (matedist > FRIEND_DIST)
|
||||||
|
@ -221,33 +221,33 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
||||||
}
|
}
|
||||||
else //Roam after something.
|
else //Roam after something.
|
||||||
{
|
{
|
||||||
b->first_shot = true;
|
b->Bot->first_shot = true;
|
||||||
|
|
||||||
/////
|
/////
|
||||||
roam:
|
roam:
|
||||||
/////
|
/////
|
||||||
if (b->enemy && Check_LOS (actor, b->enemy, SHOOTFOV*3/2)) //If able to see enemy while avoiding missile , still fire at it.
|
if (b->Bot->enemy && Check_LOS (actor, b->Bot->enemy, SHOOTFOV*3/2)) //If able to see enemy while avoiding missile , still fire at it.
|
||||||
Dofire (actor, cmd); //Order bot to fire current weapon
|
Dofire (actor, cmd); //Order bot to fire current weapon
|
||||||
|
|
||||||
if (b->dest && !(b->dest->flags&MF_SPECIAL) && b->dest->health < 0)
|
if (b->Bot->dest && !(b->Bot->dest->flags&MF_SPECIAL) && b->Bot->dest->health < 0)
|
||||||
{ //Roaming after something dead.
|
{ //Roaming after something dead.
|
||||||
b->dest = NULL;
|
b->Bot->dest = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b->dest == NULL)
|
if (b->Bot->dest == NULL)
|
||||||
{
|
{
|
||||||
if (b->t_fight && b->enemy) //Enemy/bot has jumped around corner. So what to do?
|
if (b->Bot->t_fight && b->Bot->enemy) //Enemy/bot has jumped around corner. So what to do?
|
||||||
{
|
{
|
||||||
if (b->enemy->player)
|
if (b->Bot->enemy->player)
|
||||||
{
|
{
|
||||||
if (((b->enemy->player->ReadyWeapon != NULL && b->enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) ||
|
if (((b->Bot->enemy->player->ReadyWeapon != NULL && b->Bot->enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) ||
|
||||||
(pr_botmove()%100)>b->skill.isp) && b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
(pr_botmove()%100)>b->Bot->skill.isp) && b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||||
b->dest = b->enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy.
|
b->Bot->dest = b->Bot->enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy.
|
||||||
else //hide while b->t_fight, but keep view at enemy.
|
else //hide while b->t_fight, but keep view at enemy.
|
||||||
b->angle = R_PointToAngle2(actor->x, actor->y, b->enemy->x, b->enemy->y);
|
b->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->enemy->x, b->Bot->enemy->y);
|
||||||
} //Just a monster, so kill it.
|
} //Just a monster, so kill it.
|
||||||
else
|
else
|
||||||
b->dest = b->enemy;
|
b->Bot->dest = b->Bot->enemy;
|
||||||
|
|
||||||
//VerifFavoritWeapon(actor->player); //Dont know why here.., but it must be here, i know the reason, but not why at this spot, uh.
|
//VerifFavoritWeapon(actor->player); //Dont know why here.., but it must be here, i know the reason, but not why at this spot, uh.
|
||||||
}
|
}
|
||||||
|
@ -272,42 +272,42 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
||||||
item = it.Next();
|
item = it.Next();
|
||||||
}
|
}
|
||||||
firstthing = item;
|
firstthing = item;
|
||||||
b->dest = item;
|
b->Bot->dest = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (b->mate && (r < 179 || P_CheckSight(actor, b->mate)))
|
else if (b->Bot->mate && (r < 179 || P_CheckSight(actor, b->Bot->mate)))
|
||||||
{
|
{
|
||||||
b->dest = b->mate;
|
b->Bot->dest = b->Bot->mate;
|
||||||
}
|
}
|
||||||
else if ((playeringame[(r&(MAXPLAYERS-1))]) && players[(r&(MAXPLAYERS-1))].mo->health > 0)
|
else if ((playeringame[(r&(MAXPLAYERS-1))]) && players[(r&(MAXPLAYERS-1))].mo->health > 0)
|
||||||
{
|
{
|
||||||
b->dest = players[(r&(MAXPLAYERS-1))].mo;
|
b->Bot->dest = players[(r&(MAXPLAYERS-1))].mo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b->dest)
|
if (b->Bot->dest)
|
||||||
{
|
{
|
||||||
b->t_roam = MAXROAM;
|
b->Bot->t_roam = MAXROAM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (b->dest)
|
if (b->Bot->dest)
|
||||||
{ //Bot has a target so roam after it.
|
{ //Bot has a target so roam after it.
|
||||||
Roam (actor, cmd);
|
Roam (actor, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
} //End of movement main part.
|
} //End of movement main part.
|
||||||
|
|
||||||
if (!b->t_roam && b->dest)
|
if (!b->Bot->t_roam && b->Bot->dest)
|
||||||
{
|
{
|
||||||
b->prev = b->dest;
|
b->Bot->prev = b->Bot->dest;
|
||||||
b->dest = NULL;
|
b->Bot->dest = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b->t_fight<(AFTERTICS/2))
|
if (b->Bot->t_fight<(AFTERTICS/2))
|
||||||
actor->flags |= MF_DROPOFF;
|
actor->flags |= MF_DROPOFF;
|
||||||
|
|
||||||
b->oldx = actor->x;
|
b->Bot->oldx = actor->x;
|
||||||
b->oldy = actor->y;
|
b->Bot->oldy = actor->y;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BOT_WhatToGet
|
//BOT_WhatToGet
|
||||||
|
@ -324,7 +324,7 @@ void FCajunMaster::WhatToGet (AActor *actor, AActor *item)
|
||||||
|
|
||||||
#define typeis(x) item->IsKindOf (PClass::FindClass (#x))
|
#define typeis(x) item->IsKindOf (PClass::FindClass (#x))
|
||||||
if ((item->renderflags & RF_INVISIBLE) //Under respawn and away.
|
if ((item->renderflags & RF_INVISIBLE) //Under respawn and away.
|
||||||
|| item == b->prev)
|
|| item == b->Bot->prev)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -366,21 +366,21 @@ void FCajunMaster::WhatToGet (AActor *actor, AActor *item)
|
||||||
else if (item->IsKindOf (RUNTIME_CLASS(AHealth)) && actor->health >= deh.MaxHealth /*MAXHEALTH*/)
|
else if (item->IsKindOf (RUNTIME_CLASS(AHealth)) && actor->health >= deh.MaxHealth /*MAXHEALTH*/)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((b->dest == NULL ||
|
if ((b->Bot->dest == NULL ||
|
||||||
!(b->dest->flags & MF_SPECIAL)/* ||
|
!(b->Bot->dest->flags & MF_SPECIAL)/* ||
|
||||||
!Reachable (actor, b->dest)*/)/* &&
|
!Reachable (actor, b->dest)*/)/* &&
|
||||||
Reachable (actor, item)*/) // Calling Reachable slows this down tremendously
|
Reachable (actor, item)*/) // Calling Reachable slows this down tremendously
|
||||||
{
|
{
|
||||||
b->prev = b->dest;
|
b->Bot->prev = b->Bot->dest;
|
||||||
b->dest = item;
|
b->Bot->dest = item;
|
||||||
b->t_roam = MAXROAM;
|
b->Bot->t_roam = MAXROAM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCajunMaster::Set_enemy (AActor *actor)
|
void FCajunMaster::Set_enemy (AActor *actor)
|
||||||
{
|
{
|
||||||
AActor *oldenemy;
|
AActor *oldenemy;
|
||||||
AActor **enemy = &actor->player->enemy;
|
AActor **enemy = &actor->player->Bot->enemy;
|
||||||
|
|
||||||
if (*enemy
|
if (*enemy
|
||||||
&& (*enemy)->health > 0
|
&& (*enemy)->health > 0
|
||||||
|
@ -397,7 +397,7 @@ void FCajunMaster::Set_enemy (AActor *actor)
|
||||||
// and we already have an existing enemy.
|
// and we already have an existing enemy.
|
||||||
if (deathmatch || !*enemy)
|
if (deathmatch || !*enemy)
|
||||||
{
|
{
|
||||||
actor->player->allround = !!*enemy;
|
actor->player->Bot->allround = !!*enemy;
|
||||||
*enemy = NULL;
|
*enemy = NULL;
|
||||||
*enemy = Find_enemy(actor);
|
*enemy = Find_enemy(actor);
|
||||||
if (!*enemy)
|
if (!*enemy)
|
||||||
|
|
|
@ -124,6 +124,15 @@ CCMD (god)
|
||||||
Net_WriteByte (CHT_GOD);
|
Net_WriteByte (CHT_GOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCMD(god2)
|
||||||
|
{
|
||||||
|
if (CheckCheatmode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Net_WriteByte(DEM_GENERICCHEAT);
|
||||||
|
Net_WriteByte(CHT_GOD2);
|
||||||
|
}
|
||||||
|
|
||||||
CCMD (iddqd)
|
CCMD (iddqd)
|
||||||
{
|
{
|
||||||
if (CheckCheatmode ())
|
if (CheckCheatmode ())
|
||||||
|
@ -142,6 +151,15 @@ CCMD (buddha)
|
||||||
Net_WriteByte(CHT_BUDDHA);
|
Net_WriteByte(CHT_BUDDHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCMD(buddha2)
|
||||||
|
{
|
||||||
|
if (CheckCheatmode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Net_WriteByte(DEM_GENERICCHEAT);
|
||||||
|
Net_WriteByte(CHT_BUDDHA2);
|
||||||
|
}
|
||||||
|
|
||||||
CCMD (notarget)
|
CCMD (notarget)
|
||||||
{
|
{
|
||||||
if (CheckCheatmode ())
|
if (CheckCheatmode ())
|
||||||
|
|
|
@ -500,9 +500,10 @@ UCVarValue FBaseCVar::FromString (const char *value, ECVarType type)
|
||||||
goodv = false;
|
goodv = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (value[i] < '0' && value[i] > '9' &&
|
if (value[i] < '0' ||
|
||||||
value[i] < 'A' && value[i] > 'F' &&
|
(value[i] > '9' && value[i] < 'A') ||
|
||||||
value[i] < 'a' && value[i] > 'f')
|
(value[i] > 'F' && value[i] < 'a') ||
|
||||||
|
value[i] > 'f')
|
||||||
{
|
{
|
||||||
goodv = false;
|
goodv = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,7 @@ static FCompatOption Options[] =
|
||||||
{ "maskedmidtex", COMPATF_MASKEDMIDTEX, SLOT_COMPAT },
|
{ "maskedmidtex", COMPATF_MASKEDMIDTEX, SLOT_COMPAT },
|
||||||
{ "badangles", COMPATF2_BADANGLES, SLOT_COMPAT2 },
|
{ "badangles", COMPATF2_BADANGLES, SLOT_COMPAT2 },
|
||||||
{ "floormove", COMPATF2_FLOORMOVE, SLOT_COMPAT2 },
|
{ "floormove", COMPATF2_FLOORMOVE, SLOT_COMPAT2 },
|
||||||
|
{ "soundcutoff", COMPATF2_SOUNDCUTOFF, SLOT_COMPAT2 },
|
||||||
|
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
|
@ -466,7 +466,7 @@ CUSTOM_CVAR (Int, dmflags2, 0, CVAR_SERVERINFO)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Come out of chasecam mode if we're not allowed to use chasecam.
|
// Come out of chasecam mode if we're not allowed to use chasecam.
|
||||||
if (!(dmflags2 & DF2_CHASECAM) && !G_SkillProperty (SKILLP_DisableCheats) && !sv_cheats)
|
if (!(dmflags2 & DF2_CHASECAM) && CheckCheatmode(false))
|
||||||
{
|
{
|
||||||
// Take us out of chasecam mode only.
|
// Take us out of chasecam mode only.
|
||||||
if (p->cheats & CF_CHASECAM)
|
if (p->cheats & CF_CHASECAM)
|
||||||
|
@ -620,6 +620,7 @@ CVAR (Flag, compat_polyobj, compatflags, COMPATF_POLYOBJ);
|
||||||
CVAR (Flag, compat_maskedmidtex, compatflags, COMPATF_MASKEDMIDTEX);
|
CVAR (Flag, compat_maskedmidtex, compatflags, COMPATF_MASKEDMIDTEX);
|
||||||
CVAR (Flag, compat_badangles, compatflags2, COMPATF2_BADANGLES);
|
CVAR (Flag, compat_badangles, compatflags2, COMPATF2_BADANGLES);
|
||||||
CVAR (Flag, compat_floormove, compatflags2, COMPATF2_FLOORMOVE);
|
CVAR (Flag, compat_floormove, compatflags2, COMPATF2_FLOORMOVE);
|
||||||
|
CVAR (Flag, compat_soundcutoff, compatflags2, COMPATF2_SOUNDCUTOFF);
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -978,19 +979,19 @@ void D_DoomLoop ()
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && players[i].isbot && players[i].mo)
|
if (playeringame[i] && players[i].Bot != NULL && players[i].mo)
|
||||||
{
|
{
|
||||||
players[i].savedyaw = players[i].mo->angle;
|
players[i].Bot->savedyaw = players[i].mo->angle;
|
||||||
players[i].savedpitch = players[i].mo->pitch;
|
players[i].Bot->savedpitch = players[i].mo->pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bglobal.Main (maketic%BACKUPTICS);
|
bglobal.Main (maketic%BACKUPTICS);
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && players[i].isbot && players[i].mo)
|
if (playeringame[i] && players[i].Bot != NULL && players[i].mo)
|
||||||
{
|
{
|
||||||
players[i].mo->angle = players[i].savedyaw;
|
players[i].mo->angle = players[i].Bot->savedyaw;
|
||||||
players[i].mo->pitch = players[i].savedpitch;
|
players[i].mo->pitch = players[i].Bot->savedpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (advancedemo)
|
if (advancedemo)
|
||||||
|
|
|
@ -697,7 +697,7 @@ void PlayerIsGone (int netnode, int netconsole)
|
||||||
// Pick a new network arbitrator
|
// Pick a new network arbitrator
|
||||||
for (int i = 0; i < MAXPLAYERS; i++)
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (i != netconsole && playeringame[i] && !players[i].isbot)
|
if (i != netconsole && playeringame[i] && players[i].Bot == NULL)
|
||||||
{
|
{
|
||||||
Net_Arbitrator = i;
|
Net_Arbitrator = i;
|
||||||
players[i].settings_controller = true;
|
players[i].settings_controller = true;
|
||||||
|
@ -902,7 +902,7 @@ void GetPackets (void)
|
||||||
|
|
||||||
for (i = 0; i < numplayers; ++i)
|
for (i = 0; i < numplayers; ++i)
|
||||||
{
|
{
|
||||||
int node = !players[playerbytes[i]].isbot ?
|
int node = (players[playerbytes[i]].Bot == NULL) ?
|
||||||
nodeforplayer[playerbytes[i]] : netnode;
|
nodeforplayer[playerbytes[i]] : netnode;
|
||||||
|
|
||||||
SkipTicCmd (&start, nettics[node] - realstart);
|
SkipTicCmd (&start, nettics[node] - realstart);
|
||||||
|
@ -918,7 +918,7 @@ void GetPackets (void)
|
||||||
// packet.
|
// packet.
|
||||||
for (i = 0; i < numplayers; ++i)
|
for (i = 0; i < numplayers; ++i)
|
||||||
{
|
{
|
||||||
if (!players[playerbytes[i]].isbot)
|
if (players[playerbytes[i]].Bot == NULL)
|
||||||
{
|
{
|
||||||
nettics[nodeforplayer[playerbytes[i]]] = realend;
|
nettics[nodeforplayer[playerbytes[i]]] = realend;
|
||||||
}
|
}
|
||||||
|
@ -935,10 +935,10 @@ void AdjustBots (int gameticdiv)
|
||||||
// be in even when gametic lags behind maketic.
|
// be in even when gametic lags behind maketic.
|
||||||
for (int i = 0; i < MAXPLAYERS; i++)
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && players[i].isbot && players[i].mo)
|
if (playeringame[i] && players[i].Bot != NULL && players[i].mo)
|
||||||
{
|
{
|
||||||
players[i].savedyaw = players[i].mo->angle;
|
players[i].Bot->savedyaw = players[i].mo->angle;
|
||||||
players[i].savedpitch = players[i].mo->pitch;
|
players[i].Bot->savedpitch = players[i].mo->pitch;
|
||||||
for (int j = gameticdiv; j < maketic/ticdup; j++)
|
for (int j = gameticdiv; j < maketic/ticdup; j++)
|
||||||
{
|
{
|
||||||
players[i].mo->angle += (netcmds[i][j%BACKUPTICS].ucmd.yaw << 16) * ticdup;
|
players[i].mo->angle += (netcmds[i][j%BACKUPTICS].ucmd.yaw << 16) * ticdup;
|
||||||
|
@ -952,10 +952,10 @@ void UnadjustBots ()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAXPLAYERS; i++)
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && players[i].isbot && players[i].mo)
|
if (playeringame[i] && players[i].Bot != NULL && players[i].mo)
|
||||||
{
|
{
|
||||||
players[i].mo->angle = players[i].savedyaw;
|
players[i].mo->angle = players[i].Bot->savedyaw;
|
||||||
players[i].mo->pitch = players[i].savedpitch;
|
players[i].mo->pitch = players[i].Bot->savedpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1127,7 +1127,7 @@ void NetUpdate (void)
|
||||||
{
|
{
|
||||||
if (playeringame[j])
|
if (playeringame[j])
|
||||||
{
|
{
|
||||||
if (players[j].isbot || NetMode == NET_PacketServer)
|
if (players[j].Bot != NULL || NetMode == NET_PacketServer)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1269,7 @@ void NetUpdate (void)
|
||||||
{
|
{
|
||||||
if (playeringame[j] && j != playerfornode[i] && j != consoleplayer)
|
if (playeringame[j] && j != playerfornode[i] && j != consoleplayer)
|
||||||
{
|
{
|
||||||
if (players[j].isbot || NetMode == NET_PacketServer)
|
if (players[j].Bot != NULL || NetMode == NET_PacketServer)
|
||||||
{
|
{
|
||||||
playerbytes[l++] = j;
|
playerbytes[l++] = j;
|
||||||
netbuffer[k++] = j;
|
netbuffer[k++] = j;
|
||||||
|
@ -1308,9 +1308,8 @@ void NetUpdate (void)
|
||||||
}
|
}
|
||||||
else if (i != 0)
|
else if (i != 0)
|
||||||
{
|
{
|
||||||
if (players[playerbytes[l]].isbot)
|
if (players[playerbytes[l]].Bot != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
WriteWord (0, &cmddata); // fake consistancy word
|
WriteWord (0, &cmddata); // fake consistancy word
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2251,10 +2250,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEM_ADDBOT:
|
case DEM_ADDBOT:
|
||||||
{
|
bglobal.DoAddBot (stream);
|
||||||
BYTE num = ReadByte (stream);
|
|
||||||
bglobal.DoAddBot (num, s = ReadString (stream));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEM_KILLBOTS:
|
case DEM_KILLBOTS:
|
||||||
|
@ -2710,10 +2706,13 @@ void Net_SkipCommand (int type, BYTE **stream)
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case DEM_SAY:
|
case DEM_SAY:
|
||||||
case DEM_ADDBOT:
|
|
||||||
skip = strlen ((char *)(*stream + 1)) + 2;
|
skip = strlen ((char *)(*stream + 1)) + 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DEM_ADDBOT:
|
||||||
|
skip = strlen ((char *)(*stream + 1)) + 6;
|
||||||
|
break;
|
||||||
|
|
||||||
case DEM_GIVECHEAT:
|
case DEM_GIVECHEAT:
|
||||||
case DEM_TAKECHEAT:
|
case DEM_TAKECHEAT:
|
||||||
skip = strlen ((char *)(*stream)) + 3;
|
skip = strlen ((char *)(*stream)) + 3;
|
||||||
|
@ -2875,7 +2874,7 @@ static void Network_Controller (int playernum, bool add)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (players[playernum].isbot)
|
if (players[playernum].Bot != NULL)
|
||||||
{
|
{
|
||||||
Printf ("Bots cannot be added to the controller list.\n");
|
Printf ("Bots cannot be added to the controller list.\n");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -205,6 +205,8 @@ typedef enum
|
||||||
CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact
|
CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact
|
||||||
CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths.
|
CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths.
|
||||||
CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact
|
CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact
|
||||||
|
CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either.
|
||||||
|
CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either.
|
||||||
CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die
|
CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die
|
||||||
CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip
|
CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip
|
||||||
} cheat_t;
|
} cheat_t;
|
||||||
|
@ -442,47 +444,10 @@ public:
|
||||||
FName LastDamageType; // [RH] For damage-specific pain and death sounds
|
FName LastDamageType; // [RH] For damage-specific pain and death sounds
|
||||||
|
|
||||||
//Added by MC:
|
//Added by MC:
|
||||||
angle_t savedyaw;
|
TObjPtr<DBot> Bot;
|
||||||
int savedpitch;
|
|
||||||
|
|
||||||
angle_t angle; // The wanted angle that the bot try to get every tic.
|
|
||||||
// (used to get a smoth view movement)
|
|
||||||
TObjPtr<AActor> dest; // Move Destination.
|
|
||||||
TObjPtr<AActor> prev; // Previous move destination.
|
|
||||||
|
|
||||||
|
|
||||||
TObjPtr<AActor> enemy; // The dead meat.
|
|
||||||
TObjPtr<AActor> missile; // A threatening missile that needs to be avoided.
|
|
||||||
TObjPtr<AActor> mate; // Friend (used for grouping in teamplay or coop).
|
|
||||||
TObjPtr<AActor> last_mate; // If bots mate disappeared (not if died) that mate is
|
|
||||||
// pointed to by this. Allows bot to roam to it if
|
|
||||||
// necessary.
|
|
||||||
|
|
||||||
bool settings_controller; // Player can control game settings.
|
bool settings_controller; // Player can control game settings.
|
||||||
|
|
||||||
//Skills
|
|
||||||
struct botskill_t skill;
|
|
||||||
|
|
||||||
//Tickers
|
|
||||||
int t_active; // Open door, lower lift stuff, door must open and
|
|
||||||
// lift must go down before bot does anything
|
|
||||||
// radical like try a stuckmove
|
|
||||||
int t_respawn;
|
|
||||||
int t_strafe;
|
|
||||||
int t_react;
|
|
||||||
int t_fight;
|
|
||||||
int t_roam;
|
|
||||||
int t_rocket;
|
|
||||||
|
|
||||||
//Misc booleans
|
|
||||||
bool isbot;
|
|
||||||
bool first_shot; // Used for reaction skill.
|
|
||||||
bool sleft; // If false, strafe is right.
|
|
||||||
bool allround;
|
|
||||||
|
|
||||||
fixed_t oldx;
|
|
||||||
fixed_t oldy;
|
|
||||||
|
|
||||||
float BlendR; // [RH] Final blending values
|
float BlendR; // [RH] Final blending values
|
||||||
float BlendG;
|
float BlendG;
|
||||||
float BlendB;
|
float BlendB;
|
||||||
|
|
|
@ -112,7 +112,7 @@ enum EDemoCommand
|
||||||
DEM_DROPPLAYER, // 13 Not implemented, takes a byte
|
DEM_DROPPLAYER, // 13 Not implemented, takes a byte
|
||||||
DEM_CHANGEMAP, // 14 Name of map to change to
|
DEM_CHANGEMAP, // 14 Name of map to change to
|
||||||
DEM_SUICIDE, // 15 Player wants to die
|
DEM_SUICIDE, // 15 Player wants to die
|
||||||
DEM_ADDBOT, // 16 Byte: player#, String: userinfo for bot
|
DEM_ADDBOT, // 16 Byte: player#, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp)
|
||||||
DEM_KILLBOTS, // 17 Remove all bots from the world
|
DEM_KILLBOTS, // 17 Remove all bots from the world
|
||||||
DEM_INVUSEALL, // 18 Use every item (panic!)
|
DEM_INVUSEALL, // 18 Use every item (panic!)
|
||||||
DEM_INVUSE, // 19 4 bytes: ID of item to use
|
DEM_INVUSE, // 19 4 bytes: ID of item to use
|
||||||
|
@ -219,7 +219,9 @@ enum ECheatCommand
|
||||||
CHT_GIMMIEJ,
|
CHT_GIMMIEJ,
|
||||||
CHT_GIMMIEZ,
|
CHT_GIMMIEZ,
|
||||||
CHT_BUDDHA,
|
CHT_BUDDHA,
|
||||||
CHT_NOCLIP2
|
CHT_NOCLIP2,
|
||||||
|
CHT_BUDDHA2,
|
||||||
|
CHT_GOD2
|
||||||
};
|
};
|
||||||
|
|
||||||
void StartChunk (int id, BYTE **stream);
|
void StartChunk (int id, BYTE **stream);
|
||||||
|
|
|
@ -339,6 +339,7 @@ enum
|
||||||
|
|
||||||
COMPATF2_BADANGLES = 1 << 0, // It is impossible to face directly NSEW.
|
COMPATF2_BADANGLES = 1 << 0, // It is impossible to face directly NSEW.
|
||||||
COMPATF2_FLOORMOVE = 1 << 1, // Use the same floor motion behavior as Doom.
|
COMPATF2_FLOORMOVE = 1 << 1, // Use the same floor motion behavior as Doom.
|
||||||
|
COMPATF2_SOUNDCUTOFF = 1 << 2, // Cut off sounds when an actor vanishes instead of making it owner-less
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emulate old bugs for select maps. These are not exposed by a cvar
|
// Emulate old bugs for select maps. These are not exposed by a cvar
|
||||||
|
|
|
@ -875,7 +875,7 @@ static void ChangeSpy (int changespy)
|
||||||
pnum &= MAXPLAYERS-1;
|
pnum &= MAXPLAYERS-1;
|
||||||
if (playeringame[pnum] &&
|
if (playeringame[pnum] &&
|
||||||
(!checkTeam || players[pnum].mo->IsTeammate (players[consoleplayer].mo) ||
|
(!checkTeam || players[pnum].mo->IsTeammate (players[consoleplayer].mo) ||
|
||||||
(bot_allowspy && players[pnum].isbot)))
|
(bot_allowspy && players[pnum].Bot != NULL)))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1156,7 +1156,7 @@ void G_Ticker ()
|
||||||
Printf ("%s is turbo!\n", players[i].userinfo.GetName());
|
Printf ("%s is turbo!\n", players[i].userinfo.GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netgame && !players[i].isbot && !demoplayback && (gametic%ticdup) == 0)
|
if (netgame && players[i].Bot == NULL && !demoplayback && (gametic%ticdup) == 0)
|
||||||
{
|
{
|
||||||
//players[i].inconsistant = 0;
|
//players[i].inconsistant = 0;
|
||||||
if (gametic > BACKUPTICS*ticdup && consistancy[i][buf] != cmd->consistancy)
|
if (gametic > BACKUPTICS*ticdup && consistancy[i][buf] != cmd->consistancy)
|
||||||
|
@ -1338,10 +1338,10 @@ void G_PlayerReborn (int player)
|
||||||
int chasecam;
|
int chasecam;
|
||||||
BYTE currclass;
|
BYTE currclass;
|
||||||
userinfo_t userinfo; // [RH] Save userinfo
|
userinfo_t userinfo; // [RH] Save userinfo
|
||||||
botskill_t b_skill; //Added by MC:
|
|
||||||
APlayerPawn *actor;
|
APlayerPawn *actor;
|
||||||
const PClass *cls;
|
const PClass *cls;
|
||||||
FString log;
|
FString log;
|
||||||
|
DBot *Bot; //Added by MC:
|
||||||
|
|
||||||
p = &players[player];
|
p = &players[player];
|
||||||
|
|
||||||
|
@ -1351,18 +1351,19 @@ void G_PlayerReborn (int player)
|
||||||
itemcount = p->itemcount;
|
itemcount = p->itemcount;
|
||||||
secretcount = p->secretcount;
|
secretcount = p->secretcount;
|
||||||
currclass = p->CurrentPlayerClass;
|
currclass = p->CurrentPlayerClass;
|
||||||
b_skill = p->skill; //Added by MC:
|
|
||||||
userinfo.TransferFrom(p->userinfo);
|
userinfo.TransferFrom(p->userinfo);
|
||||||
actor = p->mo;
|
actor = p->mo;
|
||||||
cls = p->cls;
|
cls = p->cls;
|
||||||
log = p->LogText;
|
log = p->LogText;
|
||||||
chasecam = p->cheats & CF_CHASECAM;
|
chasecam = p->cheats & CF_CHASECAM;
|
||||||
|
Bot = p->Bot; //Added by MC:
|
||||||
|
|
||||||
// Reset player structure to its defaults
|
// Reset player structure to its defaults
|
||||||
p->~player_t();
|
p->~player_t();
|
||||||
::new(p) player_t;
|
::new(p) player_t;
|
||||||
|
|
||||||
memcpy (p->frags, frags, sizeof(p->frags));
|
memcpy (p->frags, frags, sizeof(p->frags));
|
||||||
|
p->health = actor->health;
|
||||||
p->fragcount = fragcount;
|
p->fragcount = fragcount;
|
||||||
p->killcount = killcount;
|
p->killcount = killcount;
|
||||||
p->itemcount = itemcount;
|
p->itemcount = itemcount;
|
||||||
|
@ -1373,8 +1374,7 @@ void G_PlayerReborn (int player)
|
||||||
p->cls = cls;
|
p->cls = cls;
|
||||||
p->LogText = log;
|
p->LogText = log;
|
||||||
p->cheats |= chasecam;
|
p->cheats |= chasecam;
|
||||||
|
p->Bot = Bot; //Added by MC:
|
||||||
p->skill = b_skill; //Added by MC:
|
|
||||||
|
|
||||||
p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately
|
p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately
|
||||||
p->original_oldbuttons = ~0;
|
p->original_oldbuttons = ~0;
|
||||||
|
@ -1382,15 +1382,19 @@ void G_PlayerReborn (int player)
|
||||||
|
|
||||||
if (gamestate != GS_TITLELEVEL)
|
if (gamestate != GS_TITLELEVEL)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// [GRB] Give inventory specified in DECORATE
|
||||||
actor->GiveDefaultInventory ();
|
actor->GiveDefaultInventory ();
|
||||||
p->ReadyWeapon = p->PendingWeapon;
|
p->ReadyWeapon = p->PendingWeapon;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Added by MC: Init bot structure.
|
//Added by MC: Init bot structure.
|
||||||
if (bglobal.botingame[player])
|
if (p->Bot != NULL)
|
||||||
bglobal.CleanBotstuff (p);
|
{
|
||||||
else
|
botskill_t skill = p->Bot->skill;
|
||||||
p->isbot = false;
|
p->Bot->Clear ();
|
||||||
|
p->Bot->skill = skill;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -1183,6 +1183,15 @@ void G_FinishTravel ()
|
||||||
pawn->AddToHash ();
|
pawn->AddToHash ();
|
||||||
pawn->SetState(pawn->SpawnState);
|
pawn->SetState(pawn->SpawnState);
|
||||||
pawn->player->SendPitchLimits();
|
pawn->player->SendPitchLimits();
|
||||||
|
// Sync the FLY flags.
|
||||||
|
if (pawn->flags2 & MF2_FLY)
|
||||||
|
{
|
||||||
|
pawn->player->cheats |= CF_FLY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pawn->player->cheats &= ~CF_FLY;
|
||||||
|
}
|
||||||
|
|
||||||
for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
|
for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1306,6 +1306,7 @@ MapFlagHandlers[] =
|
||||||
{ "compat_maskedmidtex", MITYPE_COMPATFLAG, COMPATF_MASKEDMIDTEX, 0 },
|
{ "compat_maskedmidtex", MITYPE_COMPATFLAG, COMPATF_MASKEDMIDTEX, 0 },
|
||||||
{ "compat_badangles", MITYPE_COMPATFLAG, 0, COMPATF2_BADANGLES },
|
{ "compat_badangles", MITYPE_COMPATFLAG, 0, COMPATF2_BADANGLES },
|
||||||
{ "compat_floormove", MITYPE_COMPATFLAG, 0, COMPATF2_FLOORMOVE },
|
{ "compat_floormove", MITYPE_COMPATFLAG, 0, COMPATF2_FLOORMOVE },
|
||||||
|
{ "compat_soundcutoff", MITYPE_COMPATFLAG, 0, COMPATF2_SOUNDCUTOFF },
|
||||||
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 },
|
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 },
|
||||||
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
|
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
|
||||||
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 },
|
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 },
|
||||||
|
|
|
@ -1296,6 +1296,18 @@ void APowerTargeter::InitEffect ()
|
||||||
PositionAccuracy ();
|
PositionAccuracy ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool APowerTargeter::HandlePickup(AInventory *item)
|
||||||
|
{
|
||||||
|
if (Super::HandlePickup(item))
|
||||||
|
{
|
||||||
|
InitEffect(); // reset the HUD sprites
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void APowerTargeter::DoEffect ()
|
void APowerTargeter::DoEffect ()
|
||||||
{
|
{
|
||||||
Super::DoEffect ();
|
Super::DoEffect ();
|
||||||
|
@ -1384,6 +1396,42 @@ void APowerFrightener::EndEffect ()
|
||||||
Owner->player->cheats &= ~CF_FRIGHTENING;
|
Owner->player->cheats &= ~CF_FRIGHTENING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buddha Powerup --------------------------------
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS (APowerBuddha)
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// APowerBuddha :: InitEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void APowerBuddha::InitEffect ()
|
||||||
|
{
|
||||||
|
Super::InitEffect();
|
||||||
|
|
||||||
|
if (Owner== NULL || Owner->player == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Owner->player->cheats |= CF_BUDDHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// APowerBuddha :: EndEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
void APowerBuddha::EndEffect ()
|
||||||
|
{
|
||||||
|
Super::EndEffect();
|
||||||
|
|
||||||
|
if (Owner== NULL || Owner->player == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Owner->player->cheats &= ~CF_BUDDHA;
|
||||||
|
}
|
||||||
|
|
||||||
// Scanner powerup ----------------------------------------------------------
|
// Scanner powerup ----------------------------------------------------------
|
||||||
|
|
||||||
IMPLEMENT_CLASS (APowerScanner)
|
IMPLEMENT_CLASS (APowerScanner)
|
||||||
|
|
|
@ -173,6 +173,7 @@ protected:
|
||||||
void EndEffect ();
|
void EndEffect ();
|
||||||
void PositionAccuracy ();
|
void PositionAccuracy ();
|
||||||
void Travelled ();
|
void Travelled ();
|
||||||
|
bool HandlePickup(AInventory *item);
|
||||||
};
|
};
|
||||||
|
|
||||||
class APowerFrightener : public APowerup
|
class APowerFrightener : public APowerup
|
||||||
|
@ -183,6 +184,14 @@ protected:
|
||||||
void EndEffect ();
|
void EndEffect ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class APowerBuddha : public APowerup
|
||||||
|
{
|
||||||
|
DECLARE_CLASS (APowerBuddha, APowerup)
|
||||||
|
protected:
|
||||||
|
void InitEffect ();
|
||||||
|
void EndEffect ();
|
||||||
|
};
|
||||||
|
|
||||||
class APowerTimeFreezer : public APowerup
|
class APowerTimeFreezer : public APowerup
|
||||||
{
|
{
|
||||||
DECLARE_CLASS( APowerTimeFreezer, APowerup )
|
DECLARE_CLASS( APowerTimeFreezer, APowerup )
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "farchive.h"
|
#include "farchive.h"
|
||||||
|
#include "p_enemy.h"
|
||||||
|
|
||||||
static FRandom pr_morphmonst ("MorphMonster");
|
static FRandom pr_morphmonst ("MorphMonster");
|
||||||
|
|
||||||
|
@ -527,11 +528,11 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor
|
||||||
if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||||
{
|
{
|
||||||
AMorphedMonster *fakeme = static_cast<AMorphedMonster *>(actor);
|
AMorphedMonster *fakeme = static_cast<AMorphedMonster *>(actor);
|
||||||
|
AActor *realme = fakeme->UnmorphedMe;
|
||||||
if ((fakeme->UnmorphTime) &&
|
if ((fakeme->UnmorphTime) &&
|
||||||
(fakeme->MorphStyle & MORPH_UNDOBYDEATH) &&
|
(fakeme->MorphStyle & MORPH_UNDOBYDEATH) &&
|
||||||
(fakeme->UnmorphedMe))
|
(realme))
|
||||||
{
|
{
|
||||||
AActor *realme = fakeme->UnmorphedMe;
|
|
||||||
int realstyle = fakeme->MorphStyle;
|
int realstyle = fakeme->MorphStyle;
|
||||||
int realhealth = fakeme->health;
|
int realhealth = fakeme->health;
|
||||||
if (P_UndoMonsterMorph(fakeme, !!(fakeme->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
|
if (P_UndoMonsterMorph(fakeme, !!(fakeme->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
|
||||||
|
@ -542,6 +543,11 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (realme->flags4 & MF4_BOSSDEATH)
|
||||||
|
{
|
||||||
|
realme->health = 0; // make sure that A_BossDeath considers it dead.
|
||||||
|
CALL_ACTION(A_BossDeath, realme);
|
||||||
|
}
|
||||||
fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die()
|
fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -499,7 +499,7 @@ bool AInventory::ShouldRespawn ()
|
||||||
{
|
{
|
||||||
if ((ItemFlags & IF_BIGPOWERUP) && !(dmflags2 & DF2_RESPAWN_SUPER)) return false;
|
if ((ItemFlags & IF_BIGPOWERUP) && !(dmflags2 & DF2_RESPAWN_SUPER)) return false;
|
||||||
if (ItemFlags & IF_NEVERRESPAWN) return false;
|
if (ItemFlags & IF_NEVERRESPAWN) return false;
|
||||||
return !!(dmflags & DF_ITEMS_RESPAWN);
|
return !!((dmflags & DF_ITEMS_RESPAWN) || (ItemFlags & IF_ALWAYSRESPAWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -1024,8 +1024,8 @@ void AInventory::Touch (AActor *toucher)
|
||||||
//Added by MC: Check if item taken was the roam destination of any bot
|
//Added by MC: Check if item taken was the roam destination of any bot
|
||||||
for (int i = 0; i < MAXPLAYERS; i++)
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (playeringame[i] && this == players[i].dest)
|
if (playeringame[i] && players[i].Bot != NULL && this == players[i].Bot->dest)
|
||||||
players[i].dest = NULL;
|
players[i].Bot->dest = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ enum
|
||||||
IF_NEVERRESPAWN = 1<<20, // Never, ever respawns
|
IF_NEVERRESPAWN = 1<<20, // Never, ever respawns
|
||||||
IF_NOSCREENFLASH = 1<<21, // No pickup flash on the player's screen
|
IF_NOSCREENFLASH = 1<<21, // No pickup flash on the player's screen
|
||||||
IF_TOSSED = 1<<22, // Was spawned by P_DropItem (i.e. as a monster drop)
|
IF_TOSSED = 1<<22, // Was spawned by P_DropItem (i.e. as a monster drop)
|
||||||
|
IF_ALWAYSRESPAWN = 1<<23, // Always respawn, regardless of dmflag
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -444,7 +444,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags)
|
||||||
if (bNormal)
|
if (bNormal)
|
||||||
{
|
{
|
||||||
bool good;
|
bool good;
|
||||||
if ((player->cheats & CF_GODMODE) || (player->mo != NULL && player->mo->flags2 & MF2_INVULNERABLE))
|
if ((player->cheats & CF_GODMODE) || (player->cheats & CF_GODMODE2) || (player->mo != NULL && player->mo->flags2 & MF2_INVULNERABLE))
|
||||||
{
|
{
|
||||||
good = SetState((stateflags & ANIMATEDGODMODE) ? "godanimated" : "god");
|
good = SetState((stateflags & ANIMATEDGODMODE) ? "godanimated" : "god");
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath)
|
||||||
switch (self->GetClass()->TypeName)
|
switch (self->GetClass()->TypeName)
|
||||||
{
|
{
|
||||||
case NAME_AlienSpectre1:
|
case NAME_AlienSpectre1:
|
||||||
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 999, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 999, FRACUNIT, 0, -1, 0, false);
|
||||||
log = 95;
|
log = 95;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath)
|
||||||
{ // Another Sigil piece. Woohoo!
|
{ // Another Sigil piece. Woohoo!
|
||||||
log = 83;
|
log = 83;
|
||||||
}
|
}
|
||||||
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, -1, 0, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -80,6 +80,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderDeath)
|
||||||
{
|
{
|
||||||
if (CheckBossDeath (self))
|
if (CheckBossDeath (self))
|
||||||
{
|
{
|
||||||
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 667, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 667, FRACUNIT, 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -548,7 +548,7 @@ void APowerCoupling::Die (AActor *source, AActor *inflictor, int dmgflags)
|
||||||
P_NoiseAlert (source, this);
|
P_NoiseAlert (source, this);
|
||||||
}
|
}
|
||||||
EV_DoDoor (DDoor::doorClose, NULL, players[i].mo, 225, 2*FRACUNIT, 0, 0, 0);
|
EV_DoDoor (DDoor::doorClose, NULL, players[i].mo, 225, 2*FRACUNIT, 0, 0, 0);
|
||||||
EV_DoFloor (DFloor::floorLowerToHighest, NULL, 44, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorLowerToHighest, NULL, 44, FRACUNIT, 0, -1, 0, false);
|
||||||
players[i].mo->GiveInventoryType (QuestItemClasses[5]);
|
players[i].mo->GiveInventoryType (QuestItemClasses[5]);
|
||||||
S_Sound (CHAN_VOICE, "svox/voc13", 1, ATTN_NORM);
|
S_Sound (CHAN_VOICE, "svox/voc13", 1, ATTN_NORM);
|
||||||
players[i].SetLogNumber (13);
|
players[i].SetLogNumber (13);
|
||||||
|
|
|
@ -290,6 +290,9 @@ void FMapInfoParser::ParseGameInfo()
|
||||||
else gameinfo.mCheatMapArrow = "";
|
else gameinfo.mCheatMapArrow = "";
|
||||||
}
|
}
|
||||||
// Insert valid keys here.
|
// Insert valid keys here.
|
||||||
|
GAMEINFOKEY_STRING(mCheatKey, "cheatKey")
|
||||||
|
GAMEINFOKEY_STRING(mEasyKey, "easyKey")
|
||||||
|
GAMEINFOKEY_STRING(TitlePage, "titlePage")
|
||||||
GAMEINFOKEY_STRING(TitlePage, "titlePage")
|
GAMEINFOKEY_STRING(TitlePage, "titlePage")
|
||||||
GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false)
|
GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false)
|
||||||
GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true)
|
GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true)
|
||||||
|
|
1
src/gi.h
1
src/gi.h
|
@ -169,6 +169,7 @@ struct gameinfo_t
|
||||||
int TextScreenY;
|
int TextScreenY;
|
||||||
FName DefaultEndSequence;
|
FName DefaultEndSequence;
|
||||||
FString mMapArrow, mCheatMapArrow;
|
FString mMapArrow, mCheatMapArrow;
|
||||||
|
FString mEasyKey, mCheatKey;
|
||||||
FGIFont mStatscreenMapNameFont;
|
FGIFont mStatscreenMapNameFont;
|
||||||
FGIFont mStatscreenFinishedFont;
|
FGIFont mStatscreenFinishedFont;
|
||||||
FGIFont mStatscreenEnteringFont;
|
FGIFont mStatscreenEnteringFont;
|
||||||
|
|
|
@ -135,8 +135,8 @@ struct PreGamePacket
|
||||||
};
|
};
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u_long address;
|
DWORD address;
|
||||||
u_short port;
|
WORD port;
|
||||||
BYTE player;
|
BYTE player;
|
||||||
BYTE pad;
|
BYTE pad;
|
||||||
} machines[MAXNETNODES];
|
} machines[MAXNETNODES];
|
||||||
|
@ -660,6 +660,12 @@ void HostGame (int i)
|
||||||
numplayers = 2;
|
numplayers = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (numplayers > MAXNETNODES)
|
||||||
|
{
|
||||||
|
I_FatalError("You cannot host a game with %d players. The limit is currently %d.", numplayers, MAXNETNODES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (numplayers == 1)
|
if (numplayers == 1)
|
||||||
{ // Special case: Only 1 player, so don't bother starting the network
|
{ // Special case: Only 1 player, so don't bother starting the network
|
||||||
netgame = false;
|
netgame = false;
|
||||||
|
|
|
@ -99,6 +99,23 @@ void cht_DoCheat (player_t *player, int cheat)
|
||||||
msg = GStrings("TXT_BUDDHAOFF");
|
msg = GStrings("TXT_BUDDHAOFF");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CHT_GOD2:
|
||||||
|
player->cheats ^= CF_GODMODE2;
|
||||||
|
if (player->cheats & CF_GODMODE2)
|
||||||
|
msg = GStrings("STSTR_DQD2ON");
|
||||||
|
else
|
||||||
|
msg = GStrings("STSTR_DQD2OFF");
|
||||||
|
ST_SetNeedRefresh();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHT_BUDDHA2:
|
||||||
|
player->cheats ^= CF_BUDDHA2;
|
||||||
|
if (player->cheats & CF_BUDDHA2)
|
||||||
|
msg = GStrings("TXT_BUDDHA2ON");
|
||||||
|
else
|
||||||
|
msg = GStrings("TXT_BUDDHA2OFF");
|
||||||
|
break;
|
||||||
|
|
||||||
case CHT_NOCLIP:
|
case CHT_NOCLIP:
|
||||||
player->cheats ^= CF_NOCLIP;
|
player->cheats ^= CF_NOCLIP;
|
||||||
if (player->cheats & CF_NOCLIP)
|
if (player->cheats & CF_NOCLIP)
|
||||||
|
@ -323,7 +340,6 @@ void cht_DoCheat (player_t *player, int cheat)
|
||||||
player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players));
|
player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players));
|
||||||
}
|
}
|
||||||
player->mo->DamageType = NAME_None;
|
player->mo->DamageType = NAME_None;
|
||||||
// player->mo->GiveDefaultInventory();
|
|
||||||
if (player->ReadyWeapon != NULL)
|
if (player->ReadyWeapon != NULL)
|
||||||
{
|
{
|
||||||
P_SetPsprite(player, ps_weapon, player->ReadyWeapon->GetUpState());
|
P_SetPsprite(player, ps_weapon, player->ReadyWeapon->GetUpState());
|
||||||
|
|
|
@ -120,6 +120,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag
|
||||||
|
|
||||||
//Add the floor
|
//Add the floor
|
||||||
ffloor = new F3DFloor;
|
ffloor = new F3DFloor;
|
||||||
|
ffloor->top.copied = ffloor->bottom.copied = false;
|
||||||
ffloor->top.model = ffloor->bottom.model = ffloor->model = sec2;
|
ffloor->top.model = ffloor->bottom.model = ffloor->model = sec2;
|
||||||
ffloor->target = sec;
|
ffloor->target = sec;
|
||||||
ffloor->ceilingclip = ffloor->floorclip = NULL;
|
ffloor->ceilingclip = ffloor->floorclip = NULL;
|
||||||
|
@ -420,6 +421,8 @@ void P_Recalculate3DFloors(sector_t * sector)
|
||||||
F3DFloor * pick;
|
F3DFloor * pick;
|
||||||
unsigned pickindex;
|
unsigned pickindex;
|
||||||
F3DFloor * clipped=NULL;
|
F3DFloor * clipped=NULL;
|
||||||
|
F3DFloor * solid=NULL;
|
||||||
|
fixed_t solid_bottom=0;
|
||||||
fixed_t clipped_top;
|
fixed_t clipped_top;
|
||||||
fixed_t clipped_bottom=0;
|
fixed_t clipped_bottom=0;
|
||||||
fixed_t maxheight, minheight;
|
fixed_t maxheight, minheight;
|
||||||
|
@ -477,6 +480,7 @@ void P_Recalculate3DFloors(sector_t * sector)
|
||||||
}
|
}
|
||||||
|
|
||||||
oldlist.Delete(pickindex);
|
oldlist.Delete(pickindex);
|
||||||
|
fixed_t pick_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector));
|
||||||
|
|
||||||
if (pick->flags & FF_THISINSIDE)
|
if (pick->flags & FF_THISINSIDE)
|
||||||
{
|
{
|
||||||
|
@ -486,10 +490,38 @@ void P_Recalculate3DFloors(sector_t * sector)
|
||||||
}
|
}
|
||||||
else if (pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) && pick->flags&FF_EXISTS)
|
else if (pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) && pick->flags&FF_EXISTS)
|
||||||
{
|
{
|
||||||
clipped=pick;
|
// We must check if this nonsolid segment gets clipped from the top by another 3D floor
|
||||||
clipped_top=height;
|
if (solid != NULL && solid_bottom < height)
|
||||||
clipped_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector));
|
{
|
||||||
ffloors.Push(pick);
|
ffloors.Push(pick);
|
||||||
|
if (solid_bottom < pick_bottom)
|
||||||
|
{
|
||||||
|
// this one is fully covered
|
||||||
|
pick->flags|=FF_CLIPPED;
|
||||||
|
pick->flags&=~FF_EXISTS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
F3DFloor * dyn=new F3DFloor;
|
||||||
|
*dyn=*pick;
|
||||||
|
pick->flags|=FF_CLIPPED;
|
||||||
|
pick->flags&=~FF_EXISTS;
|
||||||
|
dyn->flags|=FF_DYNAMIC;
|
||||||
|
dyn->top.copyPlane(&solid->bottom);
|
||||||
|
ffloors.Push(dyn);
|
||||||
|
|
||||||
|
clipped = dyn;
|
||||||
|
clipped_top = solid_bottom;
|
||||||
|
clipped_bottom = pick_bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clipped = pick;
|
||||||
|
clipped_top = height;
|
||||||
|
clipped_bottom = pick_bottom;
|
||||||
|
ffloors.Push(pick);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (clipped && clipped_bottom<height)
|
else if (clipped && clipped_bottom<height)
|
||||||
{
|
{
|
||||||
|
@ -499,12 +531,10 @@ void P_Recalculate3DFloors(sector_t * sector)
|
||||||
clipped->flags|=FF_CLIPPED;
|
clipped->flags|=FF_CLIPPED;
|
||||||
clipped->flags&=~FF_EXISTS;
|
clipped->flags&=~FF_EXISTS;
|
||||||
dyn->flags|=FF_DYNAMIC;
|
dyn->flags|=FF_DYNAMIC;
|
||||||
dyn->bottom=pick->top;
|
dyn->bottom.copyPlane(&pick->top);
|
||||||
ffloors.Push(dyn);
|
ffloors.Push(dyn);
|
||||||
ffloors.Push(pick);
|
ffloors.Push(pick);
|
||||||
|
|
||||||
fixed_t pick_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector));
|
|
||||||
|
|
||||||
if (pick_bottom<=clipped_bottom)
|
if (pick_bottom<=clipped_bottom)
|
||||||
{
|
{
|
||||||
clipped=NULL;
|
clipped=NULL;
|
||||||
|
@ -515,14 +545,25 @@ void P_Recalculate3DFloors(sector_t * sector)
|
||||||
dyn=new F3DFloor;
|
dyn=new F3DFloor;
|
||||||
*dyn=*clipped;
|
*dyn=*clipped;
|
||||||
dyn->flags|=FF_DYNAMIC|FF_EXISTS;
|
dyn->flags|=FF_DYNAMIC|FF_EXISTS;
|
||||||
dyn->top=pick->bottom;
|
dyn->top.copyPlane(&pick->bottom);
|
||||||
ffloors.Push(dyn);
|
ffloors.Push(dyn);
|
||||||
|
clipped = dyn;
|
||||||
|
clipped_top = pick_bottom;
|
||||||
}
|
}
|
||||||
|
solid = pick;
|
||||||
|
solid_bottom = pick_bottom;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clipped=NULL;
|
clipped = NULL;
|
||||||
|
if (solid == NULL || solid_bottom > pick_bottom)
|
||||||
|
{
|
||||||
|
// only if this one is lower
|
||||||
|
solid = pick;
|
||||||
|
solid_bottom = pick_bottom;
|
||||||
|
}
|
||||||
ffloors.Push(pick);
|
ffloors.Push(pick);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -910,3 +951,27 @@ int P_Find3DFloor(sector_t * sec, fixed_t x, fixed_t y, fixed_t z, bool above, b
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "c_dispatch.h"
|
||||||
|
|
||||||
|
|
||||||
|
CCMD (dump3df)
|
||||||
|
{
|
||||||
|
if (argv.argc() > 1)
|
||||||
|
{
|
||||||
|
int sec = strtol(argv[1], NULL, 10);
|
||||||
|
sector_t *sector = §ors[sec];
|
||||||
|
TArray<F3DFloor*> & ffloors=sector->e->XFloor.ffloors;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ffloors.Size(); i++)
|
||||||
|
{
|
||||||
|
fixed_t height=ffloors[i]->top.plane->ZatPoint(CenterSpot(sector));
|
||||||
|
fixed_t bheight=ffloors[i]->bottom.plane->ZatPoint(CenterSpot(sector));
|
||||||
|
|
||||||
|
Printf("FFloor %d @ top = %f (model = %d), bottom = %f (model = %d), flags = %B, alpha = %d %s %s\n",
|
||||||
|
i, height / 65536., ffloors[i]->top.model->sectornum,
|
||||||
|
bheight / 65536., ffloors[i]->bottom.model->sectornum,
|
||||||
|
ffloors[i]->flags, ffloors[i]->alpha, (ffloors[i]->flags&FF_EXISTS)? "Exists":"", (ffloors[i]->flags&FF_DYNAMIC)? "Dynamic":"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -77,6 +77,13 @@ struct F3DFloor
|
||||||
sector_t * model;
|
sector_t * model;
|
||||||
int isceiling;
|
int isceiling;
|
||||||
int vindex;
|
int vindex;
|
||||||
|
bool copied;
|
||||||
|
|
||||||
|
void copyPlane(planeref * other)
|
||||||
|
{
|
||||||
|
*this = *other;
|
||||||
|
copied = true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
planeref bottom;
|
planeref bottom;
|
||||||
|
|
|
@ -4228,7 +4228,7 @@ int DLevelScript::DoClassifyActor(int tid)
|
||||||
{
|
{
|
||||||
classify |= ACTOR_VOODOODOLL;
|
classify |= ACTOR_VOODOODOLL;
|
||||||
}
|
}
|
||||||
if (actor->player->isbot)
|
if (actor->player->Bot != NULL)
|
||||||
{
|
{
|
||||||
classify |= ACTOR_BOT;
|
classify |= ACTOR_BOT;
|
||||||
}
|
}
|
||||||
|
@ -5619,15 +5619,27 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
||||||
wallMask = args[6];
|
wallMask = args[6];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool forceTID = 0;
|
||||||
|
if (argCount >= 8)
|
||||||
|
{
|
||||||
|
if (args[7] != 0)
|
||||||
|
forceTID = 1;
|
||||||
|
}
|
||||||
|
|
||||||
AActor* pickedActor = P_LinePickActor(actor, args[1] << 16, args[3], args[2] << 16, actorMask, wallMask);
|
AActor* pickedActor = P_LinePickActor(actor, args[1] << 16, args[3], args[2] << 16, actorMask, wallMask);
|
||||||
if (pickedActor == NULL) {
|
if (pickedActor == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pickedActor->RemoveFromHash();
|
if (!(forceTID) && (args[4] == 0) && (pickedActor->tid == 0))
|
||||||
pickedActor->tid = args[4];
|
return 0;
|
||||||
pickedActor->AddToHash();
|
|
||||||
|
|
||||||
|
if ((pickedActor->tid == 0) || (forceTID))
|
||||||
|
{
|
||||||
|
pickedActor->RemoveFromHash();
|
||||||
|
pickedActor->tid = args[4];
|
||||||
|
pickedActor->AddToHash();
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -8632,7 +8644,7 @@ scriptwait:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
STACK(1) = players[STACK(1)].isbot;
|
STACK(1) = (players[STACK(1)].Bot != NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -460,7 +460,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
|
||||||
// run into them (otherwise opening them would be
|
// run into them (otherwise opening them would be
|
||||||
// a real pain).
|
// a real pain).
|
||||||
{
|
{
|
||||||
if (!thing->player || thing->player->isbot)
|
if (!thing->player || thing->player->Bot != NULL)
|
||||||
return false; // JDC: bad guys never close doors
|
return false; // JDC: bad guys never close doors
|
||||||
//Added by MC: Neither do bots.
|
//Added by MC: Neither do bots.
|
||||||
|
|
||||||
|
|
|
@ -1592,7 +1592,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// [SP] If you don't see any enemies in deathmatch, look for players (but only when friend to a specific player.)
|
// [SP] If you don't see any enemies in deathmatch, look for players (but only when friend to a specific player.)
|
||||||
if (actor->FriendPlayer == 0 && (!teamplay || actor->DesignatedTeam == TEAM_NONE)) return result;
|
if (actor->FriendPlayer == 0 && (!teamplay || actor->GetTeam() == TEAM_NONE)) return result;
|
||||||
if (result || !deathmatch) return true;
|
if (result || !deathmatch) return true;
|
||||||
|
|
||||||
|
|
||||||
|
@ -3275,13 +3275,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_BossDeath)
|
||||||
{
|
{
|
||||||
if (type == NAME_Fatso)
|
if (type == NAME_Fatso)
|
||||||
{
|
{
|
||||||
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, -1, 0, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == NAME_Arachnotron)
|
if (type == NAME_Arachnotron)
|
||||||
{
|
{
|
||||||
EV_DoFloor (DFloor::floorRaiseByTexture, NULL, 667, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorRaiseByTexture, NULL, 667, FRACUNIT, 0, -1, 0, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3290,11 +3290,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_BossDeath)
|
||||||
switch (level.flags & LEVEL_SPECACTIONSMASK)
|
switch (level.flags & LEVEL_SPECACTIONSMASK)
|
||||||
{
|
{
|
||||||
case LEVEL_SPECLOWERFLOOR:
|
case LEVEL_SPECLOWERFLOOR:
|
||||||
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, -1, 0, false);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case LEVEL_SPECLOWERFLOORTOHIGHEST:
|
case LEVEL_SPECLOWERFLOORTOHIGHEST:
|
||||||
EV_DoFloor (DFloor::floorLowerToHighest, NULL, 666, FRACUNIT, 0, 0, 0, false);
|
EV_DoFloor (DFloor::floorLowerToHighest, NULL, 666, FRACUNIT, 0, -1, 0, false);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case LEVEL_SPECOPENDOOR:
|
case LEVEL_SPECOPENDOOR:
|
||||||
|
|
|
@ -320,7 +320,7 @@ manual_floor:
|
||||||
rtn = true;
|
rtn = true;
|
||||||
floor = new DFloor (sec);
|
floor = new DFloor (sec);
|
||||||
floor->m_Type = floortype;
|
floor->m_Type = floortype;
|
||||||
floor->m_Crush = -1;
|
floor->m_Crush = crush;
|
||||||
floor->m_Hexencrush = hexencrush;
|
floor->m_Hexencrush = hexencrush;
|
||||||
floor->m_Speed = speed;
|
floor->m_Speed = speed;
|
||||||
floor->m_ResetCount = 0; // [RH]
|
floor->m_ResetCount = 0; // [RH]
|
||||||
|
@ -374,7 +374,6 @@ manual_floor:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DFloor::floorRaiseAndCrushDoom:
|
case DFloor::floorRaiseAndCrushDoom:
|
||||||
floor->m_Crush = crush;
|
|
||||||
case DFloor::floorRaiseToLowestCeiling:
|
case DFloor::floorRaiseToLowestCeiling:
|
||||||
floor->m_Direction = 1;
|
floor->m_Direction = 1;
|
||||||
newheight = sec->FindLowestCeilingSurrounding (&spot);
|
newheight = sec->FindLowestCeilingSurrounding (&spot);
|
||||||
|
@ -406,7 +405,6 @@ manual_floor:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DFloor::floorRaiseAndCrush:
|
case DFloor::floorRaiseAndCrush:
|
||||||
floor->m_Crush = crush;
|
|
||||||
floor->m_Direction = 1;
|
floor->m_Direction = 1;
|
||||||
newheight = sec->FindLowestCeilingPoint (&spot) - 8*FRACUNIT;
|
newheight = sec->FindLowestCeilingPoint (&spot) - 8*FRACUNIT;
|
||||||
floor->m_FloorDestDist = sec->floorplane.PointToDist (spot, newheight);
|
floor->m_FloorDestDist = sec->floorplane.PointToDist (spot, newheight);
|
||||||
|
|
|
@ -100,10 +100,10 @@ void P_TouchSpecialThing (AActor *special, AActor *toucher)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Added by MC: Finished with this destination.
|
//Added by MC: Finished with this destination.
|
||||||
if (toucher->player != NULL && toucher->player->isbot && special == toucher->player->dest)
|
if (toucher->player != NULL && toucher->player->Bot != NULL && special == toucher->player->Bot->dest)
|
||||||
{
|
{
|
||||||
toucher->player->prev = toucher->player->dest;
|
toucher->player->Bot->prev = toucher->player->Bot->dest;
|
||||||
toucher->player->dest = NULL;
|
toucher->player->Bot->dest = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
special->Touch (toucher);
|
special->Touch (toucher);
|
||||||
|
@ -608,17 +608,17 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags)
|
||||||
//Added by MC: Respawn bots
|
//Added by MC: Respawn bots
|
||||||
if (bglobal.botnum && consoleplayer == Net_Arbitrator && !demoplayback)
|
if (bglobal.botnum && consoleplayer == Net_Arbitrator && !demoplayback)
|
||||||
{
|
{
|
||||||
if (player->isbot)
|
if (player->Bot != NULL)
|
||||||
player->t_respawn = (pr_botrespawn()%15)+((bglobal.botnum-1)*2)+TICRATE+1;
|
player->Bot->t_respawn = (pr_botrespawn()%15)+((bglobal.botnum-1)*2)+TICRATE+1;
|
||||||
|
|
||||||
//Added by MC: Discard enemies.
|
//Added by MC: Discard enemies.
|
||||||
for (int i = 0; i < MAXPLAYERS; i++)
|
for (int i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (players[i].isbot && this == players[i].enemy)
|
if (players[i].Bot != NULL && this == players[i].Bot->enemy)
|
||||||
{
|
{
|
||||||
if (players[i].dest == players[i].enemy)
|
if (players[i].Bot->dest == players[i].Bot->enemy)
|
||||||
players[i].dest = NULL;
|
players[i].Bot->dest = NULL;
|
||||||
players[i].enemy = NULL;
|
players[i].Bot->enemy = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1193,11 +1193,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
|
||||||
//
|
//
|
||||||
if (player)
|
if (player)
|
||||||
{
|
{
|
||||||
|
//Added by MC: Lets bots look allround for enemies if they survive an ambush.
|
||||||
//Added by MC: Lets bots look allround for enemies if they survive an ambush.
|
if (player->Bot != NULL)
|
||||||
if (player->isbot)
|
|
||||||
{
|
{
|
||||||
player->allround = true;
|
player->Bot->allround = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of game hell hack
|
// end of game hell hack
|
||||||
|
@ -1210,8 +1209,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
|
||||||
if (!(flags & DMG_FORCED))
|
if (!(flags & DMG_FORCED))
|
||||||
{
|
{
|
||||||
// check the real player, not a voodoo doll here for invulnerability effects
|
// check the real player, not a voodoo doll here for invulnerability effects
|
||||||
if (damage < TELEFRAG_DAMAGE && ((player->mo->flags2 & MF2_INVULNERABLE) ||
|
if ((damage < TELEFRAG_DAMAGE && ((player->mo->flags2 & MF2_INVULNERABLE) ||
|
||||||
(player->cheats & CF_GODMODE)))
|
(player->cheats & CF_GODMODE))) ||
|
||||||
|
(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
|
{ // player is invulnerable, so don't hurt him
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1219,8 +1220,13 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
|
||||||
if (!(flags & DMG_NO_ARMOR) && player->mo->Inventory != NULL)
|
if (!(flags & DMG_NO_ARMOR) && player->mo->Inventory != NULL)
|
||||||
{
|
{
|
||||||
int newdam = damage;
|
int newdam = damage;
|
||||||
player->mo->Inventory->AbsorbDamage (damage, mod, newdam);
|
player->mo->Inventory->AbsorbDamage(damage, mod, newdam);
|
||||||
damage = newdam;
|
if (damage < TELEFRAG_DAMAGE)
|
||||||
|
{
|
||||||
|
// if we are telefragging don't let the damage value go below that magic value. Some further checks would fail otherwise.
|
||||||
|
damage = newdam;
|
||||||
|
}
|
||||||
|
|
||||||
if (damage <= 0)
|
if (damage <= 0)
|
||||||
{
|
{
|
||||||
// If MF6_FORCEPAIN is set, make the player enter the pain state.
|
// If MF6_FORCEPAIN is set, make the player enter the pain state.
|
||||||
|
@ -1233,7 +1239,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (damage >= player->health
|
if (damage >= player->health && damage < TELEFRAG_DAMAGE
|
||||||
&& (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch)
|
&& (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch)
|
||||||
&& !player->morphTics)
|
&& !player->morphTics)
|
||||||
{ // Try to use some inventory health
|
{ // Try to use some inventory health
|
||||||
|
@ -1255,9 +1261,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
|
||||||
// This does not save the player if damage >= TELEFRAG_DAMAGE, still need to
|
// This does not save the player if damage >= TELEFRAG_DAMAGE, still need to
|
||||||
// telefrag him right? ;) (Unfortunately the damage is "absorbed" by armor,
|
// telefrag him right? ;) (Unfortunately the damage is "absorbed" by armor,
|
||||||
// but telefragging should still do enough damage to kill the player)
|
// but telefragging should still do enough damage to kill the player)
|
||||||
if ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE
|
// Ignore players that are already dead.
|
||||||
// Ignore players that are already dead.
|
if (((player->cheats & CF_BUDDHA2) || ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE)) && player->playerstate != PST_DEAD)
|
||||||
&& player->playerstate != PST_DEAD)
|
|
||||||
{
|
{
|
||||||
// If this is a voodoo doll we need to handle the real player as well.
|
// If this is a voodoo doll we need to handle the real player as well.
|
||||||
player->mo->health = target->health = player->health = 1;
|
player->mo->health = target->health = player->health = 1;
|
||||||
|
@ -1317,43 +1322,52 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
|
||||||
|
|
||||||
|
|
||||||
if (target->health <= 0)
|
if (target->health <= 0)
|
||||||
{ // Death
|
{
|
||||||
target->special1 = damage;
|
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...
|
||||||
// use inflictor's death type if it got one.
|
target->health = 1;
|
||||||
if (inflictor && inflictor->DeathType != NAME_None) mod = inflictor->DeathType;
|
}
|
||||||
|
else
|
||||||
// check for special fire damage or ice damage deaths
|
|
||||||
if (mod == NAME_Fire)
|
|
||||||
{
|
{
|
||||||
if (player && !player->morphTics)
|
|
||||||
{ // Check for flame death
|
// Death
|
||||||
if (!inflictor ||
|
target->special1 = damage;
|
||||||
((target->health > -50) && (damage > 25)) ||
|
|
||||||
!(inflictor->flags5 & MF5_SPECIALFIREDAMAGE))
|
// use inflictor's death type if it got one.
|
||||||
|
if (inflictor && inflictor->DeathType != NAME_None) mod = inflictor->DeathType;
|
||||||
|
|
||||||
|
// check for special fire damage or ice damage deaths
|
||||||
|
if (mod == NAME_Fire)
|
||||||
|
{
|
||||||
|
if (player && !player->morphTics)
|
||||||
|
{ // Check for flame death
|
||||||
|
if (!inflictor ||
|
||||||
|
((target->health > -50) && (damage > 25)) ||
|
||||||
|
!(inflictor->flags5 & MF5_SPECIALFIREDAMAGE))
|
||||||
|
{
|
||||||
|
target->DamageType = NAME_Fire;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
target->DamageType = NAME_Fire;
|
target->DamageType = NAME_Fire;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
target->DamageType = NAME_Fire;
|
target->DamageType = mod;
|
||||||
}
|
}
|
||||||
}
|
if (source && source->tracer && (source->flags5 & MF5_SUMMONEDMONSTER))
|
||||||
else
|
{ // Minotaur's kills go to his master
|
||||||
{
|
// Make sure still alive and not a pointer to fighter head
|
||||||
target->DamageType = mod;
|
if (source->tracer->player && (source->tracer->player->mo == source->tracer))
|
||||||
}
|
{
|
||||||
if (source && source->tracer && (source->flags5 & MF5_SUMMONEDMONSTER))
|
source = source->tracer;
|
||||||
{ // Minotaur's kills go to his master
|
}
|
||||||
// Make sure still alive and not a pointer to fighter head
|
|
||||||
if (source->tracer->player && (source->tracer->player->mo == source->tracer))
|
|
||||||
{
|
|
||||||
source = source->tracer;
|
|
||||||
}
|
}
|
||||||
|
target->Die (source, inflictor, flags);
|
||||||
|
return damage;
|
||||||
}
|
}
|
||||||
target->Die (source, inflictor, flags);
|
|
||||||
return damage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
woundstate = target->FindState(NAME_Wound, mod);
|
woundstate = target->FindState(NAME_Wound, mod);
|
||||||
|
@ -1673,7 +1687,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage,
|
||||||
target->health -= damage;
|
target->health -= damage;
|
||||||
if (target->health <= 0)
|
if (target->health <= 0)
|
||||||
{ // Death
|
{ // Death
|
||||||
if (player->cheats & CF_BUDDHA)
|
if ((player->cheats & CF_BUDDHA && damage < TELEFRAG_DAMAGE) || (player->cheats & CF_BUDDHA2))
|
||||||
{ // [SP] Save the player...
|
{ // [SP] Save the player...
|
||||||
player->health = target->health = 1;
|
player->health = target->health = 1;
|
||||||
}
|
}
|
||||||
|
@ -1711,7 +1725,6 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage,
|
||||||
P_SetMobjState(target, target->info->painstate);
|
P_SetMobjState(target, target->info->painstate);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -281,43 +281,43 @@ FUNC(LS_Generic_Door)
|
||||||
FUNC(LS_Floor_LowerByValue)
|
FUNC(LS_Floor_LowerByValue)
|
||||||
// Floor_LowerByValue (tag, speed, height)
|
// Floor_LowerByValue (tag, speed, height)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, 0, 0, false);
|
return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_LowerToLowest)
|
FUNC(LS_Floor_LowerToLowest)
|
||||||
// Floor_LowerToLowest (tag, speed)
|
// Floor_LowerToLowest (tag, speed)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, 0, 0, false);
|
return EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_LowerToHighest)
|
FUNC(LS_Floor_LowerToHighest)
|
||||||
// Floor_LowerToHighest (tag, speed, adjust, hereticlower)
|
// Floor_LowerToHighest (tag, speed, adjust, hereticlower)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorLowerToHighest, ln, arg0, SPEED(arg1), (arg2-128)*FRACUNIT, 0, 0, false, arg3==1);
|
return EV_DoFloor (DFloor::floorLowerToHighest, ln, arg0, SPEED(arg1), (arg2-128)*FRACUNIT, -1, 0, false, arg3==1);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_LowerToNearest)
|
FUNC(LS_Floor_LowerToNearest)
|
||||||
// Floor_LowerToNearest (tag, speed)
|
// Floor_LowerToNearest (tag, speed)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorLowerToNearest, ln, arg0, SPEED(arg1), 0, 0, 0, false);
|
return EV_DoFloor (DFloor::floorLowerToNearest, ln, arg0, SPEED(arg1), 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseByValue)
|
FUNC(LS_Floor_RaiseByValue)
|
||||||
// Floor_RaiseByValue (tag, speed, height)
|
// Floor_RaiseByValue (tag, speed, height)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseToHighest)
|
FUNC(LS_Floor_RaiseToHighest)
|
||||||
// Floor_RaiseToHighest (tag, speed)
|
// Floor_RaiseToHighest (tag, speed)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseToHighest, ln, arg0, SPEED(arg1), 0, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseToHighest, ln, arg0, SPEED(arg1), 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseToNearest)
|
FUNC(LS_Floor_RaiseToNearest)
|
||||||
// Floor_RaiseToNearest (tag, speed)
|
// Floor_RaiseToNearest (tag, speed)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseToNearest, ln, arg0, SPEED(arg1), 0, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseToNearest, ln, arg0, SPEED(arg1), 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseAndCrush)
|
FUNC(LS_Floor_RaiseAndCrush)
|
||||||
|
@ -335,13 +335,13 @@ FUNC(LS_Floor_RaiseAndCrushDoom)
|
||||||
FUNC(LS_Floor_RaiseByValueTimes8)
|
FUNC(LS_Floor_RaiseByValueTimes8)
|
||||||
// FLoor_RaiseByValueTimes8 (tag, speed, height)
|
// FLoor_RaiseByValueTimes8 (tag, speed, height)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_LowerByValueTimes8)
|
FUNC(LS_Floor_LowerByValueTimes8)
|
||||||
// Floor_LowerByValueTimes8 (tag, speed, height)
|
// Floor_LowerByValueTimes8 (tag, speed, height)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, 0, 0, false);
|
return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_CrushStop)
|
FUNC(LS_Floor_CrushStop)
|
||||||
|
@ -353,51 +353,51 @@ FUNC(LS_Floor_CrushStop)
|
||||||
FUNC(LS_Floor_LowerInstant)
|
FUNC(LS_Floor_LowerInstant)
|
||||||
// Floor_LowerInstant (tag, unused, height)
|
// Floor_LowerInstant (tag, unused, height)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorLowerInstant, ln, arg0, 0, arg2*FRACUNIT*8, 0, 0, false);
|
return EV_DoFloor (DFloor::floorLowerInstant, ln, arg0, 0, arg2*FRACUNIT*8, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseInstant)
|
FUNC(LS_Floor_RaiseInstant)
|
||||||
// Floor_RaiseInstant (tag, unused, height)
|
// Floor_RaiseInstant (tag, unused, height)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseInstant, ln, arg0, 0, arg2*FRACUNIT*8, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseInstant, ln, arg0, 0, arg2*FRACUNIT*8, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_MoveToValueTimes8)
|
FUNC(LS_Floor_MoveToValueTimes8)
|
||||||
// Floor_MoveToValueTimes8 (tag, speed, height, negative)
|
// Floor_MoveToValueTimes8 (tag, speed, height, negative)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorMoveToValue, ln, arg0, SPEED(arg1),
|
return EV_DoFloor (DFloor::floorMoveToValue, ln, arg0, SPEED(arg1),
|
||||||
arg2*FRACUNIT*8*(arg3?-1:1), 0, 0, false);
|
arg2*FRACUNIT*8*(arg3?-1:1), -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_MoveToValue)
|
FUNC(LS_Floor_MoveToValue)
|
||||||
// Floor_MoveToValue (tag, speed, height, negative)
|
// Floor_MoveToValue (tag, speed, height, negative)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorMoveToValue, ln, arg0, SPEED(arg1),
|
return EV_DoFloor (DFloor::floorMoveToValue, ln, arg0, SPEED(arg1),
|
||||||
arg2*FRACUNIT*(arg3?-1:1), 0, 0, false);
|
arg2*FRACUNIT*(arg3?-1:1), -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseToLowestCeiling)
|
FUNC(LS_Floor_RaiseToLowestCeiling)
|
||||||
// Floor_RaiseToLowestCeiling (tag, speed)
|
// Floor_RaiseToLowestCeiling (tag, speed)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseToLowestCeiling, ln, arg0, SPEED(arg1), 0, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseToLowestCeiling, ln, arg0, SPEED(arg1), 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseByTexture)
|
FUNC(LS_Floor_RaiseByTexture)
|
||||||
// Floor_RaiseByTexture (tag, speed)
|
// Floor_RaiseByTexture (tag, speed)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseByTexture, ln, arg0, SPEED(arg1), 0, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseByTexture, ln, arg0, SPEED(arg1), 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_RaiseByValueTxTy)
|
FUNC(LS_Floor_RaiseByValueTxTy)
|
||||||
// Floor_RaiseByValueTxTy (tag, speed, height)
|
// Floor_RaiseByValueTxTy (tag, speed, height)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorRaiseAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, 0, 0, false);
|
return EV_DoFloor (DFloor::floorRaiseAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_LowerToLowestTxTy)
|
FUNC(LS_Floor_LowerToLowestTxTy)
|
||||||
// Floor_LowerToLowestTxTy (tag, speed)
|
// Floor_LowerToLowestTxTy (tag, speed)
|
||||||
{
|
{
|
||||||
return EV_DoFloor (DFloor::floorLowerAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, 0, 0, false);
|
return EV_DoFloor (DFloor::floorLowerAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, -1, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNC(LS_Floor_Waggle)
|
FUNC(LS_Floor_Waggle)
|
||||||
|
@ -1764,7 +1764,7 @@ FUNC(LS_FloorAndCeiling_LowerRaise)
|
||||||
// more or less unintuitive value for the fourth arg to trigger Boom's broken behavior
|
// more or less unintuitive value for the fourth arg to trigger Boom's broken behavior
|
||||||
if (arg3 != 1998 || !res) // (1998 for the year in which Boom was released... :P)
|
if (arg3 != 1998 || !res) // (1998 for the year in which Boom was released... :P)
|
||||||
{
|
{
|
||||||
res |= EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, 0, 0, false);
|
res |= EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, -1, 0, false);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -559,6 +559,7 @@ enum EDmgFlags
|
||||||
DMG_NO_FACTOR = 16,
|
DMG_NO_FACTOR = 16,
|
||||||
DMG_PLAYERATTACK = 32,
|
DMG_PLAYERATTACK = 32,
|
||||||
DMG_FOILINVUL = 64,
|
DMG_FOILINVUL = 64,
|
||||||
|
DMG_FOILBUDDHA = 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags)
|
||||||
|
|
||||||
if (ff_top > tmf.floorz)
|
if (ff_top > tmf.floorz)
|
||||||
{
|
{
|
||||||
if (ff_top <= tmf.z || (!(flags && FFCF_3DRESTRICT) && (tmf.thing != NULL && ff_bottom < tmf.z && ff_top < tmf.z + tmf.thing->MaxStepHeight)))
|
if (ff_top <= tmf.z || (!(flags & FFCF_3DRESTRICT) && (tmf.thing != NULL && ff_bottom < tmf.z && ff_top < tmf.z + tmf.thing->MaxStepHeight)))
|
||||||
{
|
{
|
||||||
tmf.dropoffz = tmf.floorz = ff_top;
|
tmf.dropoffz = tmf.floorz = ff_top;
|
||||||
tmf.floorpic = *rover->top.texture;
|
tmf.floorpic = *rover->top.texture;
|
||||||
|
@ -1111,24 +1111,27 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm)
|
||||||
// cases where they are clearly supposed to do that
|
// cases where they are clearly supposed to do that
|
||||||
if (thing->IsFriend(tm.thing->target))
|
if (thing->IsFriend(tm.thing->target))
|
||||||
{
|
{
|
||||||
// Friends never harm each other
|
// Friends never harm each other, unless the shooter has the HARMFRIENDS set.
|
||||||
return false;
|
if (!(thing->flags7 & MF7_HARMFRIENDS)) return false;
|
||||||
}
|
}
|
||||||
if (thing->TIDtoHate != 0 && thing->TIDtoHate == tm.thing->target->TIDtoHate)
|
else
|
||||||
{
|
{
|
||||||
// [RH] Don't hurt monsters that hate the same thing as you do
|
if (thing->TIDtoHate != 0 && thing->TIDtoHate == tm.thing->target->TIDtoHate)
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (thing->GetSpecies() == tm.thing->target->GetSpecies() && !(thing->flags6 & MF6_DOHARMSPECIES))
|
|
||||||
{
|
|
||||||
// Don't hurt same species or any relative -
|
|
||||||
// but only if the target isn't one's hostile.
|
|
||||||
if (!thing->IsHostile(tm.thing->target))
|
|
||||||
{
|
{
|
||||||
// Allow hurting monsters the shooter hates.
|
// [RH] Don't hurt monsters that hate the same thing as you do
|
||||||
if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid)
|
return false;
|
||||||
|
}
|
||||||
|
if (thing->GetSpecies() == tm.thing->target->GetSpecies() && !(thing->flags6 & MF6_DOHARMSPECIES))
|
||||||
|
{
|
||||||
|
// Don't hurt same species or any relative -
|
||||||
|
// but only if the target isn't one's hostile.
|
||||||
|
if (!thing->IsHostile(tm.thing->target))
|
||||||
{
|
{
|
||||||
return false;
|
// Allow hurting monsters the shooter hates.
|
||||||
|
if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1919,13 +1922,13 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
}
|
}
|
||||||
|
|
||||||
//Added by MC: To prevent bot from getting into dangerous sectors.
|
//Added by MC: To prevent bot from getting into dangerous sectors.
|
||||||
if (thing->player && thing->player->isbot && thing->flags & MF_SHOOTABLE)
|
if (thing->player && thing->player->Bot != NULL && thing->flags & MF_SHOOTABLE)
|
||||||
{
|
{
|
||||||
if (tm.sector != thing->Sector
|
if (tm.sector != thing->Sector
|
||||||
&& bglobal.IsDangerous(tm.sector))
|
&& bglobal.IsDangerous(tm.sector))
|
||||||
{
|
{
|
||||||
thing->player->prev = thing->player->dest;
|
thing->player->Bot->prev = thing->player->Bot->dest;
|
||||||
thing->player->dest = NULL;
|
thing->player->Bot->dest = NULL;
|
||||||
thing->velx = 0;
|
thing->velx = 0;
|
||||||
thing->vely = 0;
|
thing->vely = 0;
|
||||||
thing->z = oldz;
|
thing->z = oldz;
|
||||||
|
@ -2157,7 +2160,7 @@ bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y)
|
||||||
{ // too big a step up
|
{ // too big a step up
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if ((thing->flags & MF_MISSILE) && !(thing->flags6 && MF6_STEPMISSILE) && tm.floorz > newz)
|
else if ((thing->flags & MF_MISSILE) && !(thing->flags6 & MF6_STEPMISSILE) && tm.floorz > newz)
|
||||||
{ // [RH] Don't let normal missiles climb steps
|
{ // [RH] Don't let normal missiles climb steps
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1199,12 +1199,6 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
||||||
if (nextstate == NULL) nextstate = mo->FindState(NAME_Death, NAME_Extreme);
|
if (nextstate == NULL) nextstate = mo->FindState(NAME_Death, NAME_Extreme);
|
||||||
}
|
}
|
||||||
if (nextstate == NULL) nextstate = mo->FindState(NAME_Death);
|
if (nextstate == NULL) nextstate = mo->FindState(NAME_Death);
|
||||||
mo->SetState (nextstate);
|
|
||||||
|
|
||||||
if (mo->ObjectFlags & OF_EuthanizeMe)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line != NULL && line->special == Line_Horizon && !(mo->flags3 & MF3_SKYEXPLODE))
|
if (line != NULL && line->special == Line_Horizon && !(mo->flags3 & MF3_SKYEXPLODE))
|
||||||
{
|
{
|
||||||
|
@ -1280,8 +1274,17 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextstate != NULL)
|
// play the sound before changing the state, so that AActor::Destroy can call S_RelinkSounds on it and the death state can override it.
|
||||||
|
if (mo->DeathSound)
|
||||||
{
|
{
|
||||||
|
S_Sound (mo, CHAN_VOICE, mo->DeathSound, 1,
|
||||||
|
(mo->flags3 & MF3_FULLVOLDEATH) ? ATTN_NONE : ATTN_NORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
mo->SetState (nextstate);
|
||||||
|
if (!(mo->ObjectFlags & OF_EuthanizeMe))
|
||||||
|
{
|
||||||
|
// The rest only applies if the missile actor still exists.
|
||||||
// [RH] Change render style of exploding rockets
|
// [RH] Change render style of exploding rockets
|
||||||
if (mo->flags5 & MF5_DEHEXPLOSION)
|
if (mo->flags5 & MF5_DEHEXPLOSION)
|
||||||
{
|
{
|
||||||
|
@ -1314,11 +1317,6 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
||||||
|
|
||||||
mo->flags &= ~MF_MISSILE;
|
mo->flags &= ~MF_MISSILE;
|
||||||
|
|
||||||
if (mo->DeathSound)
|
|
||||||
{
|
|
||||||
S_Sound (mo, CHAN_VOICE, mo->DeathSound, 1,
|
|
||||||
(mo->flags3 & MF3_FULLVOLDEATH) ? ATTN_NONE : ATTN_NORM);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3116,7 +3114,7 @@ void AActor::Tick ()
|
||||||
special2++;
|
special2++;
|
||||||
}
|
}
|
||||||
//Added by MC: Freeze mode.
|
//Added by MC: Freeze mode.
|
||||||
if (bglobal.freeze && !(player && !player->isbot))
|
if (bglobal.freeze && !(player && player->Bot == NULL))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3237,18 +3235,18 @@ void AActor::Tick ()
|
||||||
bglobal.m_Thinking = true;
|
bglobal.m_Thinking = true;
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
if (!playeringame[i] || !players[i].isbot)
|
if (!playeringame[i] || players[i].Bot == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (flags3 & MF3_ISMONSTER)
|
if (flags3 & MF3_ISMONSTER)
|
||||||
{
|
{
|
||||||
if (health > 0
|
if (health > 0
|
||||||
&& !players[i].enemy
|
&& !players[i].Bot->enemy
|
||||||
&& player ? !IsTeammate (players[i].mo) : true
|
&& player ? !IsTeammate (players[i].mo) : true
|
||||||
&& P_AproxDistance (players[i].mo->x-x, players[i].mo->y-y) < MAX_MONSTER_TARGET_DIST
|
&& P_AproxDistance (players[i].mo->x-x, players[i].mo->y-y) < MAX_MONSTER_TARGET_DIST
|
||||||
&& P_CheckSight (players[i].mo, this, SF_SEEPASTBLOCKEVERYTHING))
|
&& P_CheckSight (players[i].mo, this, SF_SEEPASTBLOCKEVERYTHING))
|
||||||
{ //Probably a monster, so go kill it.
|
{ //Probably a monster, so go kill it.
|
||||||
players[i].enemy = this;
|
players[i].Bot->enemy = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (flags & MF_SPECIAL)
|
else if (flags & MF_SPECIAL)
|
||||||
|
@ -3260,10 +3258,10 @@ void AActor::Tick ()
|
||||||
}
|
}
|
||||||
else if (flags & MF_MISSILE)
|
else if (flags & MF_MISSILE)
|
||||||
{
|
{
|
||||||
if (!players[i].missile && (flags3 & MF3_WARNBOT))
|
if (!players[i].Bot->missile && (flags3 & MF3_WARNBOT))
|
||||||
{ //warn for incoming missiles.
|
{ //warn for incoming missiles.
|
||||||
if (target != players[i].mo && bglobal.Check_LOS (players[i].mo, this, ANGLE_90))
|
if (target != players[i].mo && bglobal.Check_LOS (players[i].mo, this, ANGLE_90))
|
||||||
players[i].missile = this;
|
players[i].Bot->missile = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5018,10 +5016,11 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc
|
||||||
cls = cls->ParentClass;
|
cls = cls->ParentClass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statedone:
|
||||||
|
if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
statedone:
|
|
||||||
if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE;
|
|
||||||
if (bloodtype >= 1)
|
if (bloodtype >= 1)
|
||||||
P_DrawSplash2 (40, x, y, z, dir, 2, bloodcolor);
|
P_DrawSplash2 (40, x, y, z, dir, 2, bloodcolor);
|
||||||
}
|
}
|
||||||
|
@ -5857,22 +5856,41 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AActor::GetTeam()
|
||||||
|
{
|
||||||
|
if (player)
|
||||||
|
{
|
||||||
|
return player->userinfo.GetTeam();
|
||||||
|
}
|
||||||
|
|
||||||
|
int myTeam = DesignatedTeam;
|
||||||
|
|
||||||
|
// Check for monsters that belong to a player on the team but aren't part of the team themselves.
|
||||||
|
if (myTeam == TEAM_NONE && FriendPlayer != 0)
|
||||||
|
{
|
||||||
|
myTeam = players[FriendPlayer - 1].userinfo.GetTeam();
|
||||||
|
}
|
||||||
|
return myTeam;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool AActor::IsTeammate (AActor *other)
|
bool AActor::IsTeammate (AActor *other)
|
||||||
{
|
{
|
||||||
if (!other)
|
if (!other)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
else if (!deathmatch && player && other->player)
|
else if (!deathmatch && player && other->player)
|
||||||
return true;
|
|
||||||
int myTeam = DesignatedTeam;
|
|
||||||
int otherTeam = other->DesignatedTeam;
|
|
||||||
if (player)
|
|
||||||
myTeam = player->userinfo.GetTeam();
|
|
||||||
if (other->player)
|
|
||||||
otherTeam = other->player->userinfo.GetTeam();
|
|
||||||
if (teamplay && myTeam != TEAM_NONE && myTeam == otherTeam)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (teamplay)
|
||||||
|
{
|
||||||
|
int myTeam = GetTeam();
|
||||||
|
int otherTeam = other->GetTeam();
|
||||||
|
|
||||||
|
return (myTeam != TEAM_NONE && myTeam == otherTeam);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ void P_FireWeapon (player_t *player, FState *state)
|
||||||
|
|
||||||
// [SO] 9/2/02: People were able to do an awful lot of damage
|
// [SO] 9/2/02: People were able to do an awful lot of damage
|
||||||
// when they were observers...
|
// when they were observers...
|
||||||
if (!player->isbot && bot_observer)
|
if (player->Bot == NULL && bot_observer)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ void P_FireWeaponAlt (player_t *player, FState *state)
|
||||||
|
|
||||||
// [SO] 9/2/02: People were able to do an awful lot of damage
|
// [SO] 9/2/02: People were able to do an awful lot of damage
|
||||||
// when they were observers...
|
// when they were observers...
|
||||||
if (!player->isbot && bot_observer)
|
if (player->Bot == NULL && bot_observer)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -298,7 +298,7 @@ void P_FireWeaponAlt (player_t *player, FState *state)
|
||||||
void P_ReloadWeapon (player_t *player, FState *state)
|
void P_ReloadWeapon (player_t *player, FState *state)
|
||||||
{
|
{
|
||||||
AWeapon *weapon;
|
AWeapon *weapon;
|
||||||
if (!player->isbot && bot_observer)
|
if (player->Bot == NULL && bot_observer)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ void P_ReloadWeapon (player_t *player, FState *state)
|
||||||
void P_ZoomWeapon (player_t *player, FState *state)
|
void P_ZoomWeapon (player_t *player, FState *state)
|
||||||
{
|
{
|
||||||
AWeapon *weapon;
|
AWeapon *weapon;
|
||||||
if (!player->isbot && bot_observer)
|
if (player->Bot == NULL && bot_observer)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,7 +271,7 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name)
|
||||||
|
|
||||||
dst->cheats |= chasecam;
|
dst->cheats |= chasecam;
|
||||||
|
|
||||||
if (dst->isbot)
|
if (dst->Bot != NULL)
|
||||||
{
|
{
|
||||||
botinfo_t *thebot = bglobal.botinfo;
|
botinfo_t *thebot = bglobal.botinfo;
|
||||||
while (thebot && stricmp (name, thebot->name))
|
while (thebot && stricmp (name, thebot->name))
|
||||||
|
@ -283,7 +283,6 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name)
|
||||||
thebot->inuse = true;
|
thebot->inuse = true;
|
||||||
}
|
}
|
||||||
bglobal.botnum++;
|
bglobal.botnum++;
|
||||||
bglobal.botingame[dst - players] = true;
|
|
||||||
dst->userinfo.TransferFrom(uibackup2);
|
dst->userinfo.TransferFrom(uibackup2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -4175,6 +4175,7 @@ static void P_Shutdown ()
|
||||||
P_FreeLevelData ();
|
P_FreeLevelData ();
|
||||||
P_FreeExtraLevelData ();
|
P_FreeExtraLevelData ();
|
||||||
ST_Clear();
|
ST_Clear();
|
||||||
|
bglobal.DestroyAllBots ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
#include "v_text.h"
|
||||||
#include "thingdef/thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
// Each state is owned by an actor. Actors can own any number of
|
// Each state is owned by an actor. Actors can own any number of
|
||||||
|
@ -699,6 +700,10 @@ FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, const PClass *mytype
|
||||||
{
|
{
|
||||||
I_Error ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
|
I_Error ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf (TEXTCOLOR_RED "Attempt to get invalid state %s from actor %s.\n", label, type->TypeName.GetChars());
|
||||||
|
}
|
||||||
delete[] namestart; // free the allocated string buffer
|
delete[] namestart; // free the allocated string buffer
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ void P_Ticker (void)
|
||||||
|
|
||||||
for (i = 0; i<MAXPLAYERS; i++)
|
for (i = 0; i<MAXPLAYERS; i++)
|
||||||
if (playeringame[i] &&
|
if (playeringame[i] &&
|
||||||
/*Added by MC: Freeze mode.*/!(bglobal.freeze && players[i].isbot))
|
/*Added by MC: Freeze mode.*/!(bglobal.freeze && players[i].Bot != NULL))
|
||||||
P_PlayerThink (&players[i]);
|
P_PlayerThink (&players[i]);
|
||||||
|
|
||||||
StatusBar->Tick (); // [RH] moved this here
|
StatusBar->Tick (); // [RH] moved this here
|
||||||
|
|
|
@ -366,7 +366,7 @@ bool FTraceInfo::TraceTraverse (int ptflags)
|
||||||
Results->HitTexture = CurSector->GetTexture(sector_t::ceiling);
|
Results->HitTexture = CurSector->GetTexture(sector_t::ceiling);
|
||||||
}
|
}
|
||||||
else if (entersector == NULL ||
|
else if (entersector == NULL ||
|
||||||
hitz <= bf || hitz >= bc ||
|
hitz < bf || hitz > bc ||
|
||||||
in->d.line->flags & WallMask)
|
in->d.line->flags & WallMask)
|
||||||
{ // hit the wall
|
{ // hit the wall
|
||||||
Results->HitType = TRACE_HitWall;
|
Results->HitType = TRACE_HitWall;
|
||||||
|
|
134
src/p_user.cpp
134
src/p_user.cpp
|
@ -293,28 +293,7 @@ player_t::player_t()
|
||||||
respawn_time(0),
|
respawn_time(0),
|
||||||
camera(0),
|
camera(0),
|
||||||
air_finished(0),
|
air_finished(0),
|
||||||
savedyaw(0),
|
Bot(0),
|
||||||
savedpitch(0),
|
|
||||||
angle(0),
|
|
||||||
dest(0),
|
|
||||||
prev(0),
|
|
||||||
enemy(0),
|
|
||||||
missile(0),
|
|
||||||
mate(0),
|
|
||||||
last_mate(0),
|
|
||||||
t_active(0),
|
|
||||||
t_respawn(0),
|
|
||||||
t_strafe(0),
|
|
||||||
t_react(0),
|
|
||||||
t_fight(0),
|
|
||||||
t_roam(0),
|
|
||||||
t_rocket(0),
|
|
||||||
isbot(0),
|
|
||||||
first_shot(0),
|
|
||||||
sleft(0),
|
|
||||||
allround(0),
|
|
||||||
oldx(0),
|
|
||||||
oldy(0),
|
|
||||||
BlendR(0),
|
BlendR(0),
|
||||||
BlendG(0),
|
BlendG(0),
|
||||||
BlendB(0),
|
BlendB(0),
|
||||||
|
@ -333,7 +312,6 @@ player_t::player_t()
|
||||||
memset (&cmd, 0, sizeof(cmd));
|
memset (&cmd, 0, sizeof(cmd));
|
||||||
memset (frags, 0, sizeof(frags));
|
memset (frags, 0, sizeof(frags));
|
||||||
memset (psprites, 0, sizeof(psprites));
|
memset (psprites, 0, sizeof(psprites));
|
||||||
memset (&skill, 0, sizeof(skill));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
player_t &player_t::operator=(const player_t &p)
|
player_t &player_t::operator=(const player_t &p)
|
||||||
|
@ -401,30 +379,8 @@ player_t &player_t::operator=(const player_t &p)
|
||||||
camera = p.camera;
|
camera = p.camera;
|
||||||
air_finished = p.air_finished;
|
air_finished = p.air_finished;
|
||||||
LastDamageType = p.LastDamageType;
|
LastDamageType = p.LastDamageType;
|
||||||
savedyaw = p.savedyaw;
|
Bot = p.Bot;
|
||||||
savedpitch = p.savedpitch;
|
|
||||||
angle = p.angle;
|
|
||||||
dest = p.dest;
|
|
||||||
prev = p.prev;
|
|
||||||
enemy = p.enemy;
|
|
||||||
missile = p.missile;
|
|
||||||
mate = p.mate;
|
|
||||||
last_mate = p.last_mate;
|
|
||||||
settings_controller = p.settings_controller;
|
settings_controller = p.settings_controller;
|
||||||
skill = p.skill;
|
|
||||||
t_active = p.t_active;
|
|
||||||
t_respawn = p.t_respawn;
|
|
||||||
t_strafe = p.t_strafe;
|
|
||||||
t_react = p.t_react;
|
|
||||||
t_fight = p.t_fight;
|
|
||||||
t_roam = p.t_roam;
|
|
||||||
t_rocket = p.t_rocket;
|
|
||||||
isbot = p.isbot;
|
|
||||||
first_shot = p.first_shot;
|
|
||||||
sleft = p.sleft;
|
|
||||||
allround = p.allround;
|
|
||||||
oldx = p.oldx;
|
|
||||||
oldy = p.oldy;
|
|
||||||
BlendR = p.BlendR;
|
BlendR = p.BlendR;
|
||||||
BlendG = p.BlendG;
|
BlendG = p.BlendG;
|
||||||
BlendB = p.BlendB;
|
BlendB = p.BlendB;
|
||||||
|
@ -466,12 +422,7 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep)
|
||||||
if (*&poisoner == old) poisoner = replacement, changed++;
|
if (*&poisoner == old) poisoner = replacement, changed++;
|
||||||
if (*&attacker == old) attacker = replacement, changed++;
|
if (*&attacker == old) attacker = replacement, changed++;
|
||||||
if (*&camera == old) camera = replacement, changed++;
|
if (*&camera == old) camera = replacement, changed++;
|
||||||
if (*&dest == old) dest = replacement, changed++;
|
if (*&Bot == old) Bot = static_cast<DBot *>(rep), changed++;
|
||||||
if (*&prev == old) prev = replacement, changed++;
|
|
||||||
if (*&enemy == old) enemy = replacement, changed++;
|
|
||||||
if (*&missile == old) missile = replacement, changed++;
|
|
||||||
if (*&mate == old) mate = replacement, changed++;
|
|
||||||
if (*&last_mate == old) last_mate = replacement, changed++;
|
|
||||||
if (ReadyWeapon == old) ReadyWeapon = static_cast<AWeapon *>(rep), changed++;
|
if (ReadyWeapon == old) ReadyWeapon = static_cast<AWeapon *>(rep), changed++;
|
||||||
if (PendingWeapon == old) PendingWeapon = static_cast<AWeapon *>(rep), changed++;
|
if (PendingWeapon == old) PendingWeapon = static_cast<AWeapon *>(rep), changed++;
|
||||||
if (*&PremorphWeapon == old) PremorphWeapon = static_cast<AWeapon *>(rep), changed++;
|
if (*&PremorphWeapon == old) PremorphWeapon = static_cast<AWeapon *>(rep), changed++;
|
||||||
|
@ -486,12 +437,7 @@ size_t player_t::PropagateMark()
|
||||||
GC::Mark(poisoner);
|
GC::Mark(poisoner);
|
||||||
GC::Mark(attacker);
|
GC::Mark(attacker);
|
||||||
GC::Mark(camera);
|
GC::Mark(camera);
|
||||||
GC::Mark(dest);
|
GC::Mark(Bot);
|
||||||
GC::Mark(prev);
|
|
||||||
GC::Mark(enemy);
|
|
||||||
GC::Mark(missile);
|
|
||||||
GC::Mark(mate);
|
|
||||||
GC::Mark(last_mate);
|
|
||||||
GC::Mark(ReadyWeapon);
|
GC::Mark(ReadyWeapon);
|
||||||
GC::Mark(ConversationNPC);
|
GC::Mark(ConversationNPC);
|
||||||
GC::Mark(ConversationPC);
|
GC::Mark(ConversationPC);
|
||||||
|
@ -740,10 +686,10 @@ void APlayerPawn::SetupWeaponSlots()
|
||||||
// If we're the local player, then there's a bit more work to do.
|
// If we're the local player, then there's a bit more work to do.
|
||||||
// This also applies if we're a bot and this is the net arbitrator.
|
// This also applies if we're a bot and this is the net arbitrator.
|
||||||
if (player - players == consoleplayer ||
|
if (player - players == consoleplayer ||
|
||||||
(player->isbot && consoleplayer == Net_Arbitrator))
|
(player->Bot != NULL && consoleplayer == Net_Arbitrator))
|
||||||
{
|
{
|
||||||
FWeaponSlots local_slots(player->weapons);
|
FWeaponSlots local_slots(player->weapons);
|
||||||
if (player->isbot)
|
if (player->Bot != NULL)
|
||||||
{ // Bots only need weapons from KEYCONF, not INI modifications.
|
{ // Bots only need weapons from KEYCONF, not INI modifications.
|
||||||
P_PlaybackKeyConfWeapons(&local_slots);
|
P_PlaybackKeyConfWeapons(&local_slots);
|
||||||
}
|
}
|
||||||
|
@ -1257,9 +1203,6 @@ void APlayerPawn::GiveDefaultInventory ()
|
||||||
{
|
{
|
||||||
if (player == NULL) return;
|
if (player == NULL) return;
|
||||||
|
|
||||||
// [GRB] Give inventory specified in DECORATE
|
|
||||||
player->health = GetDefault ()->health;
|
|
||||||
|
|
||||||
// HexenArmor must always be the first item in the inventory because
|
// HexenArmor must always be the first item in the inventory because
|
||||||
// it provides player class based protection that should not affect
|
// it provides player class based protection that should not affect
|
||||||
// any other protection item.
|
// any other protection item.
|
||||||
|
@ -2175,7 +2118,7 @@ void P_DeathThink (player_t *player)
|
||||||
if ((player->cmd.ucmd.buttons & BT_USE ||
|
if ((player->cmd.ucmd.buttons & BT_USE ||
|
||||||
((multiplayer || alwaysapplydmflags) && (dmflags & DF_FORCE_RESPAWN))) && !(dmflags2 & DF2_NO_RESPAWN))
|
((multiplayer || alwaysapplydmflags) && (dmflags & DF_FORCE_RESPAWN))) && !(dmflags2 & DF2_NO_RESPAWN))
|
||||||
{
|
{
|
||||||
if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && !player->isbot))
|
if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && player->Bot == NULL))
|
||||||
{
|
{
|
||||||
player->cls = NULL; // Force a new class if the player is using a random class
|
player->cls = NULL; // Force a new class if the player is using a random class
|
||||||
player->playerstate = (multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) ? PST_REBORN : PST_ENTER;
|
player->playerstate = (multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) ? PST_REBORN : PST_ENTER;
|
||||||
|
@ -3007,9 +2950,17 @@ void player_t::Serialize (FArchive &arc)
|
||||||
<< respawn_time
|
<< respawn_time
|
||||||
<< air_finished
|
<< air_finished
|
||||||
<< turnticks
|
<< turnticks
|
||||||
<< oldbuttons
|
<< oldbuttons;
|
||||||
<< isbot
|
bool IsBot;
|
||||||
<< BlendR
|
if (SaveVersion >= 4514)
|
||||||
|
{
|
||||||
|
arc << Bot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arc << IsBot;
|
||||||
|
}
|
||||||
|
arc << BlendR
|
||||||
<< BlendG
|
<< BlendG
|
||||||
<< BlendB
|
<< BlendB
|
||||||
<< BlendA;
|
<< BlendA;
|
||||||
|
@ -3092,32 +3043,31 @@ void player_t::Serialize (FArchive &arc)
|
||||||
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (cheats & CF_NOCLIP2);
|
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (cheats & CF_NOCLIP2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isbot)
|
if (SaveVersion < 4514 && IsBot)
|
||||||
{
|
{
|
||||||
arc << angle
|
Bot = new DBot;
|
||||||
<< dest
|
GC::WriteBarrier (Bot);
|
||||||
<< prev
|
|
||||||
<< enemy
|
arc << Bot->angle
|
||||||
<< missile
|
<< Bot->dest
|
||||||
<< mate
|
<< Bot->prev
|
||||||
<< last_mate
|
<< Bot->enemy
|
||||||
<< skill
|
<< Bot->missile
|
||||||
<< t_active
|
<< Bot->mate
|
||||||
<< t_respawn
|
<< Bot->last_mate
|
||||||
<< t_strafe
|
<< Bot->skill
|
||||||
<< t_react
|
<< Bot->t_active
|
||||||
<< t_fight
|
<< Bot->t_respawn
|
||||||
<< t_roam
|
<< Bot->t_strafe
|
||||||
<< t_rocket
|
<< Bot->t_react
|
||||||
<< first_shot
|
<< Bot->t_fight
|
||||||
<< sleft
|
<< Bot->t_roam
|
||||||
<< allround
|
<< Bot->t_rocket
|
||||||
<< oldx
|
<< Bot->first_shot
|
||||||
<< oldy;
|
<< Bot->sleft
|
||||||
}
|
<< Bot->allround
|
||||||
else
|
<< Bot->oldx
|
||||||
{
|
<< Bot->oldy;
|
||||||
dest = prev = enemy = missile = mate = last_mate = NULL;
|
|
||||||
}
|
}
|
||||||
if (arc.IsLoading ())
|
if (arc.IsLoading ())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1575,7 +1575,7 @@ void S_RelinkSound (AActor *from, AActor *to)
|
||||||
{
|
{
|
||||||
chan->Actor = to;
|
chan->Actor = to;
|
||||||
}
|
}
|
||||||
else if (!(chan->ChanFlags & CHAN_LOOP))
|
else if (!(chan->ChanFlags & CHAN_LOOP) && !(compatflags2 & COMPATF2_SOUNDCUTOFF))
|
||||||
{
|
{
|
||||||
chan->Actor = NULL;
|
chan->Actor = NULL;
|
||||||
chan->SourceType = SOURCE_Unattached;
|
chan->SourceType = SOURCE_Unattached;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "m_swap.h"
|
#include "m_swap.h"
|
||||||
|
#include "doomerrors.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -277,7 +278,16 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const
|
||||||
return new TimidityMIDIDevice;
|
return new TimidityMIDIDevice;
|
||||||
|
|
||||||
case MDEV_OPL:
|
case MDEV_OPL:
|
||||||
return new OPLMIDIDevice;
|
try
|
||||||
|
{
|
||||||
|
return new OPLMIDIDevice;
|
||||||
|
}
|
||||||
|
catch (CRecoverableError &err)
|
||||||
|
{
|
||||||
|
// The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found.
|
||||||
|
Printf("Unable to create OPL MIDI device: %s\nFalling back to FModEx playback", err.GetMessage());
|
||||||
|
return new FMODMIDIDevice;
|
||||||
|
}
|
||||||
|
|
||||||
case MDEV_TIMIDITY:
|
case MDEV_TIMIDITY:
|
||||||
return new TimidityPPMIDIDevice;
|
return new TimidityPPMIDIDevice;
|
||||||
|
|
|
@ -2912,6 +2912,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
|
||||||
self->flags3 = (defs->flags3 & ~(MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS)) | (self->flags3 & (MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS));
|
self->flags3 = (defs->flags3 & ~(MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS)) | (self->flags3 & (MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS));
|
||||||
self->flags4 = (defs->flags4 & ~MF4_NOHATEPLAYERS) | (self->flags4 & MF4_NOHATEPLAYERS);
|
self->flags4 = (defs->flags4 & ~MF4_NOHATEPLAYERS) | (self->flags4 & MF4_NOHATEPLAYERS);
|
||||||
self->flags5 = defs->flags5;
|
self->flags5 = defs->flags5;
|
||||||
|
self->flags6 = defs->flags6;
|
||||||
|
self->flags7 = defs->flags7;
|
||||||
self->SetState (self->SpawnState);
|
self->SetState (self->SpawnState);
|
||||||
self->renderflags &= ~RF_INVISIBLE;
|
self->renderflags &= ~RF_INVISIBLE;
|
||||||
|
|
||||||
|
@ -4348,12 +4350,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
|
||||||
ACTION_PARAM_INT(flags, 5);
|
ACTION_PARAM_INT(flags, 5);
|
||||||
ACTION_PARAM_STATE(success_state, 6);
|
ACTION_PARAM_STATE(success_state, 6);
|
||||||
|
|
||||||
fixed_t
|
|
||||||
|
|
||||||
oldx,
|
|
||||||
oldy,
|
|
||||||
oldz;
|
|
||||||
|
|
||||||
AActor *reference = COPY_AAPTR(self, destination_selector);
|
AActor *reference = COPY_AAPTR(self, destination_selector);
|
||||||
|
|
||||||
if (!reference)
|
if (!reference)
|
||||||
|
@ -4362,6 +4358,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixed_t oldx = self->x;
|
||||||
|
fixed_t oldy = self->y;
|
||||||
|
fixed_t oldz = self->z;
|
||||||
|
|
||||||
if (!(flags & WARPF_ABSOLUTEANGLE))
|
if (!(flags & WARPF_ABSOLUTEANGLE))
|
||||||
{
|
{
|
||||||
angle += (flags & WARPF_USECALLERANGLE) ? self->angle : reference->angle;
|
angle += (flags & WARPF_USECALLERANGLE) ? self->angle : reference->angle;
|
||||||
|
@ -4371,20 +4371,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
|
||||||
if (!(flags & WARPF_ABSOLUTEOFFSET))
|
if (!(flags & WARPF_ABSOLUTEOFFSET))
|
||||||
{
|
{
|
||||||
angle_t fineangle = angle >> ANGLETOFINESHIFT;
|
angle_t fineangle = angle >> ANGLETOFINESHIFT;
|
||||||
oldx = xofs;
|
fixed_t xofs1 = xofs;
|
||||||
|
|
||||||
// (borrowed from A_SpawnItemEx, assumed workable)
|
// (borrowed from A_SpawnItemEx, assumed workable)
|
||||||
// in relative mode negative y values mean 'left' and positive ones mean 'right'
|
// in relative mode negative y values mean 'left' and positive ones mean 'right'
|
||||||
// This is the inverse orientation of the absolute mode!
|
// This is the inverse orientation of the absolute mode!
|
||||||
|
|
||||||
xofs = FixedMul(oldx, finecosine[fineangle]) + FixedMul(yofs, finesine[fineangle]);
|
xofs = FixedMul(xofs1, finecosine[fineangle]) + FixedMul(yofs, finesine[fineangle]);
|
||||||
yofs = FixedMul(oldx, finesine[fineangle]) - FixedMul(yofs, finecosine[fineangle]);
|
yofs = FixedMul(xofs1, finesine[fineangle]) - FixedMul(yofs, finecosine[fineangle]);
|
||||||
}
|
}
|
||||||
|
|
||||||
oldx = self->x;
|
|
||||||
oldy = self->y;
|
|
||||||
oldz = self->z;
|
|
||||||
|
|
||||||
if (flags & WARPF_TOFLOOR)
|
if (flags & WARPF_TOFLOOR)
|
||||||
{
|
{
|
||||||
// set correct xy
|
// set correct xy
|
||||||
|
@ -4835,43 +4831,26 @@ enum DMSS
|
||||||
DMSS_AFFECTARMOR = 2,
|
DMSS_AFFECTARMOR = 2,
|
||||||
DMSS_KILL = 4,
|
DMSS_KILL = 4,
|
||||||
DMSS_NOFACTOR = 8,
|
DMSS_NOFACTOR = 8,
|
||||||
|
DMSS_FOILBUDDHA = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags)
|
static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags)
|
||||||
{
|
{
|
||||||
if ((amount > 0) || (flags & DMSS_KILL))
|
int dmgFlags = 0;
|
||||||
{
|
if (flags & DMSS_FOILINVUL)
|
||||||
if (!(dmgtarget->flags2 & MF2_INVULNERABLE) || (flags & DMSS_FOILINVUL))
|
dmgFlags += DMG_FOILINVUL;
|
||||||
{
|
if (flags & DMSS_FOILBUDDHA)
|
||||||
if (flags & DMSS_KILL)
|
dmgFlags += DMG_FOILBUDDHA;
|
||||||
{
|
if ((flags & DMSS_KILL) || (flags & DMSS_NOFACTOR)) //Kill implies NoFactor
|
||||||
P_DamageMobj(dmgtarget, self, self, dmgtarget->health, DamageType, DMG_NO_FACTOR | DMG_NO_ARMOR | DMG_FOILINVUL);
|
dmgFlags += DMG_NO_FACTOR;
|
||||||
}
|
if (!(flags & DMSS_AFFECTARMOR) || (flags & DMSS_KILL)) //Kill overrides AffectArmor
|
||||||
if (flags & DMSS_AFFECTARMOR)
|
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.
|
||||||
if (flags & DMSS_NOFACTOR)
|
amount += dmgtarget->health;
|
||||||
{
|
|
||||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_FACTOR);
|
if (amount > 0)
|
||||||
}
|
P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine.
|
||||||
else
|
|
||||||
{
|
|
||||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (flags & DMSS_NOFACTOR)
|
|
||||||
{
|
|
||||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_ARMOR | DMG_NO_FACTOR);
|
|
||||||
}
|
|
||||||
//[MC] DMG_FOILINVUL is needed for making the damage occur on the actor.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_ARMOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (amount < 0)
|
else if (amount < 0)
|
||||||
{
|
{
|
||||||
amount = -amount;
|
amount = -amount;
|
||||||
|
@ -4995,30 +4974,32 @@ enum KILS
|
||||||
KILS_FOILINVUL = 1 << 0,
|
KILS_FOILINVUL = 1 << 0,
|
||||||
KILS_KILLMISSILES = 1 << 1,
|
KILS_KILLMISSILES = 1 << 1,
|
||||||
KILS_NOMONSTERS = 1 << 2,
|
KILS_NOMONSTERS = 1 << 2,
|
||||||
|
KILS_FOILBUDDHA = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags)
|
static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags)
|
||||||
{
|
{
|
||||||
|
int dmgFlags = DMG_NO_ARMOR + DMG_NO_FACTOR;
|
||||||
|
|
||||||
|
if (KILS_FOILINVUL)
|
||||||
|
dmgFlags += DMG_FOILINVUL;
|
||||||
|
if (KILS_FOILBUDDHA)
|
||||||
|
dmgFlags += DMG_FOILBUDDHA;
|
||||||
|
|
||||||
if ((killtarget->flags & MF_MISSILE) && (flags & KILS_KILLMISSILES))
|
if ((killtarget->flags & MF_MISSILE) && (flags & KILS_KILLMISSILES))
|
||||||
{
|
{
|
||||||
//[MC] Now that missiles can set masters, lets put in a check to properly destroy projectiles. BUT FIRST! New feature~!
|
//[MC] Now that missiles can set masters, lets put in a check to properly destroy projectiles. BUT FIRST! New feature~!
|
||||||
//Check to see if it's invulnerable. Disregarded if foilinvul is on, but never works on a missile with NODAMAGE
|
//Check to see if it's invulnerable. Disregarded if foilinvul is on, but never works on a missile with NODAMAGE
|
||||||
//since that's the whole point of it.
|
//since that's the whole point of it.
|
||||||
if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) && !(killtarget->flags5 & MF5_NODAMAGE))
|
if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) &&
|
||||||
|
(!(killtarget->flags2 & MF7_BUDDHA) || (flags & KILS_FOILBUDDHA)) && !(killtarget->flags5 & MF5_NODAMAGE))
|
||||||
{
|
{
|
||||||
P_ExplodeMissile(killtarget, NULL, NULL);
|
P_ExplodeMissile(killtarget, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(flags & KILS_NOMONSTERS))
|
if (!(flags & KILS_NOMONSTERS))
|
||||||
{
|
{
|
||||||
if (flags & KILS_FOILINVUL)
|
P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, dmgFlags);
|
||||||
{
|
|
||||||
P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR | DMG_FOILINVUL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,6 +241,9 @@ static FFlagDef ActorFlags[]=
|
||||||
DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7),
|
DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7),
|
||||||
DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7),
|
DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7),
|
||||||
DEFINE_FLAG(MF7, WEAPONSPAWN, AActor, flags7),
|
DEFINE_FLAG(MF7, WEAPONSPAWN, AActor, flags7),
|
||||||
|
DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7),
|
||||||
|
DEFINE_FLAG(MF7, BUDDHA, AActor, flags7),
|
||||||
|
DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7),
|
||||||
|
|
||||||
// Effect flags
|
// Effect flags
|
||||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||||
|
@ -311,6 +314,7 @@ static FFlagDef InventoryFlags[] =
|
||||||
DEFINE_FLAG(IF, NEVERRESPAWN, AInventory, ItemFlags),
|
DEFINE_FLAG(IF, NEVERRESPAWN, AInventory, ItemFlags),
|
||||||
DEFINE_FLAG(IF, NOSCREENFLASH, AInventory, ItemFlags),
|
DEFINE_FLAG(IF, NOSCREENFLASH, AInventory, ItemFlags),
|
||||||
DEFINE_FLAG(IF, TOSSED, AInventory, ItemFlags),
|
DEFINE_FLAG(IF, TOSSED, AInventory, ItemFlags),
|
||||||
|
DEFINE_FLAG(IF, ALWAYSRESPAWN, AInventory, ItemFlags),
|
||||||
|
|
||||||
DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
|
DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
|
||||||
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),};
|
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),};
|
||||||
|
|
|
@ -76,7 +76,7 @@ const char *GetVersionString();
|
||||||
|
|
||||||
// Use 4500 as the base git save version, since it's higher than the
|
// Use 4500 as the base git save version, since it's higher than the
|
||||||
// SVN revision ever got.
|
// SVN revision ever got.
|
||||||
#define SAVEVER 4513
|
#define SAVEVER 4514
|
||||||
|
|
||||||
#define SAVEVERSTRINGIFY2(x) #x
|
#define SAVEVERSTRINGIFY2(x) #x
|
||||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||||
|
|
|
@ -1330,7 +1330,7 @@ void WI_updateDeathmatchStats ()
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
// If the player is in the game and not ready, stop checking
|
// If the player is in the game and not ready, stop checking
|
||||||
if (playeringame[i] && !players[i].isbot && !playerready[i])
|
if (playeringame[i] && players[i].Bot == NULL && !playerready[i])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1429,7 +1429,7 @@ void WI_drawDeathmatchStats ()
|
||||||
clamp(int(g*255.f), 0, 255),
|
clamp(int(g*255.f), 0, 255),
|
||||||
clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (deaths_x - x) + (8 * CleanXfac), lineheight);
|
clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (deaths_x - x) + (8 * CleanXfac), lineheight);
|
||||||
|
|
||||||
if (playerready[pnum] || player->isbot) // Bots are automatically assumed ready, to prevent confusion
|
if (playerready[pnum] || player->Bot != NULL) // Bots are automatically assumed ready, to prevent confusion
|
||||||
screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE);
|
screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE);
|
||||||
|
|
||||||
color = (EColorRange)HU_GetRowColor(player, pnum == consoleplayer);
|
color = (EColorRange)HU_GetRowColor(player, pnum == consoleplayer);
|
||||||
|
@ -1638,7 +1638,7 @@ void WI_updateNetgameStats ()
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
// If the player is in the game and not ready, stop checking
|
// If the player is in the game and not ready, stop checking
|
||||||
if (playeringame[i] && !players[i].isbot && !playerready[i])
|
if (playeringame[i] && players[i].Bot == NULL && !playerready[i])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1735,7 +1735,7 @@ void WI_drawNetgameStats ()
|
||||||
clamp(int(g*255.f), 0, 255),
|
clamp(int(g*255.f), 0, 255),
|
||||||
clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (secret_x - x) + (8 * CleanXfac), lineheight);
|
clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (secret_x - x) + (8 * CleanXfac), lineheight);
|
||||||
|
|
||||||
if (playerready[i] || player->isbot) // Bots are automatically assumed ready, to prevent confusion
|
if (playerready[i] || player->Bot != NULL) // Bots are automatically assumed ready, to prevent confusion
|
||||||
screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE);
|
screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE);
|
||||||
|
|
||||||
color = (EColorRange)HU_GetRowColor(player, i == consoleplayer);
|
color = (EColorRange)HU_GetRowColor(player, i == consoleplayer);
|
||||||
|
@ -2010,7 +2010,7 @@ void WI_checkForAccelerate(void)
|
||||||
{
|
{
|
||||||
if ((player->cmd.ucmd.buttons ^ player->oldbuttons) &&
|
if ((player->cmd.ucmd.buttons ^ player->oldbuttons) &&
|
||||||
((players[i].cmd.ucmd.buttons & players[i].oldbuttons)
|
((players[i].cmd.ucmd.buttons & players[i].oldbuttons)
|
||||||
== players[i].oldbuttons) && !player->isbot)
|
== players[i].oldbuttons) && player->Bot == NULL)
|
||||||
{
|
{
|
||||||
acceleratestage = 1;
|
acceleratestage = 1;
|
||||||
playerready[i] = true;
|
playerready[i] = true;
|
||||||
|
|
|
@ -375,12 +375,14 @@ enum
|
||||||
const int KILS_FOILINVUL = 1;
|
const int KILS_FOILINVUL = 1;
|
||||||
const int KILS_KILLMISSILES = 2;
|
const int KILS_KILLMISSILES = 2;
|
||||||
const int KILS_NOMONSTERS = 4;
|
const int KILS_NOMONSTERS = 4;
|
||||||
|
const int KILS_FOILBUDDHA = 8;
|
||||||
|
|
||||||
// Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series
|
// Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series
|
||||||
const int DMSS_FOILINVUL = 1;
|
const int DMSS_FOILINVUL = 1;
|
||||||
const int DMSS_AFFECTARMOR = 2;
|
const int DMSS_AFFECTARMOR = 2;
|
||||||
const int DMSS_KILL = 4;
|
const int DMSS_KILL = 4;
|
||||||
const int DMSS_NOFACTOR = 8;
|
const int DMSS_NOFACTOR = 8;
|
||||||
|
const int DMSS_FOILBUDDHA = 16;
|
||||||
|
|
||||||
// Flags for A_AlertMonsters
|
// Flags for A_AlertMonsters
|
||||||
const int AMF_TARGETEMITTER = 1;
|
const int AMF_TARGETEMITTER = 1;
|
||||||
|
|
|
@ -110,7 +110,7 @@ ACTOR StaffPuff2
|
||||||
|
|
||||||
// Gold wand ----------------------------------------------------------------
|
// Gold wand ----------------------------------------------------------------
|
||||||
|
|
||||||
ACTOR GoldWand : HereticWeapon
|
ACTOR GoldWand : HereticWeapon 9042
|
||||||
{
|
{
|
||||||
Game Heretic
|
Game Heretic
|
||||||
+BLOODSPLATTER
|
+BLOODSPLATTER
|
||||||
|
@ -120,6 +120,7 @@ ACTOR GoldWand : HereticWeapon
|
||||||
Weapon.AmmoType "GoldWandAmmo"
|
Weapon.AmmoType "GoldWandAmmo"
|
||||||
Weapon.SisterWeapon "GoldWandPowered"
|
Weapon.SisterWeapon "GoldWandPowered"
|
||||||
Weapon.YAdjust 5
|
Weapon.YAdjust 5
|
||||||
|
Inventory.PickupMessage "$TXT_WPNGOLDWAND"
|
||||||
Obituary "$OB_MPGOLDWAND"
|
Obituary "$OB_MPGOLDWAND"
|
||||||
Tag "$TAG_GOLDWAND"
|
Tag "$TAG_GOLDWAND"
|
||||||
|
|
||||||
|
@ -127,6 +128,9 @@ ACTOR GoldWand : HereticWeapon
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
|
Spawn:
|
||||||
|
GWAN A -1
|
||||||
|
Stop
|
||||||
Ready:
|
Ready:
|
||||||
GWND A 1 A_WeaponReady
|
GWND A 1 A_WeaponReady
|
||||||
Loop
|
Loop
|
||||||
|
|
|
@ -271,6 +271,11 @@ ACTOR PowerFrightener : Powerup native
|
||||||
Powerup.Duration -60
|
Powerup.Duration -60
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ACTOR PowerBuddha : Powerup native
|
||||||
|
{
|
||||||
|
Powerup.Duration -60
|
||||||
|
}
|
||||||
|
|
||||||
ACTOR PowerScanner : Powerup native
|
ACTOR PowerScanner : Powerup native
|
||||||
{
|
{
|
||||||
Powerup.Duration -80
|
Powerup.Duration -80
|
||||||
|
|
|
@ -9,7 +9,7 @@ ACTOR Peasant : StrifeHumanoid
|
||||||
Radius 20
|
Radius 20
|
||||||
Height 56
|
Height 56
|
||||||
Monster
|
Monster
|
||||||
+FRIENDLY
|
+NEVERTARGET
|
||||||
-COUNTKILL
|
-COUNTKILL
|
||||||
+NOSPLASHALERT
|
+NOSPLASHALERT
|
||||||
+FLOORCLIP
|
+FLOORCLIP
|
||||||
|
|
|
@ -292,6 +292,8 @@ STSTR_MUS = "Music Change";
|
||||||
STSTR_NOMUS = "IMPOSSIBLE SELECTION";
|
STSTR_NOMUS = "IMPOSSIBLE SELECTION";
|
||||||
STSTR_DQDON = "Degreelessness Mode ON";
|
STSTR_DQDON = "Degreelessness Mode ON";
|
||||||
STSTR_DQDOFF = "Degreelessness Mode OFF";
|
STSTR_DQDOFF = "Degreelessness Mode OFF";
|
||||||
|
STSTR_DQD2ON = "Ultimate Degreelessness Mode ON";
|
||||||
|
STSTR_DQD2OFF = "Ultimate Degreelessness Mode OFF";
|
||||||
STSTR_KFAADDED = "Very Happy Ammo Added";
|
STSTR_KFAADDED = "Very Happy Ammo Added";
|
||||||
STSTR_FAADDED = "Ammo (no keys) Added";
|
STSTR_FAADDED = "Ammo (no keys) Added";
|
||||||
STSTR_NCON = "No Clipping Mode ON";
|
STSTR_NCON = "No Clipping Mode ON";
|
||||||
|
@ -303,6 +305,8 @@ STSTR_CHOPPERS = "... doesn't suck - GM";
|
||||||
STSTR_CLEV = "Changing Level...\n";
|
STSTR_CLEV = "Changing Level...\n";
|
||||||
TXT_BUDDHAON = "Buddha mode ON";
|
TXT_BUDDHAON = "Buddha mode ON";
|
||||||
TXT_BUDDHAOFF = "Buddha mode OFF";
|
TXT_BUDDHAOFF = "Buddha mode OFF";
|
||||||
|
TXT_BUDDHA2ON = "Ultimate Buddha Mode ON";
|
||||||
|
TXT_BUDDHA2OFF = "Ultimate Buddha Mode OFF";
|
||||||
TXT_DEFAULTPICKUPMSG = "You got a pickup";
|
TXT_DEFAULTPICKUPMSG = "You got a pickup";
|
||||||
|
|
||||||
E1TEXT =
|
E1TEXT =
|
||||||
|
@ -1242,6 +1246,7 @@ TXT_AMMOPHOENIXROD2 = "INFERNO ORB";
|
||||||
|
|
||||||
// Weapons
|
// Weapons
|
||||||
|
|
||||||
|
TXT_WPNGOLDWAND = "GOLD WAND";
|
||||||
TXT_WPNMACE = "FIREMACE";
|
TXT_WPNMACE = "FIREMACE";
|
||||||
TXT_WPNCROSSBOW = "ETHEREAL CROSSBOW";
|
TXT_WPNCROSSBOW = "ETHEREAL CROSSBOW";
|
||||||
TXT_WPNBLASTER = "DRAGON CLAW";
|
TXT_WPNBLASTER = "DRAGON CLAW";
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
Gameinfo
|
||||||
|
{
|
||||||
|
CheatKey = "maparrows/key.txt"
|
||||||
|
EasyKey = "maparrows/ravenkey.txt"
|
||||||
|
}
|
||||||
|
|
||||||
Intermission Inter_Titlescreen
|
Intermission Inter_Titlescreen
|
||||||
{
|
{
|
||||||
|
|
|
@ -1300,6 +1300,7 @@ OptionMenu "CompatibilityOptions"
|
||||||
Option "Ignore Y offsets on masked midtextures", "compat_MASKEDMIDTEX", "YesNo"
|
Option "Ignore Y offsets on masked midtextures", "compat_MASKEDMIDTEX", "YesNo"
|
||||||
Option "Cannot travel straight NSEW", "compat_badangles", "YesNo"
|
Option "Cannot travel straight NSEW", "compat_badangles", "YesNo"
|
||||||
Option "Use Doom's floor motion behavior", "compat_floormove", "YesNo"
|
Option "Use Doom's floor motion behavior", "compat_floormove", "YesNo"
|
||||||
|
Option "Sounds stop when actor vanishes", "compat_soundcutoff", "YesNo"
|
||||||
|
|
||||||
Class "CompatibilityMenu"
|
Class "CompatibilityMenu"
|
||||||
}
|
}
|
||||||
|
|
BIN
wadsrc/static/sprites/GWANA0.png
Normal file
BIN
wadsrc/static/sprites/GWANA0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 315 B |
Binary file not shown.
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 377 B |
Loading…
Reference in a new issue