NSEntity: add SetOriginUnstick(), SetBotTag()

NSWeapon: basic inventory management functions
This commit is contained in:
Marco Cawthorne 2024-07-17 14:21:44 -07:00
parent a852f887e2
commit 965d9e96d6
Signed by: eukara
GPG key ID: CE2032F0A2882A22
14 changed files with 274 additions and 31 deletions

View file

@ -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;

View file

@ -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");

View file

@ -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);
}
}
}

View file

@ -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__

View file

@ -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)

View file

@ -340,7 +340,7 @@ void
NSItem::BecomePickup(void)
{
SetSolid(SOLID_TRIGGER);
botinfo = BOTINFO_WEAPON;
SetBotTag(BOTINFO_WEAPON);
if (m_bSpins)
modelflags = MF_ROTATE;

View file

@ -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();

View file

@ -557,7 +557,7 @@ NSNavAI::PlantCharge(string defName)
#endif
/* push us outta the way! */
setorigin_safe(this, GetOrigin());
SetOriginUnstick(GetOrigin());
return (true);
}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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
}

View file

@ -0,0 +1,4 @@
void NSWeapon_NextWeapon(NSNavAI);
void NSWeapon_PrevWeapon(NSNavAI);
void NSWeapon_LastWeapon(NSNavAI);

View file

@ -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)
{