Compare commits
3 commits
dad5071379
...
bd8351db58
Author | SHA1 | Date | |
---|---|---|---|
bd8351db58 | |||
12bb472abc | |||
6078d31f12 |
29 changed files with 1268 additions and 21 deletions
|
@ -1,6 +1,31 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
. ./build.cfg
|
. ./build.cfg
|
||||||
|
|
||||||
|
safe_copy()
|
||||||
|
{
|
||||||
|
if [ -f "$1" ]
|
||||||
|
then
|
||||||
|
cp -v "$1" "$2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
radiant_build()
|
||||||
|
{
|
||||||
|
# copy files over to RADIANT
|
||||||
|
if [ ! -z "$RADIANT_PATH" ]
|
||||||
|
then
|
||||||
|
if [ -d "$RADIANT_PATH/gamepacks/games" ];
|
||||||
|
then
|
||||||
|
./make_mapdef.sh "$1"
|
||||||
|
mkdir -p "$RADIANT_PATH/gamepacks/$1.game/$1/"
|
||||||
|
safe_copy "./$1/radiant.game" "$RADIANT_PATH/gamepacks/games/$1.game"
|
||||||
|
safe_copy "./$1/entities.def" "$RADIANT_PATH/gamepacks/$1.game/$1/entities.def"
|
||||||
|
safe_copy "./$1/radiant.xml" "$RADIANT_PATH/gamepacks/$1.game/default_build_menu.xml"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
if [ "$SKIP_UPDATE" = "1" ]; then
|
if [ "$SKIP_UPDATE" = "1" ]; then
|
||||||
BUILD_UPDATE=0
|
BUILD_UPDATE=0
|
||||||
fi
|
fi
|
||||||
|
@ -34,7 +59,7 @@ if [ -x "$(command -v fteqcc)" ]; then
|
||||||
|
|
||||||
make
|
make
|
||||||
cd "$SCRPATH"
|
cd "$SCRPATH"
|
||||||
./make_mapdef.sh "$1"
|
radiant_build "$1"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -70,10 +95,8 @@ if [ -x "$(command -v fteqcc)" ]; then
|
||||||
cd ..
|
cd ..
|
||||||
export GAMEDIR=$(basename $PWD)
|
export GAMEDIR=$(basename $PWD)
|
||||||
cd $OLDDIR
|
cd $OLDDIR
|
||||||
if [ -f "$SCRPATH"/bin/worldspawn ]; then
|
radiant_build "$GAMEDIR"
|
||||||
./make_mapdef.sh $GAMEDIR
|
|
||||||
fi
|
|
||||||
done;
|
done;
|
||||||
else
|
else
|
||||||
printf "FTEQCC compiler is not present, please run build_engine.sh\n"
|
printf "FTEQCC compiler is not present, please run build_engine.sh\n"
|
||||||
fi
|
fi
|
BIN
platform/base_models.pk3dir/models/b_portal.bsp
Normal file
BIN
platform/base_models.pk3dir/models/b_portal.bsp
Normal file
Binary file not shown.
13
platform/base_models.pk3dir/models/b_portal.map
Normal file
13
platform/base_models.pk3dir/models/b_portal.map
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"spawnflags" "0"
|
||||||
|
"classname" "worldspawn"
|
||||||
|
"wad" "C:\Games\Quake\gmapn\fte.wad"
|
||||||
|
{
|
||||||
|
( -8 64 -80 ) ( -8 64 -64 ) ( -8 -0 -80 ) nodraw -64 64 180 1 -1
|
||||||
|
( -64 64 -80 ) ( -0 64 -80 ) ( -64 64 -64 ) nodraw 0 64 -180 1 -1
|
||||||
|
( -64 64 -64 ) ( -64 -0 -64 ) ( -0 64 -64 ) nodraw 64 0 90 1 1
|
||||||
|
( -0 -0 -64 ) ( -0 64 -64 ) ( -0 -0 -80 ) warpzone 64 64 0 1 1
|
||||||
|
( -0 -64 -64 ) ( -0 -64 -80 ) ( -64 -64 -64 ) nodraw 0 64 -180 1 -1
|
||||||
|
( -0 -0 64 ) ( -64 -0 64 ) ( -0 64 64 ) nodraw 64 0 90 1 1
|
||||||
|
}
|
||||||
|
}
|
10
platform/base_scripts.pk3dir/scripts/drawdebug.shader
Normal file
10
platform/base_scripts.pk3dir/scripts/drawdebug.shader
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
debugcone
|
||||||
|
{
|
||||||
|
cull none
|
||||||
|
|
||||||
|
{
|
||||||
|
rgbGen vertex
|
||||||
|
alphaGen vertex
|
||||||
|
blendFunc blend
|
||||||
|
}
|
||||||
|
}
|
15
platform/base_scripts.pk3dir/scripts/drawportal.shader
Normal file
15
platform/base_scripts.pk3dir/scripts/drawportal.shader
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//used on the front face of the portal entities.
|
||||||
|
warpzone
|
||||||
|
{
|
||||||
|
sort portal
|
||||||
|
surfaceparm nomarks
|
||||||
|
surfaceparm nodlight
|
||||||
|
}
|
||||||
|
|
||||||
|
//used on side+back faces, just to hide them.
|
||||||
|
nodraw
|
||||||
|
{
|
||||||
|
surfaceparm nomarks
|
||||||
|
surfaceparm nodlight
|
||||||
|
surfaceparm nodraw
|
||||||
|
}
|
Binary file not shown.
|
@ -48,6 +48,9 @@ Entity_EntityUpdate(float type, float new)
|
||||||
case ENT_VEHICLE:
|
case ENT_VEHICLE:
|
||||||
basevehicle_readentity(new);
|
basevehicle_readentity(new);
|
||||||
break;
|
break;
|
||||||
|
case ENT_PORTAL:
|
||||||
|
NSPortal_ReadEntity(new);
|
||||||
|
break;
|
||||||
case ENT_VEH_BRUSH:
|
case ENT_VEH_BRUSH:
|
||||||
func_vehicle_readentity(new);
|
func_vehicle_readentity(new);
|
||||||
break;
|
break;
|
||||||
|
@ -142,6 +145,9 @@ Entity_EntityUpdate(float type, float new)
|
||||||
case ENT_PUSH:
|
case ENT_PUSH:
|
||||||
trigger_push_ReadEntity(new);
|
trigger_push_ReadEntity(new);
|
||||||
break;
|
break;
|
||||||
|
case ENT_ENTITYPROJECTILE:
|
||||||
|
NSProjectile_ReadEntity(new);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
//error(sprintf("Unknown entity type update received. (%d)\n", t));
|
//error(sprintf("Unknown entity type update received. (%d)\n", t));
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,3 +148,6 @@ void main(void)
|
||||||
#define SAVE_VECTOR(x,y,z) fputs(x, sprintf("%S \"%v\" ", y, z))
|
#define SAVE_VECTOR(x,y,z) fputs(x, sprintf("%S \"%v\" ", y, z))
|
||||||
#define SAVE_STRING(x,y,z) fputs(x, sprintf("%S \"%s\" ", y, z))
|
#define SAVE_STRING(x,y,z) fputs(x, sprintf("%S \"%s\" ", y, z))
|
||||||
#define SAVE_HEX(x,y,z) fputs(x, sprintf("%S \"%x\" ", y, z))
|
#define SAVE_HEX(x,y,z) fputs(x, sprintf("%S \"%x\" ", y, z))
|
||||||
|
|
||||||
|
NSEntity EntityDef_SpawnClassname(string className);
|
||||||
|
NSEntity EntityDef_CreateClassname(string className);
|
||||||
|
|
|
@ -103,7 +103,7 @@ EntityDef_ReadFile(string filePath)
|
||||||
/* we've reached the end of a definition */
|
/* we've reached the end of a definition */
|
||||||
if (braceDepth == 0) {
|
if (braceDepth == 0) {
|
||||||
/* we have something somewhat valid I guess */
|
/* we have something somewhat valid I guess */
|
||||||
if (currentDef.entClass != "" && currentDef.spawnClass != "") {
|
if (currentDef.entClass != "" /*&& currentDef.spawnClass != ""*/) {
|
||||||
g_entDefTable[g_entDefCount].entClass = currentDef.entClass;
|
g_entDefTable[g_entDefCount].entClass = currentDef.entClass;
|
||||||
g_entDefTable[g_entDefCount].spawnClass = currentDef.spawnClass;
|
g_entDefTable[g_entDefCount].spawnClass = currentDef.spawnClass;
|
||||||
g_entDefTable[g_entDefCount].spawnData = currentDef.spawnData;
|
g_entDefTable[g_entDefCount].spawnData = currentDef.spawnData;
|
||||||
|
@ -184,7 +184,7 @@ EntityDef_PrepareEntity(entity target, int id)
|
||||||
/* check if the spawnclass is an entityDef */
|
/* check if the spawnclass is an entityDef */
|
||||||
for (int i = 0i; i < g_entDefCount; i++) {
|
for (int i = 0i; i < g_entDefCount; i++) {
|
||||||
if (g_entDefTable[id].spawnClass == g_entDefTable[i].entClass) {
|
if (g_entDefTable[id].spawnClass == g_entDefTable[i].entClass) {
|
||||||
EntityDef_PrepareEntity(self, i);
|
EntityDef_PrepareEntity(target, i);
|
||||||
isEntDefBased = true;
|
isEntDefBased = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ EntityDef_PrepareEntity(entity target, int id)
|
||||||
targetEnt.Respawn();
|
targetEnt.Respawn();
|
||||||
|
|
||||||
/* now we rename the classname for better visibility */
|
/* now we rename the classname for better visibility */
|
||||||
self.classname = g_entDefTable[id].entClass;
|
targetEnt.classname = g_entDefTable[id].entClass;
|
||||||
__fullspawndata = "";
|
__fullspawndata = "";
|
||||||
return targetEnt;
|
return targetEnt;
|
||||||
}
|
}
|
||||||
|
@ -248,4 +248,56 @@ EntityDef_SpawnClassname(string className)
|
||||||
}
|
}
|
||||||
|
|
||||||
return __NULL__;
|
return __NULL__;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSEntity
|
||||||
|
EntityDef_CreateClassname(string className)
|
||||||
|
{
|
||||||
|
entity oldSelf = self;
|
||||||
|
NSEntity new = spawn(NSEntity);
|
||||||
|
self = new;
|
||||||
|
EntityDef_SpawnClassname(className);
|
||||||
|
self = oldSelf;
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
EntityDef_GetKeyValue(string className, string keyName)
|
||||||
|
{
|
||||||
|
float spawnWords = 0;
|
||||||
|
string inheritKeys = __NULL__;
|
||||||
|
|
||||||
|
/* loop through all defs */
|
||||||
|
for (int i = 0i; i < g_entDefCount; i++) {
|
||||||
|
/* found the right def */
|
||||||
|
//print(sprintf("%S %S\n", className, g_entDefTable[i].entClass));
|
||||||
|
if (className == g_entDefTable[i].entClass) {
|
||||||
|
inheritKeys = g_entDefTable[i].inheritKeys;
|
||||||
|
spawnWords = tokenize_console(g_entDefTable[i].spawnData);
|
||||||
|
|
||||||
|
/* iterate over our own spawnkeys first */
|
||||||
|
for (int c = 0i; c < spawnWords; c+= 2i) {
|
||||||
|
if (argv(c) == keyName) {
|
||||||
|
return argv(c+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found, look into the inherit keyword's spawndata */
|
||||||
|
if (inheritKeys == __NULL__)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
for (int b = 0i; b < g_entDefCount; i++) {
|
||||||
|
if (inheritKeys == g_entDefTable[b].entClass) {
|
||||||
|
spawnWords = tokenize_console(g_entDefTable[b].spawnData);
|
||||||
|
for (int c = 0i; c < spawnWords; c+= 2i) {
|
||||||
|
if (argv(c) == keyName) {
|
||||||
|
return argv(c+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
|
@ -775,10 +775,10 @@ to remove in case we won't initialize it.
|
||||||
void
|
void
|
||||||
CheckSpawn(void() spawnfunc)
|
CheckSpawn(void() spawnfunc)
|
||||||
{
|
{
|
||||||
if (EntityDef_SpawnClassname(self.classname))
|
|
||||||
return;
|
|
||||||
if (MapTweak_EntitySpawn(self))
|
if (MapTweak_EntitySpawn(self))
|
||||||
return;
|
return;
|
||||||
|
if (EntityDef_SpawnClassname(self.classname))
|
||||||
|
return;
|
||||||
|
|
||||||
if (spawnfunc) {
|
if (spawnfunc) {
|
||||||
spawnfunc();
|
spawnfunc();
|
||||||
|
|
|
@ -47,3 +47,14 @@ Skill_GetValue(string variable, float defaultvalue)
|
||||||
float val = fabs(cvar(sprintf("sk_%s%d", variable, skill)));
|
float val = fabs(cvar(sprintf("sk_%s%d", variable, skill)));
|
||||||
return (val == 0) ? defaultvalue : val;
|
return (val == 0) ? defaultvalue : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* input string is potentially a skill variable */
|
||||||
|
float
|
||||||
|
Skill_GetDefValue(string variable)
|
||||||
|
{
|
||||||
|
if (substring(variable, 0, 6) == "skill:") {
|
||||||
|
return Skill_GetValue(substring(variable, 6, -1), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stof(variable);
|
||||||
|
}
|
|
@ -14,6 +14,8 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
noref .vector v_angle;
|
||||||
|
|
||||||
/** This entity class represents every player client.
|
/** This entity class represents every player client.
|
||||||
|
|
||||||
When clients connect via the connect command, they will findthemselves
|
When clients connect via the connect command, they will findthemselves
|
||||||
|
@ -116,7 +118,7 @@ private:
|
||||||
PREDICTED_FLOAT(viewzoom)
|
PREDICTED_FLOAT(viewzoom)
|
||||||
PREDICTED_VECTOR_N(view_ofs)
|
PREDICTED_VECTOR_N(view_ofs)
|
||||||
PREDICTED_VECTOR_N(basevelocity)
|
PREDICTED_VECTOR_N(basevelocity)
|
||||||
PREDICTED_VECTOR(v_angle)
|
PREDICTED_VECTOR_N(v_angle)
|
||||||
PREDICTED_FLOAT_N(pmove_flags)
|
PREDICTED_FLOAT_N(pmove_flags)
|
||||||
|
|
||||||
PREDICTED_FLOAT(w_attack_next)
|
PREDICTED_FLOAT(w_attack_next)
|
||||||
|
|
|
@ -27,9 +27,14 @@ public:
|
||||||
virtual void Respawn(void);
|
virtual void Respawn(void);
|
||||||
virtual void SpawnKey(string, string);
|
virtual void SpawnKey(string, string);
|
||||||
|
|
||||||
virtual void SetItem(int i);
|
nonvirtual void SetItem(int i);
|
||||||
virtual void SetFloating(int);
|
nonvirtual int GetItem(void);
|
||||||
virtual void PickupRespawn(void);
|
nonvirtual void SetFloating(int);
|
||||||
|
nonvirtual bool GetFloating(void);
|
||||||
|
nonvirtual void SetSpinning(bool);
|
||||||
|
nonvirtual bool GetSpinning(void);
|
||||||
|
|
||||||
|
nonvirtual void PickupRespawn(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_iClip;
|
int m_iClip;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#ifdef SERVER
|
#ifdef SERVER
|
||||||
void NSItem::NSItem(void)
|
void NSItem::NSItem(void)
|
||||||
{
|
{
|
||||||
m_iClip = 0i;
|
m_iClip = -1;
|
||||||
m_iWasDropped = 0i;
|
m_iWasDropped = 0i;
|
||||||
m_iInvItem = 0i;
|
m_iInvItem = 0i;
|
||||||
m_sndAcquire = __NULL__;
|
m_sndAcquire = __NULL__;
|
||||||
|
@ -122,11 +122,36 @@ void NSItem::SetItem(int i)
|
||||||
SetSize([-16,-16,0], [16,16,16]);
|
SetSize([-16,-16,0], [16,16,16]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
NSItem::GetItem(void)
|
||||||
|
{
|
||||||
|
return m_iInvItem;
|
||||||
|
}
|
||||||
|
|
||||||
void NSItem::SetFloating(int i)
|
void NSItem::SetFloating(int i)
|
||||||
{
|
{
|
||||||
m_bFloating = i ? true : false;
|
m_bFloating = i ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NSItem::GetFloating(void)
|
||||||
|
{
|
||||||
|
return m_bFloating;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSItem::SetSpinning(bool value)
|
||||||
|
{
|
||||||
|
m_bSpins = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NSItem::GetSpinning(void)
|
||||||
|
{
|
||||||
|
return m_bSpins;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
NSItem::PickupRespawn(void)
|
NSItem::PickupRespawn(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -261,6 +261,8 @@ private:
|
||||||
/* animation cycles */
|
/* animation cycles */
|
||||||
float m_flAnimTime;
|
float m_flAnimTime;
|
||||||
|
|
||||||
|
PREDICTED_VECTOR_N(view_ofs)
|
||||||
|
|
||||||
nonvirtual void _LerpTurnToEnemy(float);
|
nonvirtual void _LerpTurnToEnemy(float);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -382,6 +384,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CLIENT
|
#ifdef CLIENT
|
||||||
|
nonvirtual void _RenderDebugViewCone();
|
||||||
|
|
||||||
|
/** overrides */
|
||||||
virtual void customphysics(void);
|
virtual void customphysics(void);
|
||||||
virtual float predraw(void);
|
virtual float predraw(void);
|
||||||
virtual void ReceiveEntity(float,float);
|
virtual void ReceiveEntity(float,float);
|
||||||
|
|
|
@ -344,13 +344,13 @@ NSMonster::SeeThink(void)
|
||||||
|
|
||||||
/* first, is the potential enemy in our field of view? */
|
/* first, is the potential enemy in our field of view? */
|
||||||
makevectors(angles);
|
makevectors(angles);
|
||||||
vector v = normalize(w.origin - origin);
|
vector v = normalize(w.origin - GetEyePos());
|
||||||
float flDot = v * v_forward;
|
float flDot = v * v_forward;
|
||||||
|
|
||||||
if (flDot < SeeFOV()/180)
|
if (flDot < SeeFOV()/180)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
traceline(origin, w.origin, MOVE_EVERYTHING, this);
|
traceline(GetEyePos(), w.origin, MOVE_EVERYTHING, this);
|
||||||
|
|
||||||
/* we have line of sight with the player */
|
/* we have line of sight with the player */
|
||||||
if (trace_fraction == 1.0f || trace_ent == w) {
|
if (trace_fraction == 1.0f || trace_ent == w) {
|
||||||
|
@ -926,6 +926,7 @@ NSMonster::EvaluateEntity(void)
|
||||||
EVALUATE_VECTOR(angles, 1, MONFL_CHANGED_ANGLES_Y)
|
EVALUATE_VECTOR(angles, 1, MONFL_CHANGED_ANGLES_Y)
|
||||||
EVALUATE_VECTOR(angles, 2, MONFL_CHANGED_ANGLES_Z)
|
EVALUATE_VECTOR(angles, 2, MONFL_CHANGED_ANGLES_Z)
|
||||||
EVALUATE_FIELD(modelindex, MONFL_CHANGED_MODELINDEX)
|
EVALUATE_FIELD(modelindex, MONFL_CHANGED_MODELINDEX)
|
||||||
|
EVALUATE_VECTOR(view_ofs, 2, MONFL_CHANGED_MODELINDEX)
|
||||||
EVALUATE_FIELD(solid, MONFL_CHANGED_SOLID)
|
EVALUATE_FIELD(solid, MONFL_CHANGED_SOLID)
|
||||||
EVALUATE_FIELD(movetype, MONFL_CHANGED_FLAGS)
|
EVALUATE_FIELD(movetype, MONFL_CHANGED_FLAGS)
|
||||||
EVALUATE_FIELD(flags, MONFL_CHANGED_FLAGS)
|
EVALUATE_FIELD(flags, MONFL_CHANGED_FLAGS)
|
||||||
|
@ -973,6 +974,7 @@ NSMonster::SendEntity(entity ePEnt, float flChanged)
|
||||||
SENDENTITY_ANGLE(angles[1], MONFL_CHANGED_ANGLES_Y)
|
SENDENTITY_ANGLE(angles[1], MONFL_CHANGED_ANGLES_Y)
|
||||||
SENDENTITY_ANGLE(angles[2], MONFL_CHANGED_ANGLES_Z)
|
SENDENTITY_ANGLE(angles[2], MONFL_CHANGED_ANGLES_Z)
|
||||||
SENDENTITY_SHORT(modelindex, MONFL_CHANGED_MODELINDEX)
|
SENDENTITY_SHORT(modelindex, MONFL_CHANGED_MODELINDEX)
|
||||||
|
SENDENTITY_BYTE(view_ofs[2], MONFL_CHANGED_MODELINDEX)
|
||||||
SENDENTITY_BYTE(solid, MONFL_CHANGED_SOLID)
|
SENDENTITY_BYTE(solid, MONFL_CHANGED_SOLID)
|
||||||
SENDENTITY_BYTE(movetype, MONFL_CHANGED_FLAGS)
|
SENDENTITY_BYTE(movetype, MONFL_CHANGED_FLAGS)
|
||||||
SENDENTITY_INT(flags, MONFL_CHANGED_FLAGS)
|
SENDENTITY_INT(flags, MONFL_CHANGED_FLAGS)
|
||||||
|
@ -1027,6 +1029,8 @@ NSMonster::predraw(void)
|
||||||
frame2time = frame1time;
|
frame2time = frame1time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_RenderDebugViewCone();
|
||||||
|
|
||||||
return render;
|
return render;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,6 +1049,7 @@ NSMonster::ReceiveEntity(float flNew, float flChanged)
|
||||||
READENTITY_ANGLE(angles[1], MONFL_CHANGED_ANGLES_Y)
|
READENTITY_ANGLE(angles[1], MONFL_CHANGED_ANGLES_Y)
|
||||||
READENTITY_ANGLE(angles[2], MONFL_CHANGED_ANGLES_Z)
|
READENTITY_ANGLE(angles[2], MONFL_CHANGED_ANGLES_Z)
|
||||||
READENTITY_SHORT(modelindex, MONFL_CHANGED_MODELINDEX)
|
READENTITY_SHORT(modelindex, MONFL_CHANGED_MODELINDEX)
|
||||||
|
READENTITY_BYTE(view_ofs[2], MONFL_CHANGED_MODELINDEX)
|
||||||
READENTITY_BYTE(solid, MONFL_CHANGED_SOLID)
|
READENTITY_BYTE(solid, MONFL_CHANGED_SOLID)
|
||||||
READENTITY_BYTE(movetype, MONFL_CHANGED_FLAGS)
|
READENTITY_BYTE(movetype, MONFL_CHANGED_FLAGS)
|
||||||
READENTITY_INT(flags, MONFL_CHANGED_FLAGS)
|
READENTITY_INT(flags, MONFL_CHANGED_FLAGS)
|
||||||
|
@ -1081,6 +1086,37 @@ NSMonster::ReceiveEntity(float flNew, float flChanged)
|
||||||
|
|
||||||
setorigin(this, origin);
|
setorigin(this, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSMonster::_RenderDebugViewCone(void)
|
||||||
|
{
|
||||||
|
vector v;
|
||||||
|
float flDot;
|
||||||
|
vector testOrg;
|
||||||
|
|
||||||
|
if (autocvar(r_showViewCone, 0) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
makevectors(angles);
|
||||||
|
testOrg = pSeat->m_ePlayer.origin;
|
||||||
|
v = normalize(testOrg - GetEyePos());
|
||||||
|
flDot = v * v_forward;
|
||||||
|
|
||||||
|
/* not inside our FoV at all */
|
||||||
|
if (flDot < 90.0f/180) {
|
||||||
|
drawcone(GetEyePos(), angles, 16, 60, 90, [0.25,0,0], 0.25f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
traceline(GetEyePos(), testOrg, MOVE_EVERYTHING, this);
|
||||||
|
|
||||||
|
/* we have line of sight with the client */
|
||||||
|
if (trace_fraction == 1.0f || trace_ent == pSeat->m_ePlayer) {
|
||||||
|
drawcone(GetEyePos(), angles, 16, 60, 90, [1,0,0], 0.75f);
|
||||||
|
} else { /* in FoV, no line of sight */
|
||||||
|
drawcone(GetEyePos(), angles, 16, 60, 90, [1,1,1], 0.25f);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CLIENT
|
#ifdef CLIENT
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef MAX_AMMO_TYPES
|
||||||
|
#define MAX_AMMO_TYPES 16
|
||||||
|
#endif
|
||||||
|
|
||||||
/** This entity class represents a moving/pathfinding object.
|
/** This entity class represents a moving/pathfinding object.
|
||||||
It knows how to deal with waypoint based nodes and possibly other
|
It knows how to deal with waypoint based nodes and possibly other
|
||||||
types of pathfinding in the future.
|
types of pathfinding in the future.
|
||||||
|
@ -29,6 +33,9 @@ private:
|
||||||
nodeslist_t *m_pRoute;
|
nodeslist_t *m_pRoute;
|
||||||
vector m_vecLastNode;
|
vector m_vecLastNode;
|
||||||
vector m_vecTurnAngle;
|
vector m_vecTurnAngle;
|
||||||
|
|
||||||
|
/* These are defined in side defs\*.def, ammo_types and ammo_names */
|
||||||
|
int m_iAmmoTypes[MAX_AMMO_TYPES];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -23,6 +23,9 @@ NSNavAI::NSNavAI(void)
|
||||||
m_pRoute = __NULL__;
|
m_pRoute = __NULL__;
|
||||||
m_vecLastNode = [0,0,0];
|
m_vecLastNode = [0,0,0];
|
||||||
m_vecTurnAngle = [0,0,0];
|
m_vecTurnAngle = [0,0,0];
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_AMMO_TYPES; i++)
|
||||||
|
m_iAmmoTypes[i] = 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
96
src/shared/NSPortal.h
Normal file
96
src/shared/NSPortal.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2022 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
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enumflags
|
||||||
|
{
|
||||||
|
PORTALFL_CHANGED_ORIGIN_X,
|
||||||
|
PORTALFL_CHANGED_ORIGIN_Y,
|
||||||
|
PORTALFL_CHANGED_ORIGIN_Z,
|
||||||
|
PORTALFL_CHANGED_ANGLES_X,
|
||||||
|
PORTALFL_CHANGED_ANGLES_Y,
|
||||||
|
PORTALFL_CHANGED_ANGLES_Z,
|
||||||
|
PORTALFL_CHANGED_TARG_ENTITY,
|
||||||
|
PORTALFL_CHANGED_TARG_ORIGIN_X,
|
||||||
|
PORTALFL_CHANGED_TARG_ORIGIN_Y,
|
||||||
|
PORTALFL_CHANGED_TARG_ORIGIN_Z,
|
||||||
|
PORTALFL_CHANGED_TARG_ANGLES_X,
|
||||||
|
PORTALFL_CHANGED_TARG_ANGLES_Y,
|
||||||
|
PORTALFL_CHANGED_TARG_ANGLES_Z
|
||||||
|
} nsportal_changed_t;
|
||||||
|
|
||||||
|
class
|
||||||
|
NSPortal:NSEntity
|
||||||
|
{
|
||||||
|
void NSPortal(void);
|
||||||
|
|
||||||
|
nonvirtual void _PortalUpdated(void);
|
||||||
|
nonvirtual vector _OriginTransform(vector);
|
||||||
|
nonvirtual vector _DirectionTransform(vector);
|
||||||
|
|
||||||
|
/** overrides */
|
||||||
|
virtual vector camera_transform(vector, vector);
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
virtual void EvaluateEntity(void);
|
||||||
|
virtual float SendEntity(entity, float);
|
||||||
|
|
||||||
|
/** Sets the NSPortal ID. Only used to link portals together via PortalAutoLink. */
|
||||||
|
nonvirtual void SetPortalID(int);
|
||||||
|
/** Will link this portal to another NSPortal. */
|
||||||
|
nonvirtual bool PortalLinkTo(NSPortal);
|
||||||
|
/** Will link this portal to the youngest other NSPortal. */
|
||||||
|
nonvirtual void PortalAutoLink(void);
|
||||||
|
#endif
|
||||||
|
#ifdef CLIENT
|
||||||
|
virtual void ReceiveEntity(float, float);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
NSPortal m_ePortalTarget;
|
||||||
|
NSPortal m_ePortalTarget_net;
|
||||||
|
PREDICTED_VECTOR(m_vecTargetPos)
|
||||||
|
PREDICTED_VECTOR(m_vecTargetAngle)
|
||||||
|
|
||||||
|
vector m_vecPortalPos;
|
||||||
|
vector m_vecPortalN;
|
||||||
|
vector m_vecPortalS;
|
||||||
|
vector m_vecPortalT;
|
||||||
|
|
||||||
|
/** Will transport an entity from its position to the exit position. */
|
||||||
|
nonvirtual void TransportEntity(NSEntity);
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
vector m_vecTargetPos;
|
||||||
|
vector m_vecTargetN;
|
||||||
|
vector m_vecTargetS;
|
||||||
|
vector m_vecTargetT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
int m_iPortalValue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int m_brushNum;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
void NSPortal_ReadEntity(bool);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SOLID_PORTAL 21
|
||||||
|
|
||||||
|
.float portalnum;
|
||||||
|
.float impulse; //used as the radius for the solid_portal csg subtraction
|
412
src/shared/NSPortal.qc
Normal file
412
src/shared/NSPortal.qc
Normal file
|
@ -0,0 +1,412 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Vera Visions LLC.
|
||||||
|
* Copyright (c) 2014 David Walton
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PORTAL_MINS [8, -64, -64]
|
||||||
|
#define PORTAL_MAXS [0, 64, 64]
|
||||||
|
|
||||||
|
void
|
||||||
|
NSPortal::NSPortal(void)
|
||||||
|
{
|
||||||
|
m_ePortalTarget = __NULL__;
|
||||||
|
m_ePortalTarget_net = __NULL__;
|
||||||
|
m_vecTargetPos = g_vec_null;
|
||||||
|
m_vecTargetAngle = g_vec_null;
|
||||||
|
m_vecPortalPos = g_vec_null;
|
||||||
|
m_vecPortalN = g_vec_null;
|
||||||
|
m_vecPortalS = g_vec_null;
|
||||||
|
m_vecPortalT = g_vec_null;
|
||||||
|
m_brushNum = -1;
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
m_vecTargetPos = g_vec_null;
|
||||||
|
m_vecTargetN = g_vec_null;
|
||||||
|
m_vecTargetS = g_vec_null;
|
||||||
|
m_vecTargetT = g_vec_null;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
|
||||||
|
pvsflags = PVSF_NOREMOVE;
|
||||||
|
frame1time = 0.0f;
|
||||||
|
m_iPortalValue = -1;
|
||||||
|
|
||||||
|
/* unique portal IDs */
|
||||||
|
{
|
||||||
|
float numPortals = 0;
|
||||||
|
for (NSPortal e = __NULL__; (e = (NSPortal)find(e, ::classname, "NSPortal"));) {
|
||||||
|
e.portalnum = numPortals++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
void
|
||||||
|
NSPortal::PortalAutoLink(void)
|
||||||
|
{
|
||||||
|
/* this just links against the youngest portal of the same ID at this time */
|
||||||
|
NSPortal youngestPortal, oldestPortal;
|
||||||
|
oldestPortal = youngestPortal = __NULL__;
|
||||||
|
float youngestTime = 99999.0f;
|
||||||
|
float oldestTime = 0.0f;
|
||||||
|
|
||||||
|
/* delete any portal with the same id */
|
||||||
|
for (NSPortal e = __NULL__; (e = (NSPortal)find(e, ::classname, "NSPortal"));) {
|
||||||
|
if (e == this)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* find first AND last portal */
|
||||||
|
if (e.m_iPortalValue == m_iPortalValue) {
|
||||||
|
if (oldestTime < e.frame1time) {
|
||||||
|
oldestTime = e.frame1time;
|
||||||
|
oldestPortal = e;
|
||||||
|
}
|
||||||
|
if (youngestTime > e.frame1time) {
|
||||||
|
youngestTime = e.frame1time;
|
||||||
|
youngestPortal = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove the first portal from the world */
|
||||||
|
if (youngestPortal != oldestPortal) {
|
||||||
|
oldestPortal.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
PortalLinkTo(youngestPortal);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NSPortal::PortalLinkTo(NSPortal target)
|
||||||
|
{
|
||||||
|
m_ePortalTarget = target;
|
||||||
|
skin = m_ePortalTarget ? 0 : 1;
|
||||||
|
SendFlags |= 1;
|
||||||
|
_PortalUpdated();
|
||||||
|
|
||||||
|
if (m_ePortalTarget)
{
|
||||||
|
m_ePortalTarget.m_ePortalTarget = this;
|
||||||
|
m_ePortalTarget.skin = skin;
|
||||||
|
m_ePortalTarget.SendFlags |= 1;
|
||||||
|
m_ePortalTarget._PortalUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
return target ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSPortal::SetPortalID(int value)
|
||||||
|
{
|
||||||
|
m_iPortalValue = value;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
NSPortal::_PortalUpdated(void)
|
||||||
|
{
|
||||||
|
/* the displayed surface must be in a known position.
|
||||||
|
we're not going to compensate for the model here, because I'm too lazy.
*/
|
||||||
|
vector newAngles = angles;
|
||||||
|
//newAngles[0] * -1;
|
||||||
|
makevectors(newAngles);
|
||||||
|
|
||||||
|
m_vecPortalN = v_forward;
|
||||||
|
m_vecPortalS = -v_right;
|
||||||
|
m_vecPortalT = v_up;
|
||||||
|
m_vecPortalPos = origin;
|
||||||
|
|
||||||
|
/* expand the size of the object along the plane, and set up a portal region.
*/
|
||||||
|
movetype = MOVETYPE_NONE;
|
||||||
|
solid = skin ? SOLID_BSP : SOLID_PORTAL;
|
||||||
|
precache_model("models/b_portal.bsp");
|
||||||
|
setmodel(this, "models/b_portal.bsp");
|
||||||
|
|
||||||
|
/* determine size of major axis
*/
|
||||||
|
float portalSize = max(size[0], size[1], size[2]);
|
||||||
|
impulse = portalSize; /* let the engine know how wide the portal should be
*/
|
||||||
|
|
||||||
|
/* make sure the abs size contains the entire portal.
*/
|
||||||
|
portalSize = sqrt(portalSize * portalSize * 2);
|
||||||
|
mins -= portalSize * [1, 1, 1];
|
||||||
|
maxs += portalSize * [1, 1, 1];
|
||||||
|
setsize(this, mins, maxs);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector
|
||||||
|
NSPortal::_DirectionTransform(vector v)
|
||||||
|
{
|
||||||
|
/* FIXME: this should include .angles stuff
*/
|
||||||
|
vector tmp, r;
|
||||||
|
tmp[0] = v * m_vecPortalN;
|
||||||
|
tmp[1] = v * m_vecPortalS;
|
||||||
|
tmp[2] = v * m_vecPortalT;
|
||||||
|
|
||||||
|
r = [0, 0, 0];
|
||||||
|
|
||||||
|
if (!m_ePortalTarget)
{
|
||||||
|
#ifdef CSQC
|
||||||
|
r += tmp[2] * m_vecTargetT;
|
||||||
|
r -= tmp[1] * m_vecTargetS;
|
||||||
|
r -= tmp[0] * m_vecTargetN;
|
||||||
|
#else
|
||||||
|
r += tmp[2] * this.m_vecPortalT;
|
||||||
|
r -= tmp[1] * this.m_vecPortalS;
|
||||||
|
r -= tmp[0] * this.m_vecPortalN;
|
||||||
|
#endif
|
||||||
|
}
else
{
|
||||||
|
r += tmp[2] * m_ePortalTarget.m_vecPortalT;
|
||||||
|
r -= tmp[1] * m_ePortalTarget.m_vecPortalS;
|
||||||
|
r -= tmp[0] * m_ePortalTarget.m_vecPortalN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector
|
||||||
|
NSPortal::_OriginTransform(vector p)
|
||||||
|
{
|
||||||
|
if (!m_ePortalTarget)
{
|
||||||
|
#ifdef CSQC
|
||||||
|
return m_vecTargetPos - _DirectionTransform(m_vecPortalPos - p);
|
||||||
|
#else
|
||||||
|
return this.m_vecPortalPos - _DirectionTransform(m_vecPortalPos - p);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_ePortalTarget.m_vecPortalPos - _DirectionTransform(m_vecPortalPos - p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to generate forward/right/up vectors
|
||||||
|
// return value is the new view origin.
|
||||||
|
// trace_end_pos needs to contain the pvs origin.
|
||||||
|
vector
|
||||||
|
NSPortal::camera_transform(vector originalOrg, vector originalAngles)
|
||||||
|
{
|
||||||
|
vector newCameraPos;
|
||||||
|
|
||||||
|
newCameraPos = _OriginTransform(originalOrg);
|
||||||
|
v_forward = _DirectionTransform(v_forward);
|
||||||
|
v_right = _DirectionTransform(v_right);
|
||||||
|
v_up = _DirectionTransform(v_up);
|
||||||
|
|
||||||
|
//trace from the center of the target to the view, to set trace_endpos for the pvs origin
|
||||||
|
if (m_ePortalTarget)
|
||||||
|
traceline(m_ePortalTarget.m_vecPortalPos, newCameraPos, MOVE_NOMONSTERS, this);
|
||||||
|
else
|
||||||
|
trace_endpos = this.m_vecPortalPos;
|
||||||
|
|
||||||
|
return newCameraPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* because when using custom player physics, the engine will not do us any favors
|
||||||
|
we have to do the portal transformation manually. DO NOT USE THIS METHOD YOURSELF
|
||||||
|
unless you really know what you're doing. This is a private method! */
|
||||||
|
void
|
||||||
|
NSPortal::TransportEntity(NSEntity target)
|
||||||
|
{
|
||||||
|
static void getMatrixDiff(vector aX, vector aY, vector aZ, vector bX, vector bY, vector bZ) {
|
||||||
|
v_forward.x = aX.x * bX.x + aY.x * bX.y + aZ.x * bX.z;
|
||||||
|
v_forward.y = aX.y * bX.x + aY.y * bX.y + aZ.y * bX.z;
|
||||||
|
v_forward.z = aX.z * bX.x + aY.z * bX.y + aZ.z * bX.z;
|
||||||
|
|
||||||
|
v_right.x = aX.x * bY.x + aY.x * bY.y + aZ.x * bY.z;
|
||||||
|
v_right.y = aX.y * bY.x + aY.y * bY.y + aZ.y * bY.z;
|
||||||
|
v_right.z = aX.z * bY.x + aY.z * bY.y + aZ.z * bY.z;
|
||||||
|
|
||||||
|
v_up.x = aX.x * bZ.x + aY.x * bZ.y + aZ.x * bZ.z;
|
||||||
|
v_up.y = aX.y * bZ.x + aY.y * bZ.y + aZ.y * bZ.z;
|
||||||
|
v_up.z = aX.z * bZ.x + aY.z * bZ.y + aZ.z * bZ.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector offsetPos;
|
||||||
|
vector portalAngleX, portalAngleY, portalAngleZ;
|
||||||
|
vector exitAngleX, exitAngleY, exitAngleZ;
|
||||||
|
vector playerDelta;
|
||||||
|
vector targetAngleX, targetAngleY, targetAngleZ;
|
||||||
|
vector playerVelX, playerVelY, playerVelZ;
|
||||||
|
vector angleDiff;
|
||||||
|
float totalSpeed;
|
||||||
|
|
||||||
|
/* angle matrix of the portal entry */
|
||||||
|
makevectors(GetAngles());
|
||||||
|
portalAngleX = v_forward * -1;
|
||||||
|
portalAngleY = v_right * -1;
|
||||||
|
portalAngleZ = v_up;
|
||||||
|
|
||||||
|
/* matrix of target entity angles */
|
||||||
|
if (target.flags & FL_CLIENT) {
|
||||||
|
makevectors(input_angles);
|
||||||
|
} else {
|
||||||
|
makevectors(target.GetAngles());
|
||||||
|
}
|
||||||
|
targetAngleX = v_forward;
|
||||||
|
targetAngleY = v_right;
|
||||||
|
targetAngleZ = v_up;
|
||||||
|
|
||||||
|
/* angle matrix of portal exit */
|
||||||
|
makevectors(m_ePortalTarget.GetAngles());
|
||||||
|
exitAngleX = v_forward;
|
||||||
|
exitAngleY = v_right;
|
||||||
|
exitAngleZ = v_up;
|
||||||
|
|
||||||
|
/* ! CALCULATE THE NEW POSITION - START ! */
|
||||||
|
/* get the offset */
|
||||||
|
offsetPos = target.GetOrigin() - GetOrigin();
|
||||||
|
|
||||||
|
/* calculate the delta of player pos to portal using said angle matrix */
|
||||||
|
playerDelta[0] = dotproduct(offsetPos, portalAngleX);
|
||||||
|
playerDelta[1] = dotproduct(offsetPos, portalAngleY);
|
||||||
|
playerDelta[2] = dotproduct(offsetPos, portalAngleZ);
|
||||||
|
|
||||||
|
/* now, translate the offset to the exit angle */
|
||||||
|
offsetPos = m_ePortalTarget.GetOrigin();
|
||||||
|
offsetPos += exitAngleX * playerDelta[0];
|
||||||
|
offsetPos += exitAngleY * playerDelta[1];
|
||||||
|
offsetPos += exitAngleZ * playerDelta[2];
|
||||||
|
target.SetOrigin(offsetPos); /* apply the new position */
|
||||||
|
|
||||||
|
/* ! CALCULATE THE NEW ANGLE - START ! */
|
||||||
|
/* get the difference between the two rotational matrices */
|
||||||
|
getMatrixDiff(portalAngleX, portalAngleY, portalAngleZ * -1, targetAngleX, targetAngleY, targetAngleZ);
|
||||||
|
angleDiff = vectoangles(v_forward, -v_up); /* we now have an euler angle */
|
||||||
|
|
||||||
|
/* apply the new angles */
|
||||||
|
if (target.flags & FL_CLIENT) {
|
||||||
|
input_angles = m_ePortalTarget.GetAngles() - angleDiff;
|
||||||
|
target.v_angle = input_angles;
|
||||||
|
//Client_FixAngle(this, target.v_angle);
|
||||||
|
} else {
|
||||||
|
target.angles = m_ePortalTarget.GetAngles() - angleDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ! CALCULATE DESTINATION VELOCITY - START ! */
|
||||||
|
/* let's get the current speed first */
|
||||||
|
totalSpeed = vlen(target.GetVelocity());
|
||||||
|
/* convert target velocity into a direction matrix */
|
||||||
|
makevectors(vectoangles(target.GetVelocity()));
|
||||||
|
playerVelX = v_forward;
|
||||||
|
playerVelY = v_right;
|
||||||
|
playerVelZ = v_up;
|
||||||
|
getMatrixDiff(portalAngleX, portalAngleY, portalAngleZ, playerVelX, playerVelY, playerVelZ);
|
||||||
|
angleDiff = vectoangles(v_forward, v_up); /* we now have an euler angle again */
|
||||||
|
/* get the new movement direction relative to the exit portal */
|
||||||
|
makevectors(m_ePortalTarget.GetAngles() + angleDiff);
|
||||||
|
/* apply the final velocity */
|
||||||
|
target.SetVelocity(v_forward * totalSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
void
|
||||||
|
NSPortal::EvaluateEntity(void)
|
||||||
|
{
|
||||||
|
EVALUATE_VECTOR(origin, 0, PORTALFL_CHANGED_ORIGIN_X)
|
||||||
|
EVALUATE_VECTOR(origin, 1, PORTALFL_CHANGED_ORIGIN_Y)
|
||||||
|
EVALUATE_VECTOR(origin, 2, PORTALFL_CHANGED_ORIGIN_Z)
|
||||||
|
EVALUATE_VECTOR(angles, 0, PORTALFL_CHANGED_ANGLES_X)
|
||||||
|
EVALUATE_VECTOR(angles, 1, PORTALFL_CHANGED_ANGLES_Y)
|
||||||
|
EVALUATE_VECTOR(angles, 2, PORTALFL_CHANGED_ANGLES_Z)
|
||||||
|
EVALUATE_FIELD(m_ePortalTarget, PORTALFL_CHANGED_TARG_ENTITY)
|
||||||
|
EVALUATE_VECTOR(m_vecTargetPos, 0, PORTALFL_CHANGED_TARG_ORIGIN_X)
|
||||||
|
EVALUATE_VECTOR(m_vecTargetPos, 1, PORTALFL_CHANGED_TARG_ORIGIN_Y)
|
||||||
|
EVALUATE_VECTOR(m_vecTargetPos, 2, PORTALFL_CHANGED_TARG_ORIGIN_Z)
|
||||||
|
EVALUATE_VECTOR(m_vecTargetAngle, 0, PORTALFL_CHANGED_TARG_ANGLES_X)
|
||||||
|
EVALUATE_VECTOR(m_vecTargetAngle, 1, PORTALFL_CHANGED_TARG_ANGLES_Y)
|
||||||
|
EVALUATE_VECTOR(m_vecTargetAngle, 2, PORTALFL_CHANGED_TARG_ANGLES_Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
NSPortal::SendEntity(entity ePEnt, float flChanged)
|
||||||
|
{
|
||||||
|
WriteByte(MSG_ENTITY, ENT_PORTAL);
|
||||||
|
WriteFloat(MSG_ENTITY, flChanged);
|
||||||
|
|
||||||
|
SENDENTITY_COORD(origin[0], PORTALFL_CHANGED_ORIGIN_X)
|
||||||
|
SENDENTITY_COORD(origin[1], PORTALFL_CHANGED_ORIGIN_Y)
|
||||||
|
SENDENTITY_COORD(origin[2], PORTALFL_CHANGED_ORIGIN_Z)
|
||||||
|
SENDENTITY_FLOAT(angles[0], PORTALFL_CHANGED_ANGLES_X)
|
||||||
|
SENDENTITY_FLOAT(angles[1], PORTALFL_CHANGED_ANGLES_Y)
|
||||||
|
SENDENTITY_FLOAT(angles[2], PORTALFL_CHANGED_ANGLES_Z)
|
||||||
|
SENDENTITY_ENTITY(m_ePortalTarget, PORTALFL_CHANGED_TARG_ENTITY)
|
||||||
|
|
||||||
|
if (1) {
|
||||||
|
SENDENTITY_COORD(m_vecTargetPos[0], PORTALFL_CHANGED_TARG_ORIGIN_X)
|
||||||
|
SENDENTITY_COORD(m_vecTargetPos[1], PORTALFL_CHANGED_TARG_ORIGIN_Y)
|
||||||
|
SENDENTITY_COORD(m_vecTargetPos[2], PORTALFL_CHANGED_TARG_ORIGIN_Z)
|
||||||
|
SENDENTITY_FLOAT(m_vecTargetAngle[0], PORTALFL_CHANGED_TARG_ANGLES_X)
|
||||||
|
SENDENTITY_FLOAT(m_vecTargetAngle[1], PORTALFL_CHANGED_TARG_ANGLES_Y)
|
||||||
|
SENDENTITY_FLOAT(m_vecTargetAngle[2], PORTALFL_CHANGED_TARG_ANGLES_Z)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
void
|
||||||
|
NSPortal::ReceiveEntity(float flNew, float flChanged)
|
||||||
|
{
|
||||||
|
if (m_ePortalTarget) {
|
||||||
|
m_ePortalTarget.m_ePortalTarget = world;
|
||||||
|
m_ePortalTarget = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
READENTITY_COORD(origin[0], PORTALFL_CHANGED_ORIGIN_X)
|
||||||
|
READENTITY_COORD(origin[1], PORTALFL_CHANGED_ORIGIN_Y)
|
||||||
|
READENTITY_COORD(origin[2], PORTALFL_CHANGED_ORIGIN_Z)
|
||||||
|
READENTITY_FLOAT(angles[0], PORTALFL_CHANGED_ANGLES_X)
|
||||||
|
READENTITY_FLOAT(angles[1], PORTALFL_CHANGED_ANGLES_Y)
|
||||||
|
READENTITY_FLOAT(angles[2], PORTALFL_CHANGED_ANGLES_Z)
|
||||||
|
READENTITY_ENTITY(m_ePortalTarget, PORTALFL_CHANGED_TARG_ENTITY)
|
||||||
|
|
||||||
|
READENTITY_COORD(m_vecTargetPos[0], PORTALFL_CHANGED_TARG_ORIGIN_X)
|
||||||
|
READENTITY_COORD(m_vecTargetPos[1], PORTALFL_CHANGED_TARG_ORIGIN_Y)
|
||||||
|
READENTITY_COORD(m_vecTargetPos[2], PORTALFL_CHANGED_TARG_ORIGIN_Z)
|
||||||
|
READENTITY_FLOAT(m_vecTargetAngle[0], PORTALFL_CHANGED_TARG_ANGLES_X)
|
||||||
|
READENTITY_FLOAT(m_vecTargetAngle[1], PORTALFL_CHANGED_TARG_ANGLES_Y)
|
||||||
|
READENTITY_FLOAT(m_vecTargetAngle[2], PORTALFL_CHANGED_TARG_ANGLES_Z)
|
||||||
|
|
||||||
|
if (m_ePortalTarget) {
|
||||||
|
if (m_ePortalTarget.m_ePortalTarget)
|
||||||
|
m_ePortalTarget.m_ePortalTarget.m_ePortalTarget = world;
|
||||||
|
|
||||||
|
m_ePortalTarget. m_ePortalTarget = this;
|
||||||
|
} else {
|
||||||
|
skin = 1;
|
||||||
|
makevectors(angles);
|
||||||
|
m_vecTargetPos = origin;
|
||||||
|
m_vecTargetN = v_forward;
|
||||||
|
m_vecTargetS = v_right;
|
||||||
|
m_vecTargetT = v_up;
|
||||||
|
}
|
||||||
|
setorigin(this, origin);
|
||||||
|
_PortalUpdated();
|
||||||
|
drawmask = MASK_ENGINE;
|
||||||
|
predraw = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
void
|
||||||
|
NSPortal_ReadEntity(bool new)
|
||||||
|
{
|
||||||
|
NSPortal me = (NSPortal)self;
|
||||||
|
if (new) {
|
||||||
|
spawnfunc_NSPortal();
|
||||||
|
}
|
||||||
|
me.ReceiveEntity(new, readfloat());
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -14,23 +14,98 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef enumflags
|
||||||
|
{
|
||||||
|
PROJ_CHANGED_ORIGIN_X,
|
||||||
|
PROJ_CHANGED_ORIGIN_Y,
|
||||||
|
PROJ_CHANGED_ORIGIN_Z,
|
||||||
|
PROJ_CHANGED_ANGLES_X,
|
||||||
|
PROJ_CHANGED_ANGLES_Y,
|
||||||
|
PROJ_CHANGED_ANGLES_Z,
|
||||||
|
PROJ_CHANGED_MODELINDEX,
|
||||||
|
PROJ_CHANGED_SIZE,
|
||||||
|
PROJ_CHANGED_FRAME,
|
||||||
|
PROJ_CHANGED_SKIN,
|
||||||
|
PROJ_CHANGED_EFFECTS,
|
||||||
|
PROJ_CHANGED_BODY,
|
||||||
|
PROJ_CHANGED_SCALE,
|
||||||
|
PROJ_CHANGED_VELOCITY,
|
||||||
|
PROJ_CHANGED_ANGULARVELOCITY,
|
||||||
|
PROJ_CHANGED_RENDERCOLOR,
|
||||||
|
PROJ_CHANGED_RENDERAMT,
|
||||||
|
PROJ_CHANGED_RENDERMODE,
|
||||||
|
} nsprojectile_changed_t;
|
||||||
|
|
||||||
|
.void(entity, entity) m_pImpact;
|
||||||
|
.float traileffectnum;
|
||||||
|
|
||||||
/** This entity class represents an interactive projectile.
|
/** This entity class represents an interactive projectile.
|
||||||
Objects such as rockets, grenades, bolts etc. should ideally be this. */
|
Objects such as rockets, grenades, bolts etc. should ideally be this. */
|
||||||
class NSProjectile:NSSurfacePropEntity
|
class NSProjectile:NSSurfacePropEntity
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
PREDICTED_FLOAT_N(traileffectnum)
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
/* sprite animation gubbins */
|
/* sprite animation gubbins */
|
||||||
int m_iProjectileAnimEnd;
|
int m_iProjectileAnimEnd;
|
||||||
int m_iProjectileAnimStart;
|
int m_iProjectileAnimStart;
|
||||||
float m_flProjectileFramerate;
|
float m_flProjectileFramerate;
|
||||||
virtual void m_pImpact(entity, entity) = 0;
|
|
||||||
|
/* temp */
|
||||||
|
float m_flDmgMultiplier;
|
||||||
|
|
||||||
|
/* defAPI */
|
||||||
|
string m_defDamage;
|
||||||
|
string m_defSplashDamage;
|
||||||
|
vector m_vecLaunchVelocity;
|
||||||
|
float m_flThrust; /* TODO */
|
||||||
|
float m_flThrustStart; /* TODO */
|
||||||
|
float m_flThrustEnd; /* TODO */
|
||||||
|
float m_flFrictionLinear; /* TODO */
|
||||||
|
float m_flBounce;
|
||||||
|
float m_flMass; /* TODO */
|
||||||
|
float m_flGravity; /* TODO */
|
||||||
|
float m_flFuse;
|
||||||
|
bool m_bDetonateOnFuse;
|
||||||
|
bool m_bDetonateOnDeath;
|
||||||
|
bool m_bDetonateOnWorld;
|
||||||
|
bool m_bDetonateOnActor;
|
||||||
|
bool m_bImpactEffect; /* TODO */
|
||||||
|
bool m_bImpactGib; /* TODO */
|
||||||
|
string m_matDetonate; /* TODO */
|
||||||
|
float m_flDecalSize; /* TODO */
|
||||||
|
string m_partSmokeFly;
|
||||||
|
string m_partModelDetonate;
|
||||||
|
string m_partSmokeDetonate;
|
||||||
|
string m_partSmokeBounce;
|
||||||
|
string m_partSmokeFuse;
|
||||||
|
int m_iDebrisCount; /* TODO */
|
||||||
|
vector m_vecLightColor; /* TODO */
|
||||||
|
float m_flLightRadius; /* TODO */
|
||||||
|
float m_flLightOffset; /* TODO */
|
||||||
|
vector m_vecExplodeLightColor; /* TODO */
|
||||||
|
float m_fExplodelLightRadius; /* TODO */
|
||||||
|
float m_fExplodelLightFadetime; /* TODO */
|
||||||
|
string m_sndFly;
|
||||||
|
string m_sndExplode;
|
||||||
|
string m_sndBounce;
|
||||||
|
|
||||||
|
/* ETQW-additions */
|
||||||
|
bool m_bIsBullet;
|
||||||
|
|
||||||
nonvirtual void _AnimateThink(void);
|
nonvirtual void _AnimateThink(void);
|
||||||
nonvirtual void _AnimateThinkDead(void);
|
nonvirtual void _AnimateThinkDead(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void NSProjectile(void);
|
void NSProjectile(void);
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
virtual void ReceiveEntity(float, float);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
/** Sets the function that'll be called upon impact of the projectile onto a surface. */
|
/** Sets the function that'll be called upon impact of the projectile onto a surface. */
|
||||||
nonvirtual void SetImpact(void(entity, entity));
|
nonvirtual void SetImpact(void(entity, entity));
|
||||||
/** When called, will animated between two frame positions at a specified framerate on loop. */
|
/** When called, will animated between two frame positions at a specified framerate on loop. */
|
||||||
|
@ -41,4 +116,24 @@ public:
|
||||||
/** Called upon the projectile touching another object. */
|
/** Called upon the projectile touching another object. */
|
||||||
virtual void Touch(entity);
|
virtual void Touch(entity);
|
||||||
virtual void Spawned(void);
|
virtual void Spawned(void);
|
||||||
|
virtual void Death(void);
|
||||||
|
virtual void Pain(void);
|
||||||
|
|
||||||
|
virtual void SpawnKey(string, string);
|
||||||
|
virtual void EvaluateEntity(void);
|
||||||
|
virtual float SendEntity(entity, float);
|
||||||
|
|
||||||
|
nonvirtual void _FuseEnded(void);
|
||||||
|
nonvirtual void _Explode(void);
|
||||||
|
|
||||||
|
nonvirtual void _LaunchHitscan(vector, vector, float);
|
||||||
|
|
||||||
|
/* launch the projectile into the world */
|
||||||
|
nonvirtual void Launch(vector, vector, float, float, float);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
void NSProjectile_ReadEntity(bool);
|
||||||
|
#endif
|
|
@ -17,9 +17,187 @@
|
||||||
void
|
void
|
||||||
NSProjectile::NSProjectile(void)
|
NSProjectile::NSProjectile(void)
|
||||||
{
|
{
|
||||||
|
#ifdef SERVER
|
||||||
m_iProjectileAnimEnd = 0i;
|
m_iProjectileAnimEnd = 0i;
|
||||||
m_iProjectileAnimStart = 0i;
|
m_iProjectileAnimStart = 0i;
|
||||||
m_flProjectileFramerate = 0.1f; /* default to 10 hz */
|
m_flProjectileFramerate = 0.1f; /* default to 10 hz */
|
||||||
|
|
||||||
|
/* defAPI */
|
||||||
|
m_defDamage = __NULL__;
|
||||||
|
m_defSplashDamage = __NULL__;
|
||||||
|
m_vecLaunchVelocity = g_vec_null;
|
||||||
|
m_flThrust = 0.0f;
|
||||||
|
m_flThrustStart = 0.0f;
|
||||||
|
m_flThrustEnd = 0.0f;
|
||||||
|
m_flFrictionLinear = 0.0f;
|
||||||
|
m_flBounce = 0.0f;
|
||||||
|
m_flMass = 0.0f;
|
||||||
|
m_flGravity = 0.0f;
|
||||||
|
m_flFuse = 0.0f;
|
||||||
|
m_bDetonateOnFuse = 0.0f;
|
||||||
|
m_bDetonateOnDeath = 0.0f;
|
||||||
|
m_bDetonateOnWorld = 0.0f;
|
||||||
|
m_bDetonateOnActor = 0.0f;
|
||||||
|
m_bImpactEffect = false;
|
||||||
|
m_bImpactGib = false;
|
||||||
|
m_matDetonate = __NULL__;
|
||||||
|
m_flDecalSize = 0.0f;
|
||||||
|
m_partSmokeFly = __NULL__;
|
||||||
|
m_partModelDetonate = __NULL__;
|
||||||
|
m_partSmokeDetonate = __NULL__;
|
||||||
|
m_partSmokeBounce = __NULL__;
|
||||||
|
m_partSmokeFuse = __NULL__;
|
||||||
|
m_iDebrisCount = 0i;
|
||||||
|
m_vecLightColor = g_vec_null;
|
||||||
|
m_flLightRadius = 0.0f;
|
||||||
|
m_flLightOffset = 0.0f;
|
||||||
|
m_vecExplodeLightColor = g_vec_null;
|
||||||
|
m_fExplodelLightRadius = 0.0f;
|
||||||
|
m_fExplodelLightFadetime = 0.0f;
|
||||||
|
m_sndFly = __NULL__;
|
||||||
|
m_sndExplode = __NULL__;
|
||||||
|
m_sndBounce = __NULL__;
|
||||||
|
|
||||||
|
/* ETQW-additions */
|
||||||
|
m_bIsBullet = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SERVER
|
||||||
|
void
|
||||||
|
NSProjectile::SpawnKey(string strKey, string strValue)
|
||||||
|
{
|
||||||
|
switch (strKey) {
|
||||||
|
case "def_damage": /* direct damage, upon touch */
|
||||||
|
m_defDamage = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "def_splash_damage": /* direct damage, upon touch */
|
||||||
|
m_defSplashDamage = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "velocity":
|
||||||
|
m_vecLaunchVelocity = ReadVector(strValue);
|
||||||
|
break;
|
||||||
|
case "health": /* amount of dmg the projectile can take */
|
||||||
|
health = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "model":
|
||||||
|
model = ReadString(strValue);
|
||||||
|
m_oldModel = model;
|
||||||
|
break;
|
||||||
|
case "velocity":
|
||||||
|
velocity = ReadVector(strValue);
|
||||||
|
break;
|
||||||
|
case "angular_velocity": /* sets avelocity */
|
||||||
|
avelocity = ReadVector(strValue);
|
||||||
|
break;
|
||||||
|
case "thrust": /* rate of acceeleration */
|
||||||
|
m_flThrust = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "thrust_start": /* when to begin accel */
|
||||||
|
m_flThrustStart = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "thrust_end": /* when to stop accel */
|
||||||
|
m_flThrustEnd = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "linear_friction": /* air friction */
|
||||||
|
m_flFrictionLinear = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "bounce": /* bounce multiplier */
|
||||||
|
m_flBounce = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "mass":
|
||||||
|
m_flMass = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "gravity": /* 0 means no gravity */
|
||||||
|
m_flGravity = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "fuse": /* fuse time in seconds */
|
||||||
|
m_flFuse = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "detonate_on_fuse": /* should it detonate when fuse runs out? */
|
||||||
|
m_bDetonateOnFuse = ReadBool(strValue);
|
||||||
|
break;
|
||||||
|
case "detonate_on_death": /* should it detonate when it gets damaged enough? */
|
||||||
|
m_bDetonateOnDeath = ReadBool(strValue);
|
||||||
|
break;
|
||||||
|
case "detonate_on_world": /* should it detonate when touching world? */
|
||||||
|
m_bDetonateOnWorld = ReadBool(strValue);
|
||||||
|
break;
|
||||||
|
case "detonate_on_actor": /* should it detonate when touching a monster/player */
|
||||||
|
m_bDetonateOnActor = ReadBool(strValue);
|
||||||
|
break;
|
||||||
|
case "impact_damage_effect": /* blood splats? */
|
||||||
|
m_bImpactEffect = ReadBool(strValue);
|
||||||
|
break;
|
||||||
|
case "impact_gib": /* gibs */
|
||||||
|
m_bImpactGib = ReadBool(strValue);
|
||||||
|
break;
|
||||||
|
case "mtr_detonate":
|
||||||
|
m_matDetonate = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "decal_size":
|
||||||
|
m_flDecalSize = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "smoke_fly":
|
||||||
|
m_partSmokeFly = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "model_detonate":
|
||||||
|
m_partModelDetonate = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "smoke_detonate":
|
||||||
|
m_partSmokeDetonate = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "smoke_bounce":
|
||||||
|
m_partSmokeBounce = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "smoke_fuse":
|
||||||
|
m_partSmokeFuse = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "debris_count":
|
||||||
|
m_iDebrisCount = ReadInt(strValue);
|
||||||
|
break;
|
||||||
|
/*case "def_debris":
|
||||||
|
break;
|
||||||
|
case "def_shrapnel":
|
||||||
|
break;
|
||||||
|
case "mtr_light_shader":
|
||||||
|
break;*/
|
||||||
|
case "light_color":
|
||||||
|
m_vecLightColor = ReadVector(strValue);
|
||||||
|
break;
|
||||||
|
case "light_radius":
|
||||||
|
m_flLightRadius = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "light_offset":
|
||||||
|
m_flLightOffset = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
/*case "mtr_explode_light_shader":
|
||||||
|
break;*/
|
||||||
|
case "explode_light_color":
|
||||||
|
m_vecExplodeLightColor = ReadVector(strValue);
|
||||||
|
break;
|
||||||
|
case "explode_light_radus":
|
||||||
|
m_fExplodelLightRadius = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "explode_light_fadetime":
|
||||||
|
m_fExplodelLightFadetime = ReadFloat(strValue);
|
||||||
|
break;
|
||||||
|
case "snd_fly":
|
||||||
|
m_sndFly = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "snd_explode":
|
||||||
|
m_sndExplode = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
case "snd_bounce":
|
||||||
|
m_sndBounce = ReadString(strValue);
|
||||||
|
break;
|
||||||
|
/* ETQW-additions */
|
||||||
|
case "is_bullet":
|
||||||
|
m_bIsBullet = ReadBool(strValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
super::SpawnKey(strKey, strValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -39,9 +217,53 @@ NSProjectile::Spawned(void)
|
||||||
void
|
void
|
||||||
NSProjectile::Touch(entity eToucher)
|
NSProjectile::Touch(entity eToucher)
|
||||||
{
|
{
|
||||||
if (m_pImpact)
|
if (m_defDamage)
|
||||||
m_pImpact(eToucher, this);
|
if (eToucher.takedamage != DAMAGE_NO) {
|
||||||
|
float damageVal;
|
||||||
|
float baseDamage = Skill_GetDefValue(EntityDef_GetKeyValue(m_defDamage, "damage"));
|
||||||
|
float randomDamage = Skill_GetDefValue(EntityDef_GetKeyValue(m_defDamage, "damage_random"));
|
||||||
|
damageVal = (baseDamage + randomDamage);
|
||||||
|
|
||||||
|
if (m_flDmgMultiplier >= 0.0)
|
||||||
|
damageVal *= m_flDmgMultiplier;
|
||||||
|
|
||||||
|
Damage_Apply(eToucher, owner, damageVal, WEAPON_NONE, DMG_BLUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_bDetonateOnWorld) {
|
||||||
|
if (eToucher == world || eToucher.takedamage == DAMAGE_NO) {
|
||||||
|
_Explode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_bDetonateOnActor) {
|
||||||
|
if (eToucher.takedamage != DAMAGE_NO) {
|
||||||
|
_Explode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_partSmokeBounce)
|
||||||
|
pointparticles(particleeffectnum(m_partSmokeBounce), origin, velocity, 1);
|
||||||
|
|
||||||
|
StartSoundDef(m_sndBounce, CHAN_BODY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSProjectile::Pain(void)
|
||||||
|
{
|
||||||
|
/* do nothing. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSProjectile::Death(void)
|
||||||
|
{
|
||||||
|
if (m_bDetonateOnDeath) {
|
||||||
|
_Explode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* whatever else comes otherwise? */
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,4 +320,187 @@ NSProjectile::AnimateOnce(int startframe, int endframe, float framerate)
|
||||||
frame = startframe;
|
frame = startframe;
|
||||||
think = _AnimateThinkDead;
|
think = _AnimateThinkDead;
|
||||||
nextthink = time + m_flProjectileFramerate;
|
nextthink = time + m_flProjectileFramerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSProjectile::_FuseEnded(void)
|
||||||
|
{
|
||||||
|
if (m_bDetonateOnFuse) {
|
||||||
|
_Explode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_partSmokeFuse)
|
||||||
|
pointparticles(particleeffectnum(m_partSmokeFuse), origin, velocity, 1);
|
||||||
|
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
void
|
||||||
|
NSProjectile::_Explode(void)
|
||||||
|
{
|
||||||
|
makevectors(vectoangles(velocity));
|
||||||
|
vector explodePos = origin - (v_forward * 32);
|
||||||
|
|
||||||
|
if (m_partModelDetonate)
|
||||||
|
pointparticles(particleeffectnum(m_partModelDetonate), explodePos, velocity, 1);
|
||||||
|
|
||||||
|
//print(sprintf("%S\n", m_defSplashDamage));
|
||||||
|
if (m_defSplashDamage) {
|
||||||
|
float flDamage = Skill_GetDefValue(EntityDef_GetKeyValue(m_defSplashDamage, "damage"));
|
||||||
|
float flRadius = Skill_GetDefValue(EntityDef_GetKeyValue(m_defSplashDamage, "radius"));
|
||||||
|
|
||||||
|
if (m_flDmgMultiplier >= 0.0)
|
||||||
|
flDamage *= m_flDmgMultiplier;
|
||||||
|
|
||||||
|
//print(sprintf("Damage: %d; Radius: %d\n", flDamage, flRadius));
|
||||||
|
Damage_Radius(origin, owner, flDamage, flRadius, TRUE, WEAPON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
StartSoundDef(m_sndExplode, CHAN_VOICE, true);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSProjectile::_LaunchHitscan(vector startPos, vector launchDir, float dmgMultiplier)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSProjectile::Launch(vector startPos, vector launchDir, float fuseOffset, float powerMultiplier, float dmgMultiplier)
|
||||||
|
{
|
||||||
|
vector moveVel = g_vec_null;
|
||||||
|
|
||||||
|
if (m_bIsBullet) {
|
||||||
|
_LaunchHitscan(startPos, launchDir, dmgMultiplier);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetOrigin(startPos);
|
||||||
|
SetAngles(launchDir);
|
||||||
|
SetModel(m_oldModel);
|
||||||
|
|
||||||
|
if (dmgMultiplier <= 0.0)
|
||||||
|
dmgMultiplier = 1.0f;
|
||||||
|
|
||||||
|
if (powerMultiplier <= 0.0)
|
||||||
|
powerMultiplier = 1.0f;
|
||||||
|
|
||||||
|
m_flDmgMultiplier = dmgMultiplier;
|
||||||
|
|
||||||
|
/* convert absolute vel from def into relative */
|
||||||
|
makevectors(launchDir);
|
||||||
|
moveVel = (m_vecLaunchVelocity[0] * powerMultiplier) * v_forward;
|
||||||
|
moveVel += (m_vecLaunchVelocity[1] * powerMultiplier) * v_right;
|
||||||
|
moveVel += (m_vecLaunchVelocity[2] * powerMultiplier) * v_up;
|
||||||
|
|
||||||
|
/* fire slower underwater */
|
||||||
|
if (pointcontents(startPos) == CONTENT_WATER) {
|
||||||
|
SetVelocity(moveVel / 10);
|
||||||
|
} else {
|
||||||
|
SetVelocity(moveVel);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAngularVelocity(avelocity);
|
||||||
|
SetHealth(health);
|
||||||
|
SetSolid(SOLID_BBOX);
|
||||||
|
|
||||||
|
if (m_flBounce > 0) {
|
||||||
|
SetMovetype(MOVETYPE_BOUNCE);
|
||||||
|
} else {
|
||||||
|
SetMovetype(MOVETYPE_FLYMISSILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_partSmokeFly) {
|
||||||
|
traileffectnum = particleeffectnum(m_partSmokeFly);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetHealth() > 0) {
|
||||||
|
SetTakedamage(DAMAGE_YES);
|
||||||
|
} else {
|
||||||
|
SetTakedamage(DAMAGE_NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_flFuse > 0) {
|
||||||
|
ScheduleThink(_FuseEnded, m_flFuse + fuseOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
StartSoundDef(m_sndFly, CHAN_BODY, true);
|
||||||
|
SendFlags = (-1);
|
||||||
|
SendEntity = 0; /* HACK: remove this once Spike fixes CSQC-set traileffectnum etc. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSProjectile::EvaluateEntity(void)
|
||||||
|
{
|
||||||
|
EVALUATE_VECTOR(origin, 0, PROJ_CHANGED_ORIGIN_X)
|
||||||
|
EVALUATE_VECTOR(origin, 1, PROJ_CHANGED_ORIGIN_Y)
|
||||||
|
EVALUATE_VECTOR(origin, 2, PROJ_CHANGED_ORIGIN_Z)
|
||||||
|
EVALUATE_VECTOR(angles, 0, PROJ_CHANGED_ANGLES_X)
|
||||||
|
EVALUATE_VECTOR(angles, 1, PROJ_CHANGED_ANGLES_Y)
|
||||||
|
EVALUATE_VECTOR(angles, 2, PROJ_CHANGED_ANGLES_Z)
|
||||||
|
EVALUATE_FIELD(modelindex, PROJ_CHANGED_MODELINDEX)
|
||||||
|
EVALUATE_FIELD(traileffectnum, PROJ_CHANGED_MODELINDEX)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure StartFrame calls this */
|
||||||
|
float
|
||||||
|
NSProjectile::SendEntity(entity ePEnt, float flChanged)
|
||||||
|
{
|
||||||
|
if (!modelindex)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
WriteByte(MSG_ENTITY, ENT_ENTITYPROJECTILE);
|
||||||
|
|
||||||
|
/* broadcast how much data is expected to be read */
|
||||||
|
WriteFloat(MSG_ENTITY, flChanged);
|
||||||
|
|
||||||
|
SENDENTITY_COORD(origin[0], PROJ_CHANGED_ORIGIN_X)
|
||||||
|
SENDENTITY_COORD(origin[1], PROJ_CHANGED_ORIGIN_Y)
|
||||||
|
SENDENTITY_COORD(origin[2], PROJ_CHANGED_ORIGIN_Z)
|
||||||
|
SENDENTITY_ANGLE(angles[0], PROJ_CHANGED_ANGLES_X)
|
||||||
|
SENDENTITY_ANGLE(angles[1], PROJ_CHANGED_ANGLES_Y)
|
||||||
|
SENDENTITY_ANGLE(angles[2], PROJ_CHANGED_ANGLES_Z)
|
||||||
|
SENDENTITY_SHORT(modelindex, PROJ_CHANGED_MODELINDEX)
|
||||||
|
SENDENTITY_FLOAT(traileffectnum, PROJ_CHANGED_MODELINDEX)
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.float emiteffectnum;
|
||||||
|
#ifdef CLIENT
|
||||||
|
void
|
||||||
|
NSProjectile::ReceiveEntity(float flNew, float flChanged)
|
||||||
|
{
|
||||||
|
READENTITY_COORD(origin[0], PROJ_CHANGED_ORIGIN_X)
|
||||||
|
READENTITY_COORD(origin[1], PROJ_CHANGED_ORIGIN_Y)
|
||||||
|
READENTITY_COORD(origin[2], PROJ_CHANGED_ORIGIN_Z)
|
||||||
|
READENTITY_ANGLE(angles[0], PROJ_CHANGED_ANGLES_X)
|
||||||
|
READENTITY_ANGLE(angles[1], PROJ_CHANGED_ANGLES_Y)
|
||||||
|
READENTITY_ANGLE(angles[2], PROJ_CHANGED_ANGLES_Z)
|
||||||
|
READENTITY_SHORT(modelindex, PROJ_CHANGED_MODELINDEX)
|
||||||
|
READENTITY_FLOAT(traileffectnum, PROJ_CHANGED_MODELINDEX)
|
||||||
|
setmodelindex(this, modelindex);
|
||||||
|
setorigin(this, origin);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CLIENT
|
||||||
|
void
|
||||||
|
NSProjectile_ReadEntity(bool new)
|
||||||
|
{
|
||||||
|
float fl;
|
||||||
|
|
||||||
|
NSProjectile rend = (NSProjectile)self;
|
||||||
|
if (new) {
|
||||||
|
spawnfunc_NSProjectile();
|
||||||
|
}
|
||||||
|
|
||||||
|
fl = readfloat();
|
||||||
|
rend.ReceiveEntity(new, fl);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -159,6 +159,8 @@ public:
|
||||||
/* misc 'being' methods */
|
/* misc 'being' methods */
|
||||||
/** Returns the absolute world position of where the eyes are located. */
|
/** Returns the absolute world position of where the eyes are located. */
|
||||||
nonvirtual vector GetEyePos(void);
|
nonvirtual vector GetEyePos(void);
|
||||||
|
/** Sets the relative position of the eyes */
|
||||||
|
nonvirtual void SetEyePos(vector);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CLIENT
|
#ifdef CLIENT
|
||||||
|
|
|
@ -39,6 +39,12 @@ NSSurfacePropEntity::GetEyePos(void)
|
||||||
return origin + view_ofs;
|
return origin + view_ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NSSurfacePropEntity::SetEyePos(vector value)
|
||||||
|
{
|
||||||
|
view_ofs = value;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
NSSurfacePropEntity::Spawned(void)
|
NSSurfacePropEntity::Spawned(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -826,6 +826,8 @@ NSTalkMonster::predraw(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
addentity(this);
|
addentity(this);
|
||||||
|
_RenderDebugViewCone();
|
||||||
|
|
||||||
return (PREDRAW_NEXT);
|
return (PREDRAW_NEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ string __fullspawndata;
|
||||||
#include "NSProjectile.h"
|
#include "NSProjectile.h"
|
||||||
#include "NSItem.h"
|
#include "NSItem.h"
|
||||||
#include "NSSpraylogo.h"
|
#include "NSSpraylogo.h"
|
||||||
|
#include "NSPortal.h"
|
||||||
|
|
||||||
#include "../xr/defs.h"
|
#include "../xr/defs.h"
|
||||||
#include "NSClient.h"
|
#include "NSClient.h"
|
||||||
|
|
|
@ -20,6 +20,7 @@ typedef enum
|
||||||
ENT_NONE = 0, /**< invalid, but reserved. */
|
ENT_NONE = 0, /**< invalid, but reserved. */
|
||||||
ENT_ENTITY, /**< of type NSEntity */
|
ENT_ENTITY, /**< of type NSEntity */
|
||||||
ENT_ENTITYRENDERABLE, /**< of type NSRenderableEntity */
|
ENT_ENTITYRENDERABLE, /**< of type NSRenderableEntity */
|
||||||
|
ENT_ENTITYPROJECTILE, /**< of type NSProjectile */
|
||||||
ENT_SURFPROP, /**< of type NSSurfacePropEntity */
|
ENT_SURFPROP, /**< of type NSSurfacePropEntity */
|
||||||
ENT_PHYSICS, /**< of type NSPhysicsEntity */
|
ENT_PHYSICS, /**< of type NSPhysicsEntity */
|
||||||
ENT_MONSTER, /**< of type NSMonster */
|
ENT_MONSTER, /**< of type NSMonster */
|
||||||
|
@ -27,6 +28,7 @@ typedef enum
|
||||||
ENT_PLAYER, /**< of type NSClientPlayer */
|
ENT_PLAYER, /**< of type NSClientPlayer */
|
||||||
ENT_WEAPON, /**< of type NSWeapon */
|
ENT_WEAPON, /**< of type NSWeapon */
|
||||||
ENT_SPECTATOR, /**< of type NSClientSpectator */
|
ENT_SPECTATOR, /**< of type NSClientSpectator */
|
||||||
|
ENT_PORTAL, /**< of type NSPortal */
|
||||||
ENT_AMBIENTSOUND, /**< of type ambient_generic */
|
ENT_AMBIENTSOUND, /**< of type ambient_generic */
|
||||||
ENT_BEAM, /**< of type env_beam */
|
ENT_BEAM, /**< of type env_beam */
|
||||||
ENT_DLIGHT, /**< of type light_dynamic */
|
ENT_DLIGHT, /**< of type light_dynamic */
|
||||||
|
|
|
@ -17,6 +17,7 @@ NSMonster.qc
|
||||||
NSTalkMonster.qc
|
NSTalkMonster.qc
|
||||||
NSProjectile.qc
|
NSProjectile.qc
|
||||||
NSItem.qc
|
NSItem.qc
|
||||||
|
NSPortal.qc
|
||||||
|
|
||||||
NSClient.qc
|
NSClient.qc
|
||||||
NSClientSpectator.qc
|
NSClientSpectator.qc
|
||||||
|
|
|
@ -581,6 +581,11 @@ PMoveCustom_Move(void)
|
||||||
self.origin = trace_endpos;
|
self.origin = trace_endpos;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (trace_ent.solid == SOLID_PORTAL) {
|
||||||
|
NSPortal portalEntry = (NSPortal)trace_ent;
|
||||||
|
portalEntry.TransportEntity((NSEntity)self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,6 +602,10 @@ PMoveCustom_Move(void)
|
||||||
|
|
||||||
if (trace_fraction == 1.0) {
|
if (trace_fraction == 1.0) {
|
||||||
return;
|
return;
|
||||||
|
} else if (trace_ent.solid == SOLID_PORTAL) {
|
||||||
|
NSPortal portalEntry = (NSPortal)trace_ent;
|
||||||
|
portalEntry.TransportEntity((NSEntity)self);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (trace_startsolid) {
|
/*if (trace_startsolid) {
|
||||||
|
|
Loading…
Reference in a new issue