- removed the bot related properties from AWeapon.

This stuff is now kept locally in the bot code so that it doesn't infest the rest of the engine.
And please don't read the new botsupp.txt file as some new means to configure bots! This was merely done to get this data out of the way.
The bots are still broken beyond repair and virtually unusable, even if proper data is provided for all weapons.
This commit is contained in:
Christoph Oelckers 2018-11-24 23:48:23 +01:00
commit 8eb4697fbd
10 changed files with 131 additions and 89 deletions

View file

@ -47,6 +47,7 @@
#include "d_net.h"
#include "serializer.h"
#include "d_player.h"
#include "w_wad.h"
#include "vm.h"
IMPLEMENT_CLASS(DBot, false, true)
@ -246,69 +247,61 @@ CCMD (listbots)
// set the bot specific weapon information
// This is intentionally not in the weapon definition anymore.
BotInfoMap BotInfo;
void InitBotStuff()
{
static struct BotInit
int lump;
int lastlump = 0;
while (-1 != (lump = Wads.FindLump("BOTSUPP", &lastlump)))
{
const char *type;
int movecombatdist;
int weaponflags;
const char *projectile;
} botinits[] = {
{ "Pistol", 25000000, 0, NULL },
{ "Shotgun", 24000000, 0, NULL },
{ "SuperShotgun", 15000000, 0, NULL },
{ "Chaingun", 27000000, 0, NULL },
{ "RocketLauncher", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "Rocket" },
{ "PlasmaRifle", 27000000, 0, "PlasmaBall" },
{ "BFG9000", 10000000, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_BFG, "BFGBall" },
{ "GoldWand", 25000000, 0, NULL },
{ "GoldWandPowered", 25000000, 0, NULL },
{ "Crossbow", 24000000, 0, "CrossbowFX1" },
{ "CrossbowPowered", 24000000, 0, "CrossbowFX2" },
{ "Blaster", 27000000, 0, NULL },
{ "BlasterPowered", 27000000, 0, "BlasterFX1" },
{ "SkullRod", 27000000, 0, "HornRodFX1" },
{ "SkullRodPowered", 27000000, 0, "HornRodFX2" },
{ "PhoenixRod", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "PhoenixFX1" },
{ "Mace", 27000000, WIF_BOT_REACTION_SKILL_THING, "MaceFX2" },
{ "MacePowered", 27000000, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "MaceFX4" },
{ "FWeapHammer", 22000000, 0, "HammerMissile" },
{ "FWeapQuietus", 20000000, 0, "FSwordMissile" },
{ "CWeapStaff", 25000000, 0, "CStaffMissile" },
{ "CWeapFlane", 27000000, 0, "CFlameMissile" },
{ "MWeapWand", 25000000, 0, "MageWandMissile" },
{ "CWeapWraithverge", 22000000, 0, "HolyMissile" },
{ "MWeapFrost", 19000000, 0, "FrostMissile" },
{ "MWeapLightning", 23000000, 0, "LightningFloor" },
{ "MWeapBloodscourge", 20000000, 0, "MageStaffFX2" },
{ "StrifeCrossbow", 24000000, 0, "ElectricBolt" },
{ "StrifeCrossbow2", 24000000, 0, "PoisonBolt" },
{ "AssaultGun", 27000000, 0, NULL },
{ "MiniMissileLauncher", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "MiniMissile" },
{ "FlameThrower", 24000000, 0, "FlameMissile" },
{ "Mauler", 15000000, 0, NULL },
{ "Mauler2", 10000000, 0, "MaulerTorpedo" },
{ "StrifeGrenadeLauncher", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "HEGrenade" },
{ "StrifeGrenadeLauncher2", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "PhosphorousGrenade" },
};
for(unsigned i=0;i<sizeof(botinits)/sizeof(botinits[0]);i++)
{
const PClass *cls = PClass::FindClass(botinits[i].type);
if (cls != NULL && cls->IsDescendantOf(NAME_Weapon))
FScanner sc(lump);
sc.SetCMode(true);
while (sc.GetString())
{
AWeapon *w = (AWeapon*)GetDefaultByType(cls);
if (w != NULL)
PClassActor *wcls = PClass::FindActor(sc.String);
if (wcls != NULL && wcls->IsDescendantOf(NAME_Weapon))
{
w->MoveCombatDist = botinits[i].movecombatdist/65536.;
w->WeaponFlags |= botinits[i].weaponflags;
w->ProjectileType = PClass::FindActor(botinits[i].projectile);
BotInfoData bi = {};
sc.MustGetStringName(",");
sc.MustGetNumber();
bi.MoveCombatDist = sc.Number;
while (sc.CheckString(","))
{
sc.MustGetString();
if (sc.Compare("BOT_REACTION_SKILL_THING"))
{
bi.flags |= BIF_BOT_REACTION_SKILL_THING;
}
else if (sc.Compare("BOT_EXPLOSIVE"))
{
bi.flags |= BIF_BOT_EXPLOSIVE;
}
else if (sc.Compare("BOT_BFG"))
{
bi.flags |= BIF_BOT_BFG;
}
else
{
PClassActor *cls = PClass::FindActor(sc.String);
bi.projectileType = cls;
if (cls == nullptr)
{
sc.ScriptError("Unknown token %s", sc.String);
}
}
}
BotInfo[wcls->TypeName] = bi;
}
else
{
sc.ScriptError("%s is not a weapon type", sc.String);
}
}
}
// Fixme: Export these, too.
static const char *warnbotmissiles[] = { "PlasmaBall", "Ripper", "HornRodFX1" };
for(unsigned i=0;i<countof(warnbotmissiles);i++)
{

View file

@ -13,6 +13,7 @@
#include "d_protocol.h"
#include "r_defs.h"
#include "a_pickups.h"
#include "a_weapons.h"
#include "stats.h"
#define FORWARDWALK 0x1900
@ -49,6 +50,7 @@
#define MMAXSELECT 100 //Maximum number of monsters that can be selected at a time.
struct FCheckPosition;
class AWeapon;
struct botskill_t
{
@ -78,6 +80,34 @@ struct botinfo_t
int lastteam;
};
struct BotInfoData
{
int MoveCombatDist = 0;
int flags = 0;
PClassActor *projectileType = nullptr;
};
enum
{
BIF_BOT_REACTION_SKILL_THING = 1,
BIF_BOT_EXPLOSIVE = 2,
BIF_BOT_BFG = 4,
};
using BotInfoMap = TMap<FName, BotInfoData>;
extern BotInfoMap BotInfo;
inline BotInfoData GetBotInfo(AWeapon *weap)
{
if (weap == nullptr) return BotInfoData();
auto k = BotInfo.CheckKey(weap->GetClass()->TypeName);
if (k) return *k;
return BotInfoData();
}
//Used to keep all the globally needed variables in nice order.
class FCajunMaster
{

View file

@ -188,7 +188,7 @@ void DBot::Dofire (ticcmd_t *cmd)
//Reaction skill thing.
if (first_shot &&
!(player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING))
!(GetBotInfo(player->ReadyWeapon).flags & BIF_BOT_REACTION_SKILL_THING))
{
t_react = (100-skill.reaction+1)/((pr_botdofire()%3)+3);
}
@ -203,21 +203,21 @@ void DBot::Dofire (ticcmd_t *cmd)
Dist = player->mo->Distance2D(enemy, player->mo->Vel.X - enemy->Vel.X, player->mo->Vel.Y - enemy->Vel.Y);
//FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go.
if (player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)
if (GetBotInfo(player->ReadyWeapon).MoveCombatDist == 0)
{
//*4 is for atmosphere, the chainsaws sounding and all..
no_fire = (Dist > DEFMELEERANGE*4);
}
else if (player->ReadyWeapon->WeaponFlags & WIF_BOT_BFG)
else if (GetBotInfo(player->ReadyWeapon).flags & BIF_BOT_BFG)
{
//MAKEME: This should be smarter.
if ((pr_botdofire()%200)<=skill.reaction)
if(Check_LOS(enemy, SHOOTFOV))
no_fire = false;
}
else if (player->ReadyWeapon->ProjectileType != NULL)
else if (GetBotInfo(player->ReadyWeapon).projectileType != NULL)
{
if (player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
if (GetBotInfo(player->ReadyWeapon).flags & BIF_BOT_EXPLOSIVE)
{
//Special rules for RL
an = FireRox (enemy, cmd);
@ -234,7 +234,7 @@ void DBot::Dofire (ticcmd_t *cmd)
}
// prediction aiming
Dist = player->mo->Distance2D(enemy);
fm = Dist / GetDefaultByType (player->ReadyWeapon->ProjectileType)->Speed;
fm = Dist / GetDefaultByType (GetBotInfo(player->ReadyWeapon).projectileType)->Speed;
bglobal.SetBodyAt(enemy->Pos() + enemy->Vel.XY() * fm * 2, 1);
Angle = player->mo->AngleTo(bglobal.body1);
if (Check_LOS (enemy, SHOOTFOV))

View file

@ -345,7 +345,7 @@ void DBot::TurnToAng ()
if (player->ReadyWeapon != NULL)
{
if (player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
if (GetBotInfo(player->ReadyWeapon).flags & BIF_BOT_EXPLOSIVE)
{
if (t_roam && !missile)
{ //Keep angle that where when shot where decided.
@ -356,7 +356,7 @@ void DBot::TurnToAng ()
if(enemy)
if(!dest) //happens when running after item in combat situations, or normal, prevents weak turns
if(player->ReadyWeapon->ProjectileType == NULL && !(player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON))
if(GetBotInfo(player->ReadyWeapon).projectileType == NULL && GetBotInfo(player->ReadyWeapon).MoveCombatDist > 0)
if(Check_LOS(enemy, SHOOTFOV+5))
maxturn = 3;
}

View file

@ -173,9 +173,9 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
is (Megasphere)
) ||
dist < (GETINCOMBAT/4) ||
(player->ReadyWeapon == NULL || player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)
(GetBotInfo(player->ReadyWeapon).MoveCombatDist == 0)
)
&& (dist < GETINCOMBAT || (player->ReadyWeapon == NULL || player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
&& (dist < GETINCOMBAT || (GetBotInfo(player->ReadyWeapon).MoveCombatDist == 0))
&& Reachable (dest))
#undef is
{
@ -185,7 +185,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
dest = NULL; //To let bot turn right
if (player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
if (GetBotInfo(player->ReadyWeapon).MoveCombatDist == 0)
player->mo->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting.
if (!(enemy->flags3 & MF3_ISMONSTER))
@ -205,7 +205,7 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
if (player->ReadyWeapon == NULL ||
player->mo->Distance2D(enemy) >
player->ReadyWeapon->MoveCombatDist)
GetBotInfo(player->ReadyWeapon).MoveCombatDist)
{
// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
cmd->ucmd.forwardmove = (enemy->flags3 & MF3_ISMONSTER) ? FORWARDWALK : FORWARDRUN;
@ -273,8 +273,8 @@ void DBot::ThinkForMove (ticcmd_t *cmd)
{
if (enemy->player)
{
if (((enemy->player->ReadyWeapon != NULL && enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) ||
(pr_botmove()%100)>skill.isp) && player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
if (((enemy->player->ReadyWeapon != NULL && GetBotInfo(enemy->player->ReadyWeapon).flags & BIF_BOT_EXPLOSIVE) ||
(pr_botmove()%100)>skill.isp) && (GetBotInfo(player->ReadyWeapon).MoveCombatDist != 0))
dest = enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy.
else //hide while t_fight, but keep view at enemy.
Angle = player->mo->AngleTo(enemy);

View file

@ -68,12 +68,9 @@ DEFINE_FIELD(AWeapon, YAdjust)
DEFINE_FIELD(AWeapon, UpSound)
DEFINE_FIELD(AWeapon, ReadySound)
DEFINE_FIELD(AWeapon, SisterWeaponType)
DEFINE_FIELD(AWeapon, ProjectileType)
DEFINE_FIELD(AWeapon, AltProjectileType)
DEFINE_FIELD(AWeapon, SelectionOrder)
DEFINE_FIELD(AWeapon, MinSelAmmo1)
DEFINE_FIELD(AWeapon, MinSelAmmo2)
DEFINE_FIELD(AWeapon, MoveCombatDist)
DEFINE_FIELD(AWeapon, ReloadCounter)
DEFINE_FIELD(AWeapon, BobStyle)
DEFINE_FIELD(AWeapon, BobSpeed)
@ -184,9 +181,6 @@ void AWeapon::Serialize(FSerializer &arc)
("ammotype1", AmmoType1, def->AmmoType1)
("ammotype2", AmmoType2, def->AmmoType2)
("sisterweapontype", SisterWeaponType, def->SisterWeaponType)
("projectiletype", ProjectileType, def->ProjectileType)
("altprojectiletype", AltProjectileType, def->AltProjectileType)
("movecombatdist", MoveCombatDist, def->MoveCombatDist)
*/
}

View file

@ -142,11 +142,8 @@ public:
float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double)
FSoundIDNoInit UpSound, ReadySound; // Sounds when coming up and idle
PClassActor *SisterWeaponType; // Another weapon to pick up with this one
PClassActor *ProjectileType; // Projectile used by primary attack
PClassActor *AltProjectileType; // Projectile used by alternate attack
int SelectionOrder; // Lower-numbered weapons get picked first
int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo
double MoveCombatDist; // Used by bots, but do they *really* need it?
int ReloadCounter; // For A_CheckForReload
int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double)
float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs.
@ -210,11 +207,5 @@ enum
WIF_NODEATHDESELECT = 0x00020000, // Don't jump to the Deselect state when the player dies
WIF_NODEATHINPUT = 0x00040000, // The weapon cannot be fired/reloaded/whatever when the player is dead
WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil)
// Flags used only by bot AI:
WIF_BOT_REACTION_SKILL_THING = 1<<31, // I don't understand this
WIF_BOT_EXPLOSIVE = 1<<30, // weapon fires an explosive
WIF_BOT_BFG = 1<<28, // this is a BFG
};

View file

@ -456,9 +456,7 @@ static FFlagDef WeaponFlagDefs[] =
DEFINE_FLAG(WIF, WIMPY_WEAPON, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, MELEEWEAPON, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF_BOT, BFG, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags),
@ -469,6 +467,8 @@ static FFlagDef WeaponFlagDefs[] =
DEFINE_DUMMY_FLAG(NOLMS, false),
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false),
DEFINE_DUMMY_FLAG(BFG, true),
DEFINE_DUMMY_FLAG(EXPLOSIVE, true),
};