diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 24a1bfe03..25418acca 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -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;iIsDescendantOf(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; + +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 { diff --git a/src/b_func.cpp b/src/b_func.cpp index 87eaa66b6..34a5bd9fd 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -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)) diff --git a/src/b_move.cpp b/src/b_move.cpp index 3d3e67ed2..52ae724dc 100644 --- a/src/b_move.cpp +++ b/src/b_move.cpp @@ -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; } diff --git a/src/b_think.cpp b/src/b_think.cpp index 2c41bcda3..32dd8e6b1 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -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); diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 29579f127..0d18cbcc6 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -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) */ } diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index f1252f729..62097b633 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -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 }; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index f5d10a417..c88262298 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -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), }; diff --git a/wadsrc/static/botsupp.txt b/wadsrc/static/botsupp.txt new file mode 100644 index 000000000..730fb056a --- /dev/null +++ b/wadsrc/static/botsupp.txt @@ -0,0 +1,37 @@ +// This is just a straight dump of an internal table. Contents are: Weapon type, distance coefficient, optional flags and an optional projectile type. +Pistol, 25000000 +Shotgun, 24000000 +SuperShotgun, 15000000 +Chaingun, 27000000 +RocketLauncher, 18350080, BOT_REACTION_SKILL_THING, BOT_EXPLOSIVE, Rocket +PlasmaRifle, 27000000, PlasmaBall +BFG9000, 10000000, BOT_REACTION_SKILL_THING, BOT_BFG, BFGBall +GoldWand, 25000000 +GoldWandPowered, 25000000 +Crossbow, 24000000, CrossbowFX1 +CrossbowPowered, 24000000, CrossbowFX2 +Blaster, 27000000 +BlasterPowered, 27000000, BlasterFX1 +SkullRod, 27000000, HornRodFX1 +SkullRodPowered, 27000000, HornRodFX2 +PhoenixRod, 18350080, BOT_REACTION_SKILL_THING, BOT_EXPLOSIVE, PhoenixFX1 +Mace, 27000000, BOT_REACTION_SKILL_THING, MaceFX2 +MacePowered, 27000000, BOT_REACTION_SKILL_THING, BOT_EXPLOSIVE, MaceFX4 +FWeapHammer, 22000000, HammerMissile +FWeapQuietus, 20000000, FSwordMissile +CWeapStaff, 25000000, CStaffMissile +CWeapFlame, 27000000, CFlameMissile +MWeapWand, 25000000, MageWandMissile +CWeapWraithverge, 22000000, HolyMissile +MWeapFrost, 19000000, FrostMissile +MWeapLightning, 23000000, LightningFloor +MWeapBloodscourge, 20000000, MageStaffFX2 +StrifeCrossbow, 24000000, ElectricBolt +StrifeCrossbow2, 24000000, PoisonBolt +AssaultGun, 27000000 +MiniMissileLauncher, 18350080, BOT_REACTION_SKILL_THING, BOT_EXPLOSIVE, MiniMissile +FlameThrower, 24000000, FlameMissile +Mauler, 15000000 +Mauler2, 10000000, MaulerTorpedo +StrifeGrenadeLauncher, 18350080, BOT_REACTION_SKILL_THING, BOT_EXPLOSIVE, HEGrenade +StrifeGrenadeLauncher2, 18350080, BOT_REACTION_SKILL_THING, BOT_EXPLOSIVE, PhosphorousGrenade diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index 8612af792..1832e2d21 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -13,17 +13,14 @@ class Weapon : StateProvider native native uint WeaponFlags; native class AmmoType1, AmmoType2; // Types of ammo used by self weapon native int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon - native int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to self weapon + native int MinAmmo1, MinAmmo2; // not used anywhere. native int AmmoUse1, AmmoUse2; // How much ammo to use with each shot native int Kickback; native float YAdjust; // For viewing the weapon fullscreen (visual only so no need to be a double) native sound UpSound, ReadySound; // Sounds when coming up and idle native class SisterWeaponType; // Another weapon to pick up with self one - native class ProjectileType; // Projectile used by primary attack - native class AltProjectileType; // Projectile used by alternate attack native int SelectionOrder; // Lower-numbered weapons get picked first native int MinSelAmmo1, MinSelAmmo2; // Ignore in BestWeapon() if inadequate ammo - native double MoveCombatDist; // Used by bots, but do they *really* need it? native int ReloadCounter; // For A_CheckForReload native int BobStyle; // [XA] Bobbing style. Defines type of bobbing (e.g. Normal, Alpha) (visual only so no need to be a double) native float BobSpeed; // [XA] Bobbing speed. Defines how quickly a weapon bobs.