From 965d9e96d695753d0fbd67517c3df0eaf7a70c40 Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Wed, 17 Jul 2024 14:21:44 -0700 Subject: [PATCH] NSEntity: add SetOriginUnstick(), SetBotTag() NSWeapon: basic inventory management functions --- src/botlib/botinfo.h | 11 +- src/client/cmd.qc | 17 ++- src/gs-entbase/server/trigger_teleport.qc | 22 +-- src/shared/NSEntity.h | 5 + src/shared/NSEntity.qc | 12 ++ src/shared/NSItem.qc | 2 +- src/shared/NSMonster.qc | 2 +- src/shared/NSNavAI.qc | 2 +- src/shared/NSSpawnPoint.qc | 4 +- src/shared/NSVehicle.qc | 4 +- src/shared/NSWeapon.h | 1 + src/shared/NSWeapon.qc | 160 ++++++++++++++++++++++ src/shared/NSWeapon_NSNavAI.h | 4 + src/shared/defs.h | 59 ++++++++ 14 files changed, 274 insertions(+), 31 deletions(-) create mode 100644 src/shared/NSWeapon_NSNavAI.h diff --git a/src/botlib/botinfo.h b/src/botlib/botinfo.h index f3b69114..897e03a2 100644 --- a/src/botlib/botinfo.h +++ b/src/botlib/botinfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2022 Vera Visions LLC. + * Copyright (c) 2016-2024 Vera Visions LLC. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,11 +18,14 @@ @brief Info tags for bots used to identify objects. @ingroup bot +Any entity can have these tags set onto using NSEntity::SetBotTag(), it will help +the AI figure out a lot of game specific details. + @{ */ /* we need to keep this an enum so find() does its work faster */ -enum +typedef enum { BOTINFO_NONE, /**< no info */ BOTINFO_HEALTH, /**< health item */ @@ -32,8 +35,8 @@ enum BOTINFO_SPAWNPOINT, /**< place where to find new players */ BOTINFO_TEAM_GOALITEM, /**< team-mode goal item (flag, intel) */ BOTINFO_TEAM_GOALCAPTURE, /**< where to go when goal-item present */ - BOTINFO_END /**< end destination */ -}; + BOTINFO_END /**< end destination */ +} botInfo_t; .float botinfo; diff --git a/src/client/cmd.qc b/src/client/cmd.qc index a1cc7853..a18555e6 100644 --- a/src/client/cmd.qc +++ b/src/client/cmd.qc @@ -397,14 +397,14 @@ Cmd_Parse(string sCMD) case "-gostand": pSeat->m_iInputJump = false; break; - case "invnext": - HUD_DrawWeaponSelect_Back(); + case "weapnext": + NSWeapon_NextWeapon((NSClientPlayer)pSeat->m_ePlayer); break; - case "invprev": - HUD_DrawWeaponSelect_Forward(); + case "weapprev": + NSWeapon_PrevWeapon((NSClientPlayer)pSeat->m_ePlayer); break; - case "lastinv": - HUD_DrawWeaponSelect_Last(); + case "weaplast": + NSWeapon_LastWeapon((NSClientPlayer)pSeat->m_ePlayer); break; case "+showscores": pSeat->m_iScoresVisible = TRUE; @@ -662,6 +662,8 @@ Cmd_Init(void) registercommand("-leanleft"); registercommand("+leanright"); registercommand("-leanright"); + registercommand("weapnext"); + registercommand("weapprev"); /* voting */ registercommand("vote"); @@ -681,9 +683,6 @@ Cmd_Init(void) registercommand("slot8"); registercommand("slot9"); registercommand("slot10"); - registercommand("lastinv"); - registercommand("invnext"); - registercommand("invprev"); /* scoreboard */ registercommand("+showscores"); diff --git a/src/gs-entbase/server/trigger_teleport.qc b/src/gs-entbase/server/trigger_teleport.qc index 59ab9a47..a7f9222d 100644 --- a/src/gs-entbase/server/trigger_teleport.qc +++ b/src/gs-entbase/server/trigger_teleport.qc @@ -216,23 +216,23 @@ trigger_teleport::Touch(entity eToucher) if (eTarget) { vector endpos = eTarget.origin; - float flSpeed = vlen(eToucher.velocity); + float flSpeed = vlen(eActivator.velocity); makevectors(eTarget.angles); - eToucher.velocity = (v_forward * flSpeed); - eToucher.angles = eTarget.angles; + eActivator.velocity = (v_forward * flSpeed); + eActivator.angles = eTarget.angles; - if (eToucher.flags & FL_CLIENT) { - Client_FixAngle(eToucher, eToucher.angles); + if (eActivator.flags & FL_CLIENT) { + Client_FixAngle(eActivator, eActivator.angles); /* level designers place destinations where the feet are going to be, because monsters are mainly set up to be that way (0 0 0 being ground). players however have their it at the center of mass, so nudge it a little. */ - endpos[2] -= eToucher.mins[2]; + endpos[2] -= eActivator.mins[2]; } /* test if something is in the way. */ - tracebox(endpos, eToucher.mins, eToucher.maxs, endpos, MOVE_NORMAL, eToucher); + tracebox(endpos, eActivator.mins, eActivator.maxs, endpos, MOVE_NORMAL, eActivator); /* indeed something is in the way... */ if (trace_ent && trace_startsolid == true) { @@ -240,11 +240,11 @@ trigger_teleport::Touch(entity eToucher) if (trace_ent.takedamage != DAMAGE_NO) { NSSurfacePropEntity killThis = (NSSurfacePropEntity)trace_ent; killThis.SetHealth(-100); - killThis.Death(this, eToucher, 1000, g_vec_null, 0i); + killThis.Death(this, eActivator, 1000, g_vec_null, 0i); } } - setorigin_safe(eToucher, endpos); + eActivator.SetOriginUnstick(endpos); if (m_sndTeleport) { StartSoundDef(m_sndTeleport, CHAN_VOICE, true); @@ -258,9 +258,9 @@ trigger_teleport::Touch(entity eToucher) StartSoundDef(m_sndTeleportExit, CHAN_VOICE, true); } - EntLog("Teleported %S to %v", eToucher.netname, endpos); + EntLog("Teleported %S to %v", eActivator.netname, endpos); } else { - EntWarning("Failed to teleport %S", eToucher.netname); + EntWarning("Failed to teleport %S", eActivator.netname); } } } diff --git a/src/shared/NSEntity.h b/src/shared/NSEntity.h index 81e862f6..02c7c7b1 100644 --- a/src/shared/NSEntity.h +++ b/src/shared/NSEntity.h @@ -209,6 +209,8 @@ public: nonvirtual void SetAngularVelocity(vector); /** Sets the absolute 3D world position of the entity. */ nonvirtual void SetOrigin(vector); + /** Same as SetOrigin(), but will push the entity out the ground if needed. */ + nonvirtual void SetOriginUnstick(vector); /** Sets the bounding box size of the entity. This affects both collision and rendering bounds checking. */ nonvirtual void SetSize(vector,vector); @@ -419,6 +421,9 @@ public: /** Will read from the named def to perform an attack. */ virtual bool AttackByDef(string, bool); + + /** Sets the @ref bot_info tag on this entity to the desired botInfo_t tag. */ + nonvirtual void SetBotTag(botInfo_t); }; /** Returns a new entity. Guaranteed to be something. Never __NULL__ diff --git a/src/shared/NSEntity.qc b/src/shared/NSEntity.qc index d587a026..89e16c49 100644 --- a/src/shared/NSEntity.qc +++ b/src/shared/NSEntity.qc @@ -638,6 +638,11 @@ NSEntity::SetOrigin(vector newOrigin) { setorigin(this, newOrigin); } +void +NSEntity::SetOriginUnstick(vector newOrigin) { + setorigin_safe(this, newOrigin); +} + void NSEntity::SetModel(string newModel) { m_bIsBrush = substring(newModel, 0, 1) == "*" ? true : false; @@ -1448,6 +1453,13 @@ NSEntity::AttackByDef(string defName, bool wasReleased) return (true); } +void +NSEntity::SetBotTag(botInfo_t newTag) +{ +#ifdef SERVER + botinfo = newTag; +#endif +} int NSEntity::GetSharedID(void) diff --git a/src/shared/NSItem.qc b/src/shared/NSItem.qc index 4c61799e..5b0ad211 100644 --- a/src/shared/NSItem.qc +++ b/src/shared/NSItem.qc @@ -340,7 +340,7 @@ void NSItem::BecomePickup(void) { SetSolid(SOLID_TRIGGER); - botinfo = BOTINFO_WEAPON; + SetBotTag(BOTINFO_WEAPON); if (m_bSpins) modelflags = MF_ROTATE; diff --git a/src/shared/NSMonster.qc b/src/shared/NSMonster.qc index 48eb3f77..b9b80b74 100644 --- a/src/shared/NSMonster.qc +++ b/src/shared/NSMonster.qc @@ -1788,7 +1788,7 @@ NSMonster::Respawn(void) SetOrigin(GetSpawnVector("origin")); NSError("%S: %v, %v", classname, GetAngles(), GetOrigin()); DropToFloor(); - setorigin_safe(this, origin); + SetOriginUnstick(origin); } super::Respawn(); diff --git a/src/shared/NSNavAI.qc b/src/shared/NSNavAI.qc index 8d5e79b5..9b838ab7 100644 --- a/src/shared/NSNavAI.qc +++ b/src/shared/NSNavAI.qc @@ -557,7 +557,7 @@ NSNavAI::PlantCharge(string defName) #endif /* push us outta the way! */ - setorigin_safe(this, GetOrigin()); + SetOriginUnstick(GetOrigin()); return (true); } diff --git a/src/shared/NSSpawnPoint.qc b/src/shared/NSSpawnPoint.qc index 360f052f..f359095f 100644 --- a/src/shared/NSSpawnPoint.qc +++ b/src/shared/NSSpawnPoint.qc @@ -34,9 +34,9 @@ NSSpawnPoint::Respawn(void) super::Respawn(); - setorigin_safe(this, GetSpawnVector("origin")); + SetOriginUnstick(GetSpawnVector("origin")); SetSize(newMins, newMaxs); - botinfo = BOTINFO_SPAWNPOINT; + SetBotTag(BOTINFO_SPAWNPOINT); } void diff --git a/src/shared/NSVehicle.qc b/src/shared/NSVehicle.qc index 2e0fce43..eabe5721 100644 --- a/src/shared/NSVehicle.qc +++ b/src/shared/NSVehicle.qc @@ -455,8 +455,8 @@ NSVehicle::PlayerLeave(NSClientPlayer pl) owner = __NULL__; pl.vv_flags &= ~VFL_INVEHICLE; - pl.velocity = g_vec_null; - setorigin_safe(pl, pl.origin); + pl.ClearVelocity(); + pl.SetOriginUnstick(pl.GetOrigin()); if (m_iVehicleFlags & VHF_FROZEN) pl.vv_flags &= ~VFL_FROZEN; diff --git a/src/shared/NSWeapon.h b/src/shared/NSWeapon.h index 3a3890bf..397ebc59 100644 --- a/src/shared/NSWeapon.h +++ b/src/shared/NSWeapon.h @@ -276,3 +276,4 @@ bool isWeaponClipOnly(string weaponDef); @return true/false whether or not the weapon creates a timed, fused detonating charge of sorts. @param weaponDef the name of the entityDef that defines the weapon.*/ bool isWeaponDetonationTimed(string weaponDef); + diff --git a/src/shared/NSWeapon.qc b/src/shared/NSWeapon.qc index af5f6979..f66824ee 100644 --- a/src/shared/NSWeapon.qc +++ b/src/shared/NSWeapon.qc @@ -123,6 +123,8 @@ NSWeapon::Spawned(void) SetViewModel(m_strWeaponViewModel); SetWorldModel(model); SetPlayerModel(m_strWeaponPlayerModel); + + printf("%S\n", classname); } void @@ -1355,3 +1357,161 @@ isWeaponDetonationTimed(string weaponDef) bool isFused = (bool)stof(EntityDef_GetKeyValue(projectileDef, "detonate_on_fuse")); return (isFused); } + +.NSWeapon m_nextWeapon; +.NSWeapon m_prevWeapon; + +NSWeapon +NSWeapon_SortWeaponChain(NSClientPlayer targetPlayer) +{ + NSWeapon itemChain = targetPlayer.m_itemList; + int heighestSlot = -1i; + int heighestPos = -1i; + NSWeapon firstWeapon, lastWeapon; + + firstWeapon = lastWeapon = __NULL__; + + if (!targetPlayer.m_itemList) { + return __NULL__; + } + + /* first we determine the range of our hud buckets. */ + while (itemChain) { + if (itemChain.IsWeapon() == true) { + int hudSlot = itemChain.GetDefInt("hudSlot"); + int hudPos = itemChain.GetDefInt("hudSlotPos"); + + if (hudSlot > heighestSlot) { + heighestSlot = hudSlot; + } + if (hudPos > heighestPos) { + heighestPos = hudPos; + } + } + + itemChain = itemChain.chain; + } + + for (int hS = 0i; hS <= heighestSlot; hS++) { + for (int hP = 0i; hP <= heighestPos; hP++) { + itemChain = targetPlayer.m_itemList; + + while (itemChain) { + if (itemChain.IsWeapon() == true) { + int hudSlot = itemChain.GetDefInt("hudSlot"); + int hudPos = itemChain.GetDefInt("hudSlotPos"); + + if (hudSlot == hS && hudPos == hP) { + /* first weapon in the chain? */ + if (!lastWeapon) { + firstWeapon = itemChain; + lastWeapon = firstWeapon; + } else { + /* assign this weapon to the last weapon of our chain. */ + lastWeapon.m_nextWeapon = itemChain; + itemChain.m_prevWeapon = lastWeapon; + lastWeapon = itemChain; + } + } + } + + itemChain = itemChain.chain; + } + } + } + + /* test */ + NSWeapon weaponTest = firstWeapon; + while (weaponTest) { + weaponTest = weaponTest.m_nextWeapon; + } + + firstWeapon.m_prevWeapon = lastWeapon; + + return (firstWeapon); +} + +#ifdef CLIENT +bool +NSWeapon_CanSwitch(NSClientPlayer pl) +{ + if (!pl.m_activeWeapon) + return false; + + return true; +} + +void +NSWeapon_SelectWeapon(NSWeapon nextWeapon) +{ + if (!nextWeapon) { + pSeat->m_iHUDWeaponSelected = 0i; + return; + } + + pSeat->m_iHUDWeaponSelected = nextWeapon.GetSharedID(); +} +#endif + +/** Select the next item in the list. */ +void +NSWeapon_NextWeapon(NSNavAI pl) +{ +#ifdef CLIENT + NSWeapon firstWeapon; + + if (NSWeapon_CanSwitch(pl) = false) { + return; + } + + firstWeapon = NSWeapon_SortWeaponChain(pl); + + if (pl.m_activeWeapon.m_nextWeapon) { + NSWeapon_SelectWeapon(pl.m_activeWeapon.m_nextWeapon); + } else { + NSWeapon_SelectWeapon(firstWeapon); + } +#endif +} + +/** Select the previous item in the list. */ +void +NSWeapon_PrevWeapon(NSNavAI pl) +{ +#ifdef CLIENT + NSWeapon firstWeapon; + + if (NSWeapon_CanSwitch(pl) = false) { + return; + } + + firstWeapon = NSWeapon_SortWeaponChain(pl); + + if (pl.m_activeWeapon.m_prevWeapon) { + NSWeapon_SelectWeapon(pl.m_activeWeapon.m_prevWeapon); + } else { + NSWeapon_SelectWeapon(firstWeapon); + } +#endif +} + +/** Select the previous item in the list. */ +void +NSWeapon_LastWeapon(NSNavAI pl) +{ +#ifdef CLIENT + NSWeapon firstWeapon; + + if (NSWeapon_CanSwitch(pl) = false) { + return; + } + + firstWeapon = NSWeapon_SortWeaponChain(pl); + + if (pl.m_activeWeapon.m_prevWeapon) { + NSWeapon_SelectWeapon(pl.m_activeWeapon.m_prevWeapon); + } else { + NSWeapon_SelectWeapon(firstWeapon); + } +#endif +} diff --git a/src/shared/NSWeapon_NSNavAI.h b/src/shared/NSWeapon_NSNavAI.h new file mode 100644 index 00000000..c4ba00f0 --- /dev/null +++ b/src/shared/NSWeapon_NSNavAI.h @@ -0,0 +1,4 @@ + +void NSWeapon_NextWeapon(NSNavAI); +void NSWeapon_PrevWeapon(NSNavAI); +void NSWeapon_LastWeapon(NSNavAI); \ No newline at end of file diff --git a/src/shared/defs.h b/src/shared/defs.h index 54e52fac..15e9f726 100644 --- a/src/shared/defs.h +++ b/src/shared/defs.h @@ -105,6 +105,7 @@ string __fullspawndata; #include "NSItem.h" #include "NSWeapon.h" #include "NSNavAI.h" +#include "NSWeapon_NSNavAI.h" #include "NSMonster.h" #include "NSSquadMonster.h" #include "NSTalkMonster.h" @@ -269,6 +270,64 @@ pseudorandom() return bound(0.01, (seed) / 100.0f, 0.99f); } +#if 0 +__wrap void +WriteByte(float to, float val) +{ + breakpoint(); + prior(to, val); +} + +__wrap void +WriteChar(float to, float val) +{ + breakpoint(); + prior(to, val); +} + +__wrap void +WriteShort(float to, float val) +{ + breakpoint(); + prior(to, val); +} + +__wrap void +WriteLong(float to, float val) +{ + breakpoint(); + prior(to, val); +} + +__wrap void +WriteCoord(float to, float val) +{ + breakpoint(); + prior(to, val); +} + +__wrap void +WriteAngle(float to, float val) +{ + breakpoint(); + prior(to, val); +} + +__wrap void +WriteString(float to, string val) +{ + breakpoint(); + prior(to, val); +} + +__wrap void +WriteEntity(float to, entity val) +{ + breakpoint(); + prior(to, val); +} +#endif + __wrap void setmodel(entity ent, string mname) {