set g_balance_shotgun_secondary_melee_no_doubleslap 1
set g_balance_shotgun_secondary_melee_nonplayerdamage 40
set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_damage 70
+set g_balance_shotgun_secondary_damage 80
set g_balance_shotgun_secondary_force 200
set g_balance_shotgun_secondary_refire 1.25
set g_balance_shotgun_secondary_animtime 1
set g_balance_uzi_first_headshotaddeddamage 0
set g_balance_uzi_first_force 5
set g_balance_uzi_first_spread 0.03
-set g_balance_uzi_first_refire 0.2
+set g_balance_uzi_first_refire 0.125
set g_balance_uzi_first_ammo 1
set g_balance_uzi_sustained_damage 10 // 100 dps
set g_balance_grenadelauncher_primary_damage 50
set g_balance_grenadelauncher_primary_edgedamage 25
set g_balance_grenadelauncher_primary_force 250
-set g_balance_grenadelauncher_primary_radius 130
+set g_balance_grenadelauncher_primary_radius 120
set g_balance_grenadelauncher_primary_speed 1900
set g_balance_grenadelauncher_primary_speed_up 225
set g_balance_grenadelauncher_primary_speed_z 0
set g_balance_grenadelauncher_secondary_damage 60
set g_balance_grenadelauncher_secondary_edgedamage 30
set g_balance_grenadelauncher_secondary_force 250
-set g_balance_grenadelauncher_secondary_radius 130
+set g_balance_grenadelauncher_secondary_radius 120
set g_balance_grenadelauncher_secondary_speed 1400
set g_balance_grenadelauncher_secondary_speed_up 150
set g_balance_grenadelauncher_secondary_speed_z 0
set g_balance_nex_primary_damage 90
set g_balance_nex_primary_force 400
set g_balance_nex_primary_refire 1.5
-set g_balance_nex_primary_animtime 0.4
+set g_balance_nex_primary_animtime 0.5
set g_balance_nex_primary_ammo 6
set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3
set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000
// {{{ rocketlauncher
set g_balance_rocketlauncher_damage 80
set g_balance_rocketlauncher_edgedamage 40
-set g_balance_rocketlauncher_force 400
-set g_balance_rocketlauncher_radius 110
+set g_balance_rocketlauncher_force 500
+set g_balance_rocketlauncher_radius 120
set g_balance_rocketlauncher_speed 1500
set g_balance_rocketlauncher_speedaccel 1500
set g_balance_rocketlauncher_speedstart 800
clean:
rm -f ../progs.dat ../menu.dat ../csprogs.dat
-FILES_CSPROGS = $(shell find client common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc)
+FILES_CSPROGS = $(shell find client common warpzonelib csqcmodels -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc)
../csprogs.dat: $(FILES_CSPROGS)
@echo make[1]: Entering directory \`$(PWD)/client\'
cd client && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS)
-FILES_PROGS = $(shell find server common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc)
+FILES_PROGS = $(shell find server common warpzonelib csqcmodels -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc)
../progs.dat: $(FILES_PROGS)
@echo make[1]: Entering directory \`$(PWD)/server\'
cd server && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_PROGS)
}
}
+// FEATURE: EF_NODRAW workalike
+float EF_BRIGHTFIELD = 1;
+float EF_BRIGHTLIGHT = 4;
+float EF_DIMLIGHT = 8;
+float EF_DOUBLESIDED = 32768;
+float EF_NOSELFSHADOW = 65536;
+float MF_ROCKET = 1; // leave a trail
+float MF_GRENADE = 2; // leave a trail
+float MF_GIB = 4; // leave a trail
+float MF_ROTATE = 8; // rotate (bonus items)
+float MF_TRACER = 16; // green split trail
+float MF_ZOMGIB = 32; // small blood trail
+float MF_TRACER2 = 64; // orange split trail
+float MF_TRACER3 = 128; // purple trail
+.float csqcmodel_effects;
+.float csqcmodel_modelflags;
+void CSQCModel_Effects_PreUpdate(void)
+{
+ self.effects = self.csqcmodel_effects;
+ self.modelflags = self.csqcmodel_modelflags;
+}
+void CSQCModel_Effects_PostUpdate(void)
+{
+ self.csqcmodel_effects = self.effects;
+ self.csqcmodel_modelflags = self.modelflags;
+ self.effects = 0;
+ self.modelflags = 0;
+ if(self.csqcmodel_teleported)
+ Projectile_ResetTrail(self.origin);
+}
+void CSQCModel_Effects_Apply(void)
+{
+ float eff = self.csqcmodel_effects;
+ eff &~= CSQCMODEL_EF_INVISIBLE;
+
+ self.renderflags &~= (RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS);
+ self.effects = 0;
+ self.traileffect = 0;
+
+ if(eff & EF_BRIGHTFIELD)
+ self.traileffect = particleeffectnum("TR_NEXUIZPLASMA");
+ // ignoring EF_MUZZLEFLASH
+ if(eff & EF_BRIGHTLIGHT)
+ adddynamiclight(self.origin, 400, '3 3 3');
+ if(eff & EF_DIMLIGHT)
+ adddynamiclight(self.origin, 200, '1.5 1.5 1.5');
+ if((eff & EF_NODRAW) || (self.csqcmodel_effects & CSQCMODEL_EF_INVISIBLE))
+ self.drawmask = 0;
+ if(eff & EF_ADDITIVE)
+ self.renderflags |= RF_ADDITIVE;
+ if(eff & EF_BLUE)
+ adddynamiclight(self.origin, 200, '0.15 0.15 1.5');
+ if(eff & EF_RED)
+ adddynamiclight(self.origin, 200, '1.5 0.15 0.15');
+ // ignoring EF_NOGUNBOB
+ if(eff & EF_FULLBRIGHT)
+ self.renderflags |= RF_FULLBRIGHT;
+ if(eff & EF_FLAME)
+ pointparticles(particleeffectnum("EF_FLAME"), self.origin, '0 0 0', bound(0, frametime, 0.1));
+ if(eff & EF_STARDUST)
+ pointparticles(particleeffectnum("EF_STARDUST"), self.origin, '0 0 0', bound(0, frametime, 0.1));
+ if(eff & EF_NOSHADOW)
+ self.renderflags |= RF_NOSHADOW;
+ if(eff & EF_NODEPTHTEST)
+ self.renderflags |= RF_DEPTHHACK;
+ // ignoring EF_SELECTABLE
+ if(eff & EF_DOUBLESIDED)
+ self.effects |= EF_DOUBLESIDED;
+ if(eff & EF_NOSELFSHADOW)
+ self.effects |= EF_NOSELFSHADOW;
+ // ignoring EF_UNUSED17, EF_UNUSED18, EF_UNUSED19, EF_RESTARTANIM_BIT, EF_TELEPORT_BIT, EF_LOWPRECISION
+ if(self.csqcmodel_modelflags & MF_ROCKET)
+ self.traileffect = particleeffectnum("TR_ROCKET");
+ if(self.csqcmodel_modelflags & MF_GRENADE)
+ self.traileffect = particleeffectnum("TR_GRENADE");
+ if(self.csqcmodel_modelflags & MF_GIB)
+ self.traileffect = particleeffectnum("TR_BLOOD");
+ if(self.csqcmodel_modelflags & MF_ROTATE)
+ {
+ self.renderflags |= RF_USEAXIS;
+ makevectors(self.angles + '0 100 0' * fmod(time, 3.6));
+ }
+ if(self.csqcmodel_modelflags & MF_TRACER)
+ self.traileffect = particleeffectnum("TR_WIZSPIKE");
+ if(self.csqcmodel_modelflags & MF_ZOMGIB)
+ self.traileffect = particleeffectnum("TR_SLIGHTBLOOD");
+ if(self.csqcmodel_modelflags & MF_TRACER2)
+ self.traileffect = particleeffectnum("TR_KNIGHTSPIKE");
+ if(self.csqcmodel_modelflags & MF_TRACER3)
+ self.traileffect = particleeffectnum("TR_VORESPIKE");
+
+ if(self.drawmask)
+ Projectile_DrawTrail(self.origin);
+ else
+ Projectile_ResetTrail(self.origin);
+}
+
// general functions
void CSQCModel_Hook_PreDraw(float isplayer, float islocalplayer)
{
if(!isplayer)
CSQCModel_AutoTagIndex_Apply();
+
+ CSQCModel_Effects_Apply();
}
void CSQCModel_Hook_PreUpdate(float isplayer, float islocalplayer)
{
+ CSQCModel_Effects_PreUpdate();
if(isplayer)
{
// revert to values from server
- CSQCPlayer_ForceModel_PreUpdate();
CSQCPlayer_FallbackFrame_PreUpdate();
+ CSQCPlayer_ForceModel_PreUpdate();
}
}
CSQCPlayer_ForceModel_PostUpdate();
CSQCPlayer_FallbackFrame_PostUpdate();
}
+ CSQCModel_Effects_PostUpdate();
}
string s;
entity e;
- e = CSQCPlayer_GetPlayer(pl + 1);
+ e = CSQCModel_server2csqc(pl + 1);
if(e)
return e.origin;
autocvars.qh
-../csqcmodel/interpolate.qh
+../csqcmodellib/interpolate.qh
teamradar.qh
hud.qh
scoreboard.qh
../server/movelib.qc
main.qh
vehicles/vehicles.qh
-../csqcmodel/settings.qh
-../csqcmodel/common.qh
-../csqcmodel/cl_model.qh
-../csqcmodel/cl_player.qh
+../common/csqcmodel_settings.qh
+../csqcmodellib/common.qh
+../csqcmodellib/cl_model.qh
+../csqcmodellib/cl_player.qh
+projectile.qh
sortlist.qc
miscfunctions.qc
gibs.qc
damage.qc
casings.qc
-../csqcmodel/cl_model.qc
-../csqcmodel/cl_player.qc
+../csqcmodellib/cl_model.qc
+../csqcmodellib/cl_player.qc
effects.qc
wall.qc
modeleffects.qc
announcer.qc
Main.qc
View.qc
-../csqcmodel/interpolate.qc
+../csqcmodellib/interpolate.qc
waypointsprites.qc
movetypes.qc
prandom.qc
.float gravity;
.float snd_looping;
.float silent;
-.float traileffect;
void Projectile_ResetTrail(vector to)
{
--- /dev/null
+.float traileffect;
+void Projectile_ResetTrail(vector to);
+void Projectile_DrawTrail(vector to);
--- /dev/null
+// define this if svqc code wants to use .frame2 and .lerpfrac
+#define CSQCMODEL_HAVE_TWO_FRAMES
+
+// don't define this ever
+//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
+
+// a hack for Xonotic
+#ifdef CSQC
+# define TAG_ENTITY_NAME tag_networkentity
+# define TAG_ENTITY_TYPE float
+.float tag_networkentity;
+#else
+# define TAG_ENTITY_NAME tag_entity
+# define TAG_ENTITY_TYPE entity
+#endif
+
+// add properties you want networked to CSQC here
+#define CSQCMODEL_EXTRAPROPERTIES \
+ CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) \
+ CSQCMODEL_PROPERTY(2, float, ReadInt24_t, WriteInt24_t, effects) \
+ CSQCMODEL_PROPERTY(4, float, ReadByte, WriteByte, modelflags) \
+ CSQCMODEL_PROPERTY_SCALED(8, float, ReadByte, WriteByte, alpha, 255, 0, 255) \
+ CSQCMODEL_PROPERTY(16, float, ReadByte, WriteByte, skin) \
+ CSQCMODEL_IF(isplayer) \
+ CSQCMODEL_ENDIF \
+ CSQCMODEL_IF(!isplayer) \
+ CSQCMODEL_PROPERTY(32, TAG_ENTITY_TYPE, ReadShort, WriteEntity, TAG_ENTITY_NAME) \
+ CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_x, 255, 0, 255) \
+ CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_y, 255, 0, 255) \
+ CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_z, 255, 0, 255) \
+ CSQCMODEL_ENDIF
+// TODO get rid of colormod/glowmod here, find good solution for nex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
+
+// add hook function calls here
+#define CSQCMODEL_HOOK_PREUPDATE \
+ CSQCModel_Hook_PreUpdate(isplayer, islocalplayer);
+#define CSQCMODEL_HOOK_POSTUPDATE \
+ CSQCModel_Hook_PostUpdate(isplayer, islocalplayer);
+#define CSQCMODEL_HOOK_PREDRAW \
+ CSQCModel_Hook_PreDraw(isplayer, islocalplayer);
+#define CSQCPLAYER_HOOK_POSTCAMERASETUP
+
+// force updates of player entities that often even if unchanged
+#define CSQCPLAYER_FORCE_UPDATES 0.25
+
+// mod must define:
+//vector PL_MIN = ...;
+//vector PL_MAX = ...;
+//vector PL_VIEW_OFS = ...;
+//vector PL_CROUCH_MIN = ...;
+//vector PL_CROUCH_MAX = ...;
+//vector PL_CROUCH_VIEW_OFS = ...;
+
+#ifdef SVQC
+# ifdef NO_LEGACY_NETWORKING
+# define CSQCMODEL_AUTOINIT() CSQCModel_LinkEntity()
+# define CSQCMODEL_AUTOUPDATE() CSQCModel_CheckUpdate()
+# else
+.float iscsqcmodel;
+float autocvar_sv_use_csqc_players;
+# define CSQCMODEL_AUTOINIT() \
+ if(autocvar_sv_use_csqc_players) \
+ { \
+ CSQCModel_LinkEntity(); \
+ self.iscsqcmodel = 1; \
+ } \
+ else \
+ self.iscsqcmodel = 0
+# define CSQCMODEL_AUTOUPDATE() \
+ if(autocvar_sv_use_csqc_players && !self.iscsqcmodel) \
+ { \
+ CSQCModel_LinkEntity(); \
+ self.iscsqcmodel = 1; \
+ } \
+ if(!autocvar_sv_use_csqc_players && self.iscsqcmodel) \
+ { \
+ CSQCModel_UnlinkEntity(); \
+ self.iscsqcmodel = 0; \
+ } \
+ if(self.iscsqcmodel) \
+ CSQCModel_CheckUpdate()
+# endif
+#endif
+
+#define CSQCMODEL_EF_INVISIBLE EF_SELECTABLE
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-var float autocvar_cl_lerpanim_maxdelta_framegroups = 0.1;
-var float autocvar_cl_nolerp = 0;
-
-.float csqcmodel_lerpfrac;
-.float csqcmodel_lerpfrac2;
-.float csqcmodel_lerpfractime;
-.float csqcmodel_lerpfrac2time;
-.float csqcmodel_teleported;
-
-void CSQCModel_InterpolateAnimation_PreNote(float sf)
-{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
- if(sf & CSQCMODEL_PROPERTY_FRAME)
- {
- self.frame3 = self.frame;
- self.frame3time = self.frame1time;
- }
- if(sf & CSQCMODEL_PROPERTY_FRAME2)
- {
- self.frame4 = self.frame2;
- self.frame4time = self.frame2time;
- }
- if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
- {
- self.csqcmodel_lerpfrac2 = self.csqcmodel_lerpfrac;
- self.csqcmodel_lerpfrac2time = self.csqcmodel_lerpfractime;
- self.lerpfrac = self.csqcmodel_lerpfrac;
- }
-#else
- if(sf & CSQCMODEL_PROPERTY_FRAME)
- {
- self.frame2 = self.frame;
- self.frame2time = self.frame1time;
- }
-#endif
-}
-
-void CSQCModel_InterpolateAnimation_Note(float sf)
-{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
- if(sf & CSQCMODEL_PROPERTY_FRAME)
- {
- self.frame1time = time;
- }
- if(sf & CSQCMODEL_PROPERTY_FRAME2)
- {
- self.frame2time = time;
- }
- if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
- {
- self.csqcmodel_lerpfrac = self.lerpfrac;
- self.csqcmodel_lerpfractime = time;
- }
-#else
- if(sf & CSQCMODEL_PROPERTY_FRAME)
- {
- self.frame1time = time;
- }
-#endif
-}
-
-void CSQCModel_InterpolateAnimation_Do()
-{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
- if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
- {
- self.lerpfrac = self.csqcmodel_lerpfrac;
- self.lerpfrac3 = 0;
- self.lerpfrac4 = 0;
- }
- else
- {
- float l13, l24, llf;
- float l24_13;
-
- if(self.frame3time == 0) // if frame1/3 were not previously displayed, only frame1 can make sense
- l13 = 1;
- else
- l13 = bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-
- if(self.frame4time == 0) // if frame2/4 were not previously displayed, only frame2 can make sense
- l24 = 1;
- else
- l24 = bound(0, (time - self.frame2time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-
- if(self.csqcmodel_lerpfrac2time == 0) // if there is no old lerpfrac (newly displayed model), only lerpfrac makes sense
- llf = 1;
- else
- llf = bound(0, (time - self.csqcmodel_lerpfractime) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-
- l24_13 = self.csqcmodel_lerpfrac * llf + self.csqcmodel_lerpfrac2 * (1 - llf);
-
- self.lerpfrac = l24 * l24_13;
- self.lerpfrac4 = (1 - l24) * l24_13;
- self.lerpfrac3 = (1 - l13) * (1 - l24_13);
-
- if(l24_13 == 0) // if frames 2/4 are not displayed, clear their frametime
- {
- self.frame2time = 0;
- self.frame4time = 0;
- }
-
- if(l24_13 == 1) // if frames 1/3 are not displayed, clear their frametime
- {
- self.frame1time = 0;
- self.frame3time = 0;
- }
- }
-#else
- if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
- {
- self.lerpfrac = 0;
- }
- else
- {
- self.lerpfrac = 1 - bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
- }
-#endif
-}
-
-void CSQCModel_Draw()
-{
- // some nice flags for CSQCMODEL_IF and the hooks
- float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
- float islocalplayer = (self.entnum == player_localnum + 1);
- float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
-
- // we don't do this for the local player as that one is already handled
- // by CSQCPlayer_SetCamera()
- if(!CSQCPlayer_IsLocalPlayer())
- InterpolateOrigin_Do();
-
- // TODO csqcplayers: run prediction here too
- CSQCModel_InterpolateAnimation_Do();
-
- { CSQCMODEL_HOOK_PREDRAW }
-
- // inherit draw flags easily
- entity root = self;
- while(root.tag_entity)
- root = root.tag_entity;
- if(self != root)
- {
- self.renderflags &~= RF_EXTERNALMODEL | RF_VIEWMODEL;
- self.renderflags |= (root.renderflags & (RF_EXTERNALMODEL | RF_VIEWMODEL));
- }
-}
-
-void CSQCModel_Read()
-{
- float sf;
- sf = ReadShort();
-
- // some nice flags for CSQCMODEL_IF and the hooks
- float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
- float islocalplayer = (self.entnum == player_localnum + 1);
- float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
-
- self.iflags |= IFLAG_ANGLES; // interpolate angles too
-
- { CSQCMODEL_HOOK_PREUPDATE }
-
- CSQCPlayer_PreUpdate();
- InterpolateOrigin_Undo();
- CSQCModel_InterpolateAnimation_PreNote(sf);
-
-#define CSQCMODEL_IF(cond) if(cond) {
-#define CSQCMODEL_ENDIF }
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
- if(sf & flag) \
- self.f = r();
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
- if(sf & flag) \
- self.f = r() / s;
- ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-
- if(sf & CSQCMODEL_PROPERTY_MODELINDEX)
- setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
-
- if(sf & CSQCMODEL_PROPERTY_TELEPORTED)
- {
- self.iflags |= IFLAG_TELEPORTED;
- self.csqcmodel_teleported = 1;
- }
-
- CSQCModel_InterpolateAnimation_Note(sf);
- InterpolateOrigin_Note();
- CSQCPlayer_PostUpdate();
-
- { CSQCMODEL_HOOK_POSTUPDATE }
-
-#ifdef CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
- InterpolateOrigin_Do();
- CSQCModel_InterpolateAnimation_Do();
-#endif
-
- // relink
- setorigin(self, self.origin);
-
- // set obvious render flags
-#ifdef COMPAT_XON050_ENGINE
- if(self.entnum == player_localentnum || self.entnum == spectatee_status)
-#else
- if(self.entnum == player_localentnum)
-#endif
- self.renderflags |= RF_EXTERNALMODEL;
- else
- self.renderflags &~= RF_EXTERNALMODEL;
-
- // draw it
- self.drawmask = MASK_NORMAL;
- self.predraw = CSQCModel_Draw;
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-void CSQCModel_Read();
-
-#define CSQCMODEL_IF(cond)
-#define CSQCMODEL_ENDIF
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
- .t f;
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
- ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-var float autocvar_cl_predictionerrorcompensation = 0;
-
-// engine stuff
-.float pmove_flags;
-float pmove_onground; // weird engine flag we shouldn't really use but have to for now
-#define PMF_JUMP_HELD 1
-#define PMF_DUCKED 4
-#define PMF_ONGROUND 8
-#define REFDEFFLAG_TELEPORTED 1
-#define REFDEFFLAG_JUMPING 2
-
-entity csqcplayer;
-vector csqcplayer_origin, csqcplayer_velocity;
-float csqcplayer_sequence, player_pmflags;
-float csqcplayer_moveframe;
-vector csqcplayer_predictionerror;
-float csqcplayer_predictionerrortime;
-
-vector CSQCPlayer_GetPredictionError()
-{
- if(!autocvar_cl_predictionerrorcompensation)
- return '0 0 0';
- if(time < csqcplayer_predictionerrortime)
- return csqcplayer_predictionerror * (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation;
- return '0 0 0';
-}
-
-void CSQCPlayer_SetPredictionError(vector v)
-{
- if(!autocvar_cl_predictionerrorcompensation)
- return;
- csqcplayer_predictionerror = (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation * csqcplayer_predictionerror + v;
- csqcplayer_predictionerrortime = time + 1.0 / autocvar_cl_predictionerrorcompensation;
-}
-
-void CSQCPlayer_Unpredict()
-{
- if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
- return;
- if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
- error("Cannot unpredict in current status");
- self.origin = csqcplayer_origin;
- self.velocity = csqcplayer_velocity;
- csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side)
- self.pmove_flags = player_pmflags;
-}
-
-void CSQCPlayer_SetMinsMaxs()
-{
- if(self.pmove_flags & PMF_DUCKED)
- {
- self.mins = PL_CROUCH_MIN;
- self.maxs = PL_CROUCH_MAX;
- self.view_ofs = PL_CROUCH_VIEW_OFS;
- }
- else
- {
- self.mins = PL_MIN;
- self.maxs = PL_MAX;
- self.view_ofs = PL_VIEW_OFS;
- }
-}
-
-void CSQCPlayer_SavePrediction()
-{
- player_pmflags = self.pmove_flags;
- csqcplayer_origin = self.origin;
- csqcplayer_velocity = self.velocity;
- csqcplayer_sequence = servercommandframe;
- csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
-}
-
-void CSQCPlayer_PredictTo(float endframe)
-{
- CSQCPlayer_Unpredict();
- CSQCPlayer_SetMinsMaxs();
-
- csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
-
- if (getstatf(STAT_HEALTH) <= 0)
- {
- csqcplayer_moveframe = clientcommandframe;
- getinputstate(csqcplayer_moveframe-1);
- return;
- }
-
- while(csqcplayer_moveframe < endframe)
- {
- if (!getinputstate(csqcplayer_moveframe))
- {
- break;
- }
- if(input_timelength <= 0.0005) // too short move
- {
- dprint("CSQC physics hack: too short frame skipped\n");
- // even if not running physics, handle releasing the jump key
- if(!(input_buttons & 4))
- self.pmove_flags &~= PMF_JUMP_HELD;
- }
- else if(input_timelength > 0.05) // too long move
- {
- dprint("CSQC physics hack: too long frame split in two\n");
- input_timelength *= 0.5;
- runstandardplayerphysics(self);
- CSQCPlayer_SetMinsMaxs();
- runstandardplayerphysics(self);
- CSQCPlayer_SetMinsMaxs();
- }
- else
- {
- runstandardplayerphysics(self);
- CSQCPlayer_SetMinsMaxs();
- }
- csqcplayer_moveframe++;
- }
-
- //add in anything that was applied after (for low packet rate protocols)
- input_angles = view_angles;
-}
-
-float CSQCPlayer_IsLocalPlayer()
-{
- return (self == csqcplayer);
-}
-
-void(entity e, float fl) V_CalcRefdef = #640; // DP_CSQC_V_CALCREFDEF
-
-void CSQCPlayer_SetCamera()
-{
- if(csqcplayer)
- {
- entity oldself;
- oldself = self;
- self = csqcplayer;
-
-#ifdef COMPAT_XON050_ENGINE
- if(servercommandframe == 0 || !(checkextension("DP_CSQC_V_CALCREFDEF") || checkextension("DP_CSQC_V_CALCREFDEF_WIP1")))
-#else
- if(servercommandframe == 0)
-#endif
- {
- InterpolateOrigin_Do();
- self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
-
- // get crouch state from the server
- if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
- self.pmove_flags &~= PMF_DUCKED;
- else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
- self.pmove_flags |= PMF_DUCKED;
-
- // get onground state from the server
- if(pmove_onground)
- self.pmove_flags |= PMF_ONGROUND;
- else
- self.pmove_flags &~= PMF_ONGROUND;
-
- CSQCPlayer_SetMinsMaxs();
-
- // override it back just in case
- self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
- }
- else
- {
- if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
- {
- vector o, v;
- o = self.origin;
- v = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
- csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
- CSQCPlayer_PredictTo(servercommandframe + 1);
- CSQCPlayer_SetPredictionError(o - self.origin);
- self.origin = o;
- self.velocity = v;
-
- // get crouch state from the server
- if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
- self.pmove_flags &~= PMF_DUCKED;
- else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
- self.pmove_flags |= PMF_DUCKED;
-
- // get onground state from the server
- if(pmove_onground)
- self.pmove_flags |= PMF_ONGROUND;
- else
- self.pmove_flags &~= PMF_ONGROUND;
-
- CSQCPlayer_SavePrediction();
- }
- CSQCPlayer_PredictTo(clientcommandframe + 1);
-
- CSQCPlayer_SetMinsMaxs();
- }
-
- // relink
- setorigin(self, self.origin);
-
- // FIXME support svc_setview?
-
- if(checkextension("DP_CSQC_V_CALCREFDEF") || checkextension("DP_CSQC_V_CALCREFDEF_WIP1"))
- {
- var float refdefflags = 0;
-
- if(self.csqcmodel_teleported)
- {
- refdefflags |= REFDEFFLAG_TELEPORTED;
- self.csqcmodel_teleported = 0;
- }
-
- if(input_buttons & 4)
- refdefflags |= REFDEFFLAG_JUMPING;
-
- V_CalcRefdef(self, refdefflags);
- }
- else
- setproperty(VF_ORIGIN, self.origin + self.view_ofs);
- self.angles_y = input_angles_y;
-
- { CSQCPLAYER_HOOK_POSTCAMERASETUP }
-
- self = oldself;
- }
-}
-
-void CSQCPlayer_Remove()
-{
- if(self.entnum != player_localnum + 1)
- return;
- csqcplayer = world;
- cvar_clientsettemp("cl_movement_replay", "1");
-}
-
-float CSQCPlayer_PreUpdate()
-{
- if(self.entnum != player_localnum + 1)
- return 0;
- cvar_clientsettemp("cl_movement_replay", "0");
- if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
- CSQCPlayer_Unpredict();
- return 1;
-}
-
-float CSQCPlayer_PostUpdate()
-{
- if(self.entnum != player_localentnum)
- return 0;
- csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
- csqcplayer = self;
- self.entremove = CSQCPlayer_Remove;
- return 1;
-}
-
-entity CSQCPlayer_GetPlayer(float pl)
-{
- return findfloat(world, entnum, pl); // FIXME optimize this using an array
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-float csqcplayer_status;
-#define CSQCPLAYERSTATUS_UNPREDICTED 0
-#define CSQCPLAYERSTATUS_FROMSERVER 1
-#define CSQCPLAYERSTATUS_PREDICTED 2
-
-void CSQCPlayer_SetCamera();
-float CSQCPlayer_PreUpdate();
-float CSQCPlayer_PostUpdate();
-float CSQCPlayer_IsLocalPlayer();
-entity CSQCPlayer_GetPlayer(float pl);
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-noref string csqcmodel_license = "\
-Copyright (c) 2011 Rudolf Polzer\
-\
-Permission is hereby granted, free of charge, to any person obtaining a copy\
-of this software and associated documentation files (the \"Software\"), to\
-deal in the Software without restriction, including without limitation the\
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\
-sell copies of the Software, and to permit persons to whom the Software is\
-furnished to do so, subject to the following conditions:\
-\
-The above copyright notice and this permission notice shall be included in\
-all copies or substantial portions of the Software.\
-\
-THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\
-IN THE SOFTWARE.\
-";
-
-.vector glowmod;
-.vector view_ofs;
-.float frame;
-.float frame1time;
-.float frame2;
-.float frame2time;
-.float lerpfrac;
-
-#define CSQCMODEL_PROPERTY_FRAME 32768
-#define CSQCMODEL_PROPERTY_FRAME2 16384
-#define CSQCMODEL_PROPERTY_LERPFRAC 8192
-#define CSQCMODEL_PROPERTY_TELEPORTED 4096 // the "teleport bit" cancelling interpolation
-#define CSQCMODEL_PROPERTY_MODELINDEX 2048
-#define CSQCMODEL_PROPERTY_ORIGIN 1024
-#define CSQCMODEL_PROPERTY_YAW 512
-#define CSQCMODEL_PROPERTY_PITCHROLL 256
-
-#define ALLPROPERTIES_COMMON \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME, float, ReadByte, WriteByte, frame) \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_MODELINDEX, float, ReadShort, WriteShort, modelindex) \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_x) \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_y) \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_z) \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_x) \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_YAW, float, ReadAngle, WriteAngle, angles_y) \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_z) \
- CSQCMODEL_EXTRAPROPERTIES
-
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
-.float frame3;
-.float frame3time;
-.float lerpfrac3;
-.float frame4;
-.float frame4time;
-.float lerpfrac4;
-#define ALLPROPERTIES ALLPROPERTIES_COMMON \
- CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME2, float, ReadByte, WriteByte, frame2) \
- CSQCMODEL_PROPERTY_SCALED(CSQCMODEL_PROPERTY_LERPFRAC, float, ReadByte, WriteByte, lerpfrac, 255, 0, 255)
-#else
-#define ALLPROPERTIES ALLPROPERTIES_COMMON
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-.vector iorigin1, iorigin2;
-.vector ivelocity1, ivelocity2;
-.vector iforward1, iforward2;
-.vector iup1, iup2;
-.float itime1, itime2;
-void InterpolateOrigin_Reset()
-{
- self.iflags &~= IFLAG_INTERNALMASK;
- self.itime1 = self.itime2 = 0;
-}
-void InterpolateOrigin_Note()
-{
- float dt;
- float f0;
-
- dt = time - self.itime2;
-
- f0 = self.iflags;
- if(self.iflags & IFLAG_PREVALID)
- self.iflags |= IFLAG_VALID;
- else
- self.iflags |= IFLAG_PREVALID;
-
- self.iorigin1 = self.iorigin2;
- self.iorigin2 = self.origin;
-
- if(self.iflags & IFLAG_AUTOANGLES)
- if(self.iorigin2 != self.iorigin1)
- self.angles = vectoangles(self.iorigin2 - self.iorigin1);
-
- if(self.iflags & IFLAG_ANGLES)
- {
- fixedmakevectors(self.angles);
- if(f0 & IFLAG_VALID)
- {
- self.iforward1 = self.iforward2;
- self.iup1 = self.iup2;
- }
- else
- {
- self.iforward1 = v_forward;
- self.iup1 = v_up;
- }
- self.iforward2 = v_forward;
- self.iup2 = v_up;
- }
-
- if(self.iflags & IFLAG_VELOCITY)
- {
- self.ivelocity1 = self.ivelocity2;
- self.ivelocity2 = self.velocity;
- }
-
- if(self.iflags & IFLAG_TELEPORTED)
- {
- self.iflags &~= IFLAG_TELEPORTED;
- self.itime1 = self.itime2 = time; // don't lerp
- }
- else if(vlen(self.iorigin2 - self.iorigin1) > 1000)
- {
- self.itime1 = self.itime2 = time; // don't lerp
- }
- else if((self.iflags & IFLAG_VELOCITY) && (vlen(self.ivelocity2 - self.ivelocity1) > 1000))
- {
- self.itime1 = self.itime2 = time; // don't lerp
- }
- else if(dt >= 0.2)
- {
- self.itime1 = self.itime2 = time;
- }
- else
- {
- self.itime1 = serverprevtime;
- self.itime2 = time;
- }
-}
-void InterpolateOrigin_Do()
-{
- vector forward, up;
- if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
- {
- float f;
- f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1 + autocvar_cl_lerpexcess);
- self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2;
- if(self.iflags & IFLAG_ANGLES)
- {
- forward = (1 - f) * self.iforward1 + f * self.iforward2;
- up = (1 - f) * self.iup1 + f * self.iup2;
- self.angles = fixedvectoangles2(forward, up);
- }
- if(self.iflags & IFLAG_VELOCITY)
- self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
- }
-}
-void InterpolateOrigin_Undo()
-{
- self.origin = self.iorigin2;
- if(self.iflags & IFLAG_ANGLES)
- self.angles = fixedvectoangles2(self.iforward2, self.iup2);
- if(self.iflags & IFLAG_VELOCITY)
- self.velocity = self.ivelocity2;
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-.float iflags;
-#define IFLAG_VELOCITY 1
-#define IFLAG_ANGLES 2
-#define IFLAG_AUTOANGLES 4
-#define IFLAG_VALID 8
-#define IFLAG_PREVALID 16
-#define IFLAG_TELEPORTED 32
-#define IFLAG_INTERNALMASK (IFLAG_VALID | IFLAG_PREVALID)
-
-// call this BEFORE reading an entity update
-void InterpolateOrigin_Undo();
-
-// call this AFTER receiving an entity update
-void InterpolateOrigin_Note();
-
-// call this when the entity got teleported, before InterpolateOrigin_Note
-void InterpolateOrigin_Reset();
-
-// call this BEFORE drawing
-void InterpolateOrigin_Do();
+++ /dev/null
-// define this if svqc code wants to use .frame2 and .lerpfrac
-#define CSQCMODEL_HAVE_TWO_FRAMES
-
-// don't define this ever
-//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
-
-// a hack for Xonotic
-#ifdef CSQC
-# define TAG_ENTITY_NAME tag_networkentity
-# define TAG_ENTITY_TYPE float
-.float tag_networkentity;
-#else
-# define TAG_ENTITY_NAME tag_entity
-# define TAG_ENTITY_TYPE entity
-#endif
-
-// add properties you want networked to CSQC here
-#define CSQCMODEL_EXTRAPROPERTIES \
- CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) \
- CSQCMODEL_PROPERTY(2, float, ReadInt24_t, WriteInt24_t, effects) \
- CSQCMODEL_PROPERTY(4, float, ReadByte, WriteByte, modelflags) \
- CSQCMODEL_PROPERTY_SCALED(8, float, ReadByte, WriteByte, alpha, 255, 0, 255) \
- CSQCMODEL_PROPERTY(16, float, ReadByte, WriteByte, skin) \
- CSQCMODEL_IF(isplayer) \
- CSQCMODEL_ENDIF \
- CSQCMODEL_IF(!isplayer) \
- CSQCMODEL_PROPERTY(32, TAG_ENTITY_TYPE, ReadShort, WriteEntity, TAG_ENTITY_NAME) \
- CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_x, 255, 0, 255) \
- CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_y, 255, 0, 255) \
- CSQCMODEL_PROPERTY_SCALED(64, float, ReadByte, WriteByte, glowmod_z, 255, 0, 255) \
- CSQCMODEL_ENDIF
-// TODO get rid of colormod/glowmod here, find good solution for nex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
-
-// add hook function calls here
-#define CSQCMODEL_HOOK_PREUPDATE \
- CSQCModel_Hook_PreUpdate(isplayer, islocalplayer);
-#define CSQCMODEL_HOOK_POSTUPDATE \
- CSQCModel_Hook_PostUpdate(isplayer, islocalplayer);
-#define CSQCMODEL_HOOK_PREDRAW \
- CSQCModel_Hook_PreDraw(isplayer, islocalplayer);
-#define CSQCPLAYER_HOOK_POSTCAMERASETUP
-
-// mod must define:
-//vector PL_MIN = ...;
-//vector PL_MAX = ...;
-//vector PL_VIEW_OFS = ...;
-//vector PL_CROUCH_MIN = ...;
-//vector PL_CROUCH_MAX = ...;
-//vector PL_CROUCH_VIEW_OFS = ...;
-
-#ifdef SVQC
-# ifdef NO_LEGACY_NETWORKING
-# define CSQCMODEL_AUTOINIT() CSQCModel_LinkEntity()
-# define CSQCMODEL_AUTOUPDATE() CSQCModel_CheckUpdate()
-# else
-.float iscsqcmodel;
-float autocvar_sv_use_csqc_players;
-# define CSQCMODEL_AUTOINIT() \
- if(autocvar_sv_use_csqc_players) \
- { \
- CSQCModel_LinkEntity(); \
- self.iscsqcmodel = 1; \
- } \
- else \
- self.iscsqcmodel = 0
-# define CSQCMODEL_AUTOUPDATE() \
- if(autocvar_sv_use_csqc_players && !self.iscsqcmodel) \
- { \
- CSQCModel_LinkEntity(); \
- self.iscsqcmodel = 1; \
- } \
- if(!autocvar_sv_use_csqc_players && self.iscsqcmodel) \
- { \
- CSQCModel_UnlinkEntity(); \
- self.iscsqcmodel = 0; \
- } \
- if(self.iscsqcmodel) \
- CSQCModel_CheckUpdate()
-# endif
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-// generic CSQC model code
-
-float CSQCModel_Send(entity to, float sf)
-{
- // some nice flags for CSQCMODEL_IF
- float isplayer = (self.flags & FL_CLIENT);
- float islocalplayer = (self == to);
- float isnolocalplayer = (isplayer && (self != to));
-
- WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL);
- WriteShort(MSG_ENTITY, sf);
-
-#define CSQCMODEL_IF(cond) if(cond) {
-#define CSQCMODEL_ENDIF }
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
- if(sf & flag) \
- { \
- w(MSG_ENTITY, self.csqcmodel_##f); \
- }
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
- ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-
- return TRUE;
-}
-
-void CSQCModel_CheckUpdate()
-{
- // some nice flags for CSQCMODEL_IF
- float isplayer = (self.flags & FL_CLIENT);
- float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
- float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
-
- if(self.effects & EF_RESTARTANIM_BIT)
- {
- self.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
- self.effects &~= EF_RESTARTANIM_BIT;
- }
-
- if(self.effects & EF_TELEPORT_BIT)
- {
- self.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
- self.effects &~= EF_TELEPORT_BIT;
- }
-
-#define CSQCMODEL_IF(cond) if(cond) {
-#define CSQCMODEL_ENDIF }
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
- { \
- t tmp = self.f; \
- if(tmp != self.csqcmodel_##f) \
- { \
- self.csqcmodel_##f = tmp; \
- self.SendFlags |= flag; \
- } \
- }
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
- { \
- t tmp = bound(mi, s * self.f, ma); \
- if(tmp != self.csqcmodel_##f) \
- { \
- self.csqcmodel_##f = tmp; \
- self.SendFlags |= flag; \
- } \
- }
- ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
-}
-
-void CSQCModel_LinkEntity()
-{
- self.SendEntity = CSQCModel_Send;
- self.SendFlags = 0xFFFFFF;
-}
-
-void CSQCModel_UnlinkEntity()
-{
- self.SendEntity = func_null;
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Rudolf Polzer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-// generic CSQC model code
-
-void CSQCModel_CheckUpdate();
-void CSQCModel_LinkEntity();
-void CSQCModel_UnlinkEntity();
-
-#define CSQCMODEL_IF(cond)
-#define CSQCMODEL_ENDIF
-#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
- .t f; \
- .t csqcmodel_##f;
-#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
- ALLPROPERTIES
-#undef CSQCMODEL_PROPERTY_SCALED
-#undef CSQCMODEL_PROPERTY
-#undef CSQCMODEL_ENDIF
-#undef CSQCMODEL_IF
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+var float autocvar_cl_lerpanim_maxdelta_framegroups = 0.1;
+var float autocvar_cl_nolerp = 0;
+
+.float csqcmodel_lerpfrac;
+.float csqcmodel_lerpfrac2;
+.float csqcmodel_lerpfractime;
+.float csqcmodel_lerpfrac2time;
+
+void CSQCModel_InterpolateAnimation_PreNote(float sf)
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+ if(sf & CSQCMODEL_PROPERTY_FRAME)
+ {
+ self.frame3 = self.frame;
+ self.frame3time = self.frame1time;
+ }
+ if(sf & CSQCMODEL_PROPERTY_FRAME2)
+ {
+ self.frame4 = self.frame2;
+ self.frame4time = self.frame2time;
+ }
+ if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
+ {
+ self.csqcmodel_lerpfrac2 = self.csqcmodel_lerpfrac;
+ self.csqcmodel_lerpfrac2time = self.csqcmodel_lerpfractime;
+ self.lerpfrac = self.csqcmodel_lerpfrac;
+ }
+#else
+ if(sf & CSQCMODEL_PROPERTY_FRAME)
+ {
+ self.frame2 = self.frame;
+ self.frame2time = self.frame1time;
+ }
+#endif
+}
+
+void CSQCModel_InterpolateAnimation_Note(float sf)
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+ if(sf & CSQCMODEL_PROPERTY_FRAME)
+ {
+ self.frame1time = time;
+ }
+ if(sf & CSQCMODEL_PROPERTY_FRAME2)
+ {
+ self.frame2time = time;
+ }
+ if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
+ {
+ self.csqcmodel_lerpfrac = self.lerpfrac;
+ self.csqcmodel_lerpfractime = time;
+ }
+#else
+ if(sf & CSQCMODEL_PROPERTY_FRAME)
+ {
+ self.frame1time = time;
+ }
+#endif
+}
+
+void CSQCModel_InterpolateAnimation_Do()
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+ if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
+ {
+ self.lerpfrac = self.csqcmodel_lerpfrac;
+ self.lerpfrac3 = 0;
+ self.lerpfrac4 = 0;
+ }
+ else
+ {
+ float l13, l24, llf;
+ float l24_13;
+
+ if(self.frame3time == 0) // if frame1/3 were not previously displayed, only frame1 can make sense
+ l13 = 1;
+ else
+ l13 = bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+ if(self.frame4time == 0) // if frame2/4 were not previously displayed, only frame2 can make sense
+ l24 = 1;
+ else
+ l24 = bound(0, (time - self.frame2time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+ if(self.csqcmodel_lerpfrac2time == 0) // if there is no old lerpfrac (newly displayed model), only lerpfrac makes sense
+ llf = 1;
+ else
+ llf = bound(0, (time - self.csqcmodel_lerpfractime) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+ l24_13 = self.csqcmodel_lerpfrac * llf + self.csqcmodel_lerpfrac2 * (1 - llf);
+
+ self.lerpfrac = l24 * l24_13;
+ self.lerpfrac4 = (1 - l24) * l24_13;
+ self.lerpfrac3 = (1 - l13) * (1 - l24_13);
+
+ if(l24_13 == 0) // if frames 2/4 are not displayed, clear their frametime
+ {
+ self.frame2time = 0;
+ self.frame4time = 0;
+ }
+
+ if(l24_13 == 1) // if frames 1/3 are not displayed, clear their frametime
+ {
+ self.frame1time = 0;
+ self.frame3time = 0;
+ }
+ }
+#else
+ if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
+ {
+ self.lerpfrac = 0;
+ }
+ else
+ {
+ self.lerpfrac = 1 - bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+ }
+#endif
+}
+
+void CSQCModel_Draw()
+{
+ // some nice flags for CSQCMODEL_IF and the hooks
+ float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
+ float islocalplayer = (self.entnum == player_localnum + 1);
+ float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
+
+ // we don't do this for the local player as that one is already handled
+ // by CSQCPlayer_SetCamera()
+ if(!CSQCPlayer_IsLocalPlayer())
+ InterpolateOrigin_Do();
+
+ // TODO csqcplayers: run prediction here too
+ CSQCModel_InterpolateAnimation_Do();
+
+ { CSQCMODEL_HOOK_PREDRAW }
+
+ // inherit draw flags easily
+ entity root = self;
+ while(root.tag_entity)
+ root = root.tag_entity;
+ if(self != root)
+ {
+ self.renderflags &~= RF_EXTERNALMODEL | RF_VIEWMODEL;
+ self.renderflags |= (root.renderflags & (RF_EXTERNALMODEL | RF_VIEWMODEL));
+ }
+
+ // we're drawn, now teleporting is over
+ self.csqcmodel_teleported = 0;
+}
+
+void CSQCModel_Read()
+{
+ float sf;
+ sf = ReadShort();
+
+ // some nice flags for CSQCMODEL_IF and the hooks
+ float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
+ float islocalplayer = (self.entnum == player_localnum + 1);
+ float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
+
+ self.iflags |= IFLAG_ANGLES; // interpolate angles too
+
+ { CSQCMODEL_HOOK_PREUPDATE }
+
+ CSQCPlayer_PreUpdate();
+ InterpolateOrigin_Undo();
+ CSQCModel_InterpolateAnimation_PreNote(sf);
+
+#define CSQCMODEL_IF(cond) if(cond) {
+#define CSQCMODEL_ENDIF }
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+ if(sf & flag) \
+ self.f = r();
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
+ if(sf & flag) \
+ self.f = r() / s;
+ ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+
+ if(sf & CSQCMODEL_PROPERTY_MODELINDEX)
+ setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
+
+ if(sf & CSQCMODEL_PROPERTY_TELEPORTED)
+ {
+ self.iflags |= IFLAG_TELEPORTED;
+ self.csqcmodel_teleported = 1;
+ }
+
+ CSQCModel_InterpolateAnimation_Note(sf);
+ InterpolateOrigin_Note();
+ CSQCPlayer_PostUpdate();
+
+ { CSQCMODEL_HOOK_POSTUPDATE }
+
+#ifdef CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
+ InterpolateOrigin_Do();
+ CSQCModel_InterpolateAnimation_Do();
+#endif
+
+ // relink
+ setorigin(self, self.origin);
+
+ // set obvious render flags
+#ifdef COMPAT_XON050_ENGINE
+ if(self.entnum == player_localentnum || self.entnum == spectatee_status)
+#else
+ if(self.entnum == player_localentnum)
+#endif
+ self.renderflags |= RF_EXTERNALMODEL;
+ else
+ self.renderflags &~= RF_EXTERNALMODEL;
+
+ // draw it
+ self.drawmask = MASK_NORMAL;
+ self.predraw = CSQCModel_Draw;
+}
+
+entity CSQCModel_server2csqc(float pl)
+{
+ return findfloat(world, entnum, pl); // FIXME optimize this using an array
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+void CSQCModel_Read();
+
+#define CSQCMODEL_IF(cond)
+#define CSQCMODEL_ENDIF
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+ .t f;
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+ ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+
+entity CSQCModel_server2csqc(float pl);
+.float csqcmodel_teleported;
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+var float autocvar_cl_predictionerrorcompensation = 0;
+
+// engine stuff
+.float pmove_flags;
+float pmove_onground; // weird engine flag we shouldn't really use but have to for now
+#define PMF_JUMP_HELD 1
+#define PMF_DUCKED 4
+#define PMF_ONGROUND 8
+#define REFDEFFLAG_TELEPORTED 1
+#define REFDEFFLAG_JUMPING 2
+
+entity csqcplayer;
+vector csqcplayer_origin, csqcplayer_velocity;
+float csqcplayer_sequence, player_pmflags;
+float csqcplayer_moveframe;
+vector csqcplayer_predictionerror;
+float csqcplayer_predictionerrortime;
+
+vector CSQCPlayer_GetPredictionError()
+{
+ if(!autocvar_cl_predictionerrorcompensation)
+ return '0 0 0';
+ if(time < csqcplayer_predictionerrortime)
+ return csqcplayer_predictionerror * (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation;
+ return '0 0 0';
+}
+
+void CSQCPlayer_SetPredictionError(vector v)
+{
+ if(!autocvar_cl_predictionerrorcompensation)
+ return;
+ csqcplayer_predictionerror = (csqcplayer_predictionerrortime - time) * autocvar_cl_predictionerrorcompensation * csqcplayer_predictionerror + v;
+ csqcplayer_predictionerrortime = time + 1.0 / autocvar_cl_predictionerrorcompensation;
+}
+
+void CSQCPlayer_Unpredict()
+{
+ if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
+ return;
+ if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
+ error("Cannot unpredict in current status");
+ self.origin = csqcplayer_origin;
+ self.velocity = csqcplayer_velocity;
+ csqcplayer_moveframe = csqcplayer_sequence+1; //+1 because the recieved frame has the move already done (server side)
+ self.pmove_flags = player_pmflags;
+}
+
+void CSQCPlayer_SetMinsMaxs()
+{
+ if(self.pmove_flags & PMF_DUCKED)
+ {
+ self.mins = PL_CROUCH_MIN;
+ self.maxs = PL_CROUCH_MAX;
+ self.view_ofs = PL_CROUCH_VIEW_OFS;
+ }
+ else
+ {
+ self.mins = PL_MIN;
+ self.maxs = PL_MAX;
+ self.view_ofs = PL_VIEW_OFS;
+ }
+}
+
+void CSQCPlayer_SavePrediction()
+{
+ player_pmflags = self.pmove_flags;
+ csqcplayer_origin = self.origin;
+ csqcplayer_velocity = self.velocity;
+ csqcplayer_sequence = servercommandframe;
+ csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+}
+
+void CSQCPlayer_PredictTo(float endframe)
+{
+ CSQCPlayer_Unpredict();
+ CSQCPlayer_SetMinsMaxs();
+
+ csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+
+ if (getstatf(STAT_HEALTH) <= 0)
+ {
+ csqcplayer_moveframe = clientcommandframe;
+ getinputstate(csqcplayer_moveframe-1);
+ return;
+ }
+
+ while(csqcplayer_moveframe < endframe)
+ {
+ if (!getinputstate(csqcplayer_moveframe))
+ {
+ break;
+ }
+ if(input_timelength <= 0.0005) // too short move
+ {
+ dprint("CSQC physics hack: too short frame skipped\n");
+ // even if not running physics, handle releasing the jump key
+ if(!(input_buttons & 4))
+ self.pmove_flags &~= PMF_JUMP_HELD;
+ }
+ else if(input_timelength > 0.05) // too long move
+ {
+ dprint("CSQC physics hack: too long frame split in two\n");
+ input_timelength *= 0.5;
+ runstandardplayerphysics(self);
+ CSQCPlayer_SetMinsMaxs();
+ runstandardplayerphysics(self);
+ CSQCPlayer_SetMinsMaxs();
+ }
+ else
+ {
+ runstandardplayerphysics(self);
+ CSQCPlayer_SetMinsMaxs();
+ }
+ csqcplayer_moveframe++;
+ }
+
+ //add in anything that was applied after (for low packet rate protocols)
+ input_angles = view_angles;
+}
+
+float CSQCPlayer_IsLocalPlayer()
+{
+ return (self == csqcplayer);
+}
+
+void(entity e, float fl) V_CalcRefdef = #640; // DP_CSQC_V_CALCREFDEF
+
+void CSQCPlayer_SetCamera()
+{
+ if(csqcplayer)
+ {
+ entity oldself;
+ oldself = self;
+ self = csqcplayer;
+
+#ifdef COMPAT_XON050_ENGINE
+ if(servercommandframe == 0 || !(checkextension("DP_CSQC_V_CALCREFDEF") || checkextension("DP_CSQC_V_CALCREFDEF_WIP1")))
+#else
+ if(servercommandframe == 0)
+#endif
+ {
+ InterpolateOrigin_Do();
+ self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+
+ // get crouch state from the server
+ if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
+ self.pmove_flags &~= PMF_DUCKED;
+ else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
+ self.pmove_flags |= PMF_DUCKED;
+
+ // get onground state from the server
+ if(pmove_onground)
+ self.pmove_flags |= PMF_ONGROUND;
+ else
+ self.pmove_flags &~= PMF_ONGROUND;
+
+ CSQCPlayer_SetMinsMaxs();
+
+ // override it back just in case
+ self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
+ }
+ else
+ {
+ if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
+ {
+ vector o, v;
+ o = self.origin;
+ v = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
+ csqcplayer_status = CSQCPLAYERSTATUS_PREDICTED;
+ CSQCPlayer_PredictTo(servercommandframe + 1);
+ CSQCPlayer_SetPredictionError(o - self.origin);
+ self.origin = o;
+ self.velocity = v;
+
+ // get crouch state from the server
+ if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
+ self.pmove_flags &~= PMF_DUCKED;
+ else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
+ self.pmove_flags |= PMF_DUCKED;
+
+ // get onground state from the server
+ if(pmove_onground)
+ self.pmove_flags |= PMF_ONGROUND;
+ else
+ self.pmove_flags &~= PMF_ONGROUND;
+
+ CSQCPlayer_SavePrediction();
+ }
+ CSQCPlayer_PredictTo(clientcommandframe + 1);
+
+ CSQCPlayer_SetMinsMaxs();
+
+ self.angles_y = input_angles_y;
+ }
+
+ // relink
+ setorigin(self, self.origin);
+
+ self = oldself;
+ }
+
+ entity view;
+#ifdef COMPAT_XON050_ENGINE
+ view = CSQCModel_server2csqc((spectatee_status > 0) ? spectatee_status : player_localentnum);
+#else
+ view = CSQCModel_server2csqc(player_localentnum);
+#endif
+
+#ifdef COMPAT_XON050_ENGINE
+ if(view && !(checkextension("DP_CSQC_V_CALCREFDEF") || checkextension("DP_CSQC_V_CALCREFDEF_WIP1")))
+ {
+ // legacy code, not totally correct, but good enough for not having V_CalcRefdef
+ setproperty(VF_ORIGIN, view.origin + '0 0 1' * getstati(STAT_VIEWHEIGHT));
+ setproperty(VF_ANGLES, view_angles);
+ }
+ else
+#endif
+ if(view)
+ {
+ var float refdefflags = 0;
+
+ if(view.csqcmodel_teleported)
+ refdefflags |= REFDEFFLAG_TELEPORTED;
+
+ if(input_buttons & 4)
+ refdefflags |= REFDEFFLAG_JUMPING;
+
+ V_CalcRefdef(view, refdefflags);
+ }
+ else
+ {
+ setproperty(VF_ORIGIN, pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT));
+ setproperty(VF_ANGLES, view_angles);
+ }
+
+ { CSQCPLAYER_HOOK_POSTCAMERASETUP }
+}
+
+void CSQCPlayer_Remove()
+{
+ if(self.entnum != player_localnum + 1)
+ return;
+ csqcplayer = world;
+ cvar_clientsettemp("cl_movement_replay", "1");
+}
+
+float CSQCPlayer_PreUpdate()
+{
+ if(self.entnum != player_localnum + 1)
+ return 0;
+ cvar_clientsettemp("cl_movement_replay", "0");
+ if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
+ CSQCPlayer_Unpredict();
+ return 1;
+}
+
+float CSQCPlayer_PostUpdate()
+{
+ if(self.entnum != player_localentnum)
+ return 0;
+ csqcplayer_status = CSQCPLAYERSTATUS_FROMSERVER;
+ csqcplayer = self;
+ self.entremove = CSQCPlayer_Remove;
+ return 1;
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+float csqcplayer_status;
+#define CSQCPLAYERSTATUS_UNPREDICTED 0
+#define CSQCPLAYERSTATUS_FROMSERVER 1
+#define CSQCPLAYERSTATUS_PREDICTED 2
+
+void CSQCPlayer_SetCamera();
+float CSQCPlayer_PreUpdate();
+float CSQCPlayer_PostUpdate();
+float CSQCPlayer_IsLocalPlayer();
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+noref string csqcmodel_license = "\
+Copyright (c) 2011 Rudolf Polzer\
+\
+Permission is hereby granted, free of charge, to any person obtaining a copy\
+of this software and associated documentation files (the \"Software\"), to\
+deal in the Software without restriction, including without limitation the\
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\
+sell copies of the Software, and to permit persons to whom the Software is\
+furnished to do so, subject to the following conditions:\
+\
+The above copyright notice and this permission notice shall be included in\
+all copies or substantial portions of the Software.\
+\
+THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\
+IN THE SOFTWARE.\
+";
+
+.vector glowmod;
+.vector view_ofs;
+.float frame;
+.float frame1time;
+.float frame2;
+.float frame2time;
+.float lerpfrac;
+
+#define CSQCMODEL_PROPERTY_FRAME 32768
+#define CSQCMODEL_PROPERTY_FRAME2 16384
+#define CSQCMODEL_PROPERTY_LERPFRAC 8192
+#define CSQCMODEL_PROPERTY_TELEPORTED 4096 // the "teleport bit" cancelling interpolation
+#define CSQCMODEL_PROPERTY_MODELINDEX 2048
+#define CSQCMODEL_PROPERTY_ORIGIN 1024
+#define CSQCMODEL_PROPERTY_YAW 512
+#define CSQCMODEL_PROPERTY_PITCHROLL 256
+
+#define ALLPROPERTIES_COMMON \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME, float, ReadByte, WriteByte, frame) \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_MODELINDEX, float, ReadShort, WriteShort, modelindex) \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_x) \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_y) \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_ORIGIN, float, ReadCoord, WriteCoord, origin_z) \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_x) \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_YAW, float, ReadAngle, WriteAngle, angles_y) \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_PITCHROLL, float, ReadAngle, WriteAngle, angles_z) \
+ CSQCMODEL_EXTRAPROPERTIES
+
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+.float frame3;
+.float frame3time;
+.float lerpfrac3;
+.float frame4;
+.float frame4time;
+.float lerpfrac4;
+#define ALLPROPERTIES ALLPROPERTIES_COMMON \
+ CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME2, float, ReadByte, WriteByte, frame2) \
+ CSQCMODEL_PROPERTY_SCALED(CSQCMODEL_PROPERTY_LERPFRAC, float, ReadByte, WriteByte, lerpfrac, 255, 0, 255)
+#else
+#define ALLPROPERTIES ALLPROPERTIES_COMMON
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+.vector iorigin1, iorigin2;
+.vector ivelocity1, ivelocity2;
+.vector iforward1, iforward2;
+.vector iup1, iup2;
+.float itime1, itime2;
+void InterpolateOrigin_Reset()
+{
+ self.iflags &~= IFLAG_INTERNALMASK;
+ self.itime1 = self.itime2 = 0;
+}
+void InterpolateOrigin_Note()
+{
+ float dt;
+ float f0;
+
+ dt = time - self.itime2;
+
+ f0 = self.iflags;
+ if(self.iflags & IFLAG_PREVALID)
+ self.iflags |= IFLAG_VALID;
+ else
+ self.iflags |= IFLAG_PREVALID;
+
+ self.iorigin1 = self.iorigin2;
+ self.iorigin2 = self.origin;
+
+ if(self.iflags & IFLAG_AUTOANGLES)
+ if(self.iorigin2 != self.iorigin1)
+ self.angles = vectoangles(self.iorigin2 - self.iorigin1);
+
+ if(self.iflags & IFLAG_ANGLES)
+ {
+ fixedmakevectors(self.angles);
+ if(f0 & IFLAG_VALID)
+ {
+ self.iforward1 = self.iforward2;
+ self.iup1 = self.iup2;
+ }
+ else
+ {
+ self.iforward1 = v_forward;
+ self.iup1 = v_up;
+ }
+ self.iforward2 = v_forward;
+ self.iup2 = v_up;
+ }
+
+ if(self.iflags & IFLAG_VELOCITY)
+ {
+ self.ivelocity1 = self.ivelocity2;
+ self.ivelocity2 = self.velocity;
+ }
+
+ if(self.iflags & IFLAG_TELEPORTED)
+ {
+ self.iflags &~= IFLAG_TELEPORTED;
+ self.itime1 = self.itime2 = time; // don't lerp
+ }
+ else if(vlen(self.iorigin2 - self.iorigin1) > 1000)
+ {
+ self.itime1 = self.itime2 = time; // don't lerp
+ }
+ else if((self.iflags & IFLAG_VELOCITY) && (vlen(self.ivelocity2 - self.ivelocity1) > 1000))
+ {
+ self.itime1 = self.itime2 = time; // don't lerp
+ }
+ else if(dt >= 0.2)
+ {
+ self.itime1 = self.itime2 = time;
+ }
+ else
+ {
+ self.itime1 = serverprevtime;
+ self.itime2 = time;
+ }
+}
+void InterpolateOrigin_Do()
+{
+ vector forward, up;
+ if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
+ {
+ float f;
+ f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1 + autocvar_cl_lerpexcess);
+ self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2;
+ if(self.iflags & IFLAG_ANGLES)
+ {
+ forward = (1 - f) * self.iforward1 + f * self.iforward2;
+ up = (1 - f) * self.iup1 + f * self.iup2;
+ self.angles = fixedvectoangles2(forward, up);
+ }
+ if(self.iflags & IFLAG_VELOCITY)
+ self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
+ }
+}
+void InterpolateOrigin_Undo()
+{
+ self.origin = self.iorigin2;
+ if(self.iflags & IFLAG_ANGLES)
+ self.angles = fixedvectoangles2(self.iforward2, self.iup2);
+ if(self.iflags & IFLAG_VELOCITY)
+ self.velocity = self.ivelocity2;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+.float iflags;
+#define IFLAG_VELOCITY 1
+#define IFLAG_ANGLES 2
+#define IFLAG_AUTOANGLES 4
+#define IFLAG_VALID 8
+#define IFLAG_PREVALID 16
+#define IFLAG_TELEPORTED 32
+#define IFLAG_INTERNALMASK (IFLAG_VALID | IFLAG_PREVALID)
+
+// call this BEFORE reading an entity update
+void InterpolateOrigin_Undo();
+
+// call this AFTER receiving an entity update
+void InterpolateOrigin_Note();
+
+// call this when the entity got teleported, before InterpolateOrigin_Note
+void InterpolateOrigin_Reset();
+
+// call this BEFORE drawing
+void InterpolateOrigin_Do();
--- /dev/null
+// define this if svqc code wants to use .frame2 and .lerpfrac
+//#define CSQCMODEL_HAVE_TWO_FRAMES
+
+// don't define this ever
+//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
+
+// add properties you want networked to CSQC here
+#define CSQCMODEL_EXTRAPROPERTIES \
+ /* CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) */ \
+ /* CSQCMODEL_PROPERTY(2, float, ReadInt24_t, WriteInt24_t, effects) */
+
+// add hook function calls here
+#define CSQCMODEL_HOOK_PREUPDATE
+#define CSQCMODEL_HOOK_POSTUPDATE
+#define CSQCMODEL_HOOK_PREDRAW
+#define CSQCPLAYER_HOOK_POSTCAMERASETUP
+
+// force updates of player entities that often even if unchanged
+#define CSQCPLAYER_FORCE_UPDATES 0.25
+
+// mod must define:
+//vector PL_MIN = ...;
+//vector PL_MAX = ...;
+//vector PL_VIEW_OFS = ...;
+//vector PL_CROUCH_MIN = ...;
+//vector PL_CROUCH_MAX = ...;
+//vector PL_CROUCH_VIEW_OFS = ...;
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+// generic CSQC model code
+
+float CSQCModel_Send(entity to, float sf)
+{
+ // some nice flags for CSQCMODEL_IF
+ float isplayer = (self.flags & FL_CLIENT);
+ float islocalplayer = (self == to);
+ float isnolocalplayer = (isplayer && (self != to));
+
+ WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL);
+ WriteShort(MSG_ENTITY, sf);
+
+#define CSQCMODEL_IF(cond) if(cond) {
+#define CSQCMODEL_ENDIF }
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+ if(sf & flag) \
+ { \
+ w(MSG_ENTITY, self.csqcmodel_##f); \
+ }
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+ ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+
+ return TRUE;
+}
+
+#ifdef CSQCPLAYER_FORCE_UPDATES
+.float csqcmodel_nextforcedupdate;
+#endif
+void CSQCModel_CheckUpdate()
+{
+ // some nice flags for CSQCMODEL_IF
+ float isplayer = (self.flags & FL_CLIENT);
+ float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
+ float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
+
+#ifdef CSQCPLAYER_FORCE_UPDATES
+ if(isplayer && time > self.csqcmodel_nextforcedupdate)
+ {
+ self.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN;
+ self.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec
+ }
+#endif
+
+ if(self.effects & EF_RESTARTANIM_BIT)
+ {
+ self.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
+ self.effects &~= EF_RESTARTANIM_BIT;
+ }
+
+ if(self.effects & EF_TELEPORT_BIT)
+ {
+ self.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
+ self.effects &~= EF_TELEPORT_BIT;
+ }
+
+#define CSQCMODEL_IF(cond) if(cond) {
+#define CSQCMODEL_ENDIF }
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+ { \
+ t tmp = self.f; \
+ if(tmp != self.csqcmodel_##f) \
+ { \
+ self.csqcmodel_##f = tmp; \
+ self.SendFlags |= flag; \
+ } \
+ }
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
+ { \
+ t tmp = bound(mi, s * self.f, ma); \
+ if(tmp != self.csqcmodel_##f) \
+ { \
+ self.csqcmodel_##f = tmp; \
+ self.SendFlags |= flag; \
+ } \
+ }
+ ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+}
+
+void CSQCModel_LinkEntity()
+{
+ self.SendEntity = CSQCModel_Send;
+ self.SendFlags = 0xFFFFFF;
+}
+
+void CSQCModel_UnlinkEntity()
+{
+ self.SendEntity = func_null;
+}
--- /dev/null
+/*
+ * Copyright (c) 2011 Rudolf Polzer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+// generic CSQC model code
+
+void CSQCModel_CheckUpdate();
+void CSQCModel_LinkEntity();
+void CSQCModel_UnlinkEntity();
+
+#define CSQCMODEL_IF(cond)
+#define CSQCMODEL_ENDIF
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
+ .t f; \
+ .t csqcmodel_##f;
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) CSQCMODEL_PROPERTY(flag,t,r,w,f)
+ ALLPROPERTIES
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
const float RF_VIEWMODEL = 1;
const float RF_EXTERNALMODEL = 2;
const float RF_DEPTHHACK = 4;
-const float RF_ADDATIVE = 8;
+const float RF_ADDITIVE = 8;
const float RF_USEAXIS = 16;
const float VF_MIN = 1; //(vector)
vector particles_colormin, particles_colormax;
void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502;
float trace_networkentity;
+const float RF_FULLBRIGHT = 256;
+const float RF_NOSHADOW = 512;
}
if(q == 3)
q = 5;
- if(q >= 3)
+ else if(q >= 3)
q -= 2;
// possible status:
// 0: crypto off
}
}
- if(self.modelindex == 0 && self.deadflag == DEAD_NO)
- {
- if(self.model != "")
- bprint("\{1}^1Player ", self.netname, "^1 has a zero modelindex, trying to fix...\n");
- self.model = ""; // force the != checks to return true
- }
-
if(defaultmodel != "")
{
if (defaultmodel != self.model)
return;
}
- if (!self.owner.modelindex)
+ if (self.owner.effects & CSQCMODEL_EF_INVISIBLE)
{
self.owner.killindicator = world;
remove(self);
if(!self.killindicator)
{
- if(self.modelindex && self.deadflag == DEAD_NO)
+ if(self.deadflag == DEAD_NO)
{
killtime = max(killtime, self.clientkill_nexttime - time);
self.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
void ChatBubbleThink()
{
self.nextthink = time;
- if (!self.owner.modelindex || self.owner.chatbubbleentity != self)
+ if ((self.owner.effects & CSQCMODEL_EF_INVISIBLE) || self.owner.chatbubbleentity != self)
{
if(self.owner) // but why can that ever be world?
self.owner.chatbubbleentity = world;
void UpdateChatBubble()
{
- if (!self.modelindex)
+ if (self.effects & CSQCMODEL_EF_INVISIBLE)
return;
// spawn a chatbubble entity if needed
if (!self.chatbubbleentity)
.float oldcolormap;
void respawn(void)
{
- if(self.modelindex != 0 && autocvar_g_respawn_ghosts)
+ if(!(self.effects & CSQCMODEL_EF_INVISIBLE) && autocvar_g_respawn_ghosts)
{
self.solid = SOLID_NOT;
self.takedamage = DAMAGE_NO;
self.modelflags &~= MF_ROCKET;
}
- self.effects &~= (EF_DIMLIGHT | EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
+ self.effects &~= (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
- if(!self.modelindex || self.deadflag) // don't apply the flags if the player is gibbed
+ if((self.effects & CSQCMODEL_EF_INVISIBLE) || self.deadflag) // don't apply the flags if the player is gibbed
return;
Fire_ApplyDamage(self);
self.dmg_take = self.dmg_take + take;//max(take - 10, 0);
self.dmg_inflictor = inflictor;
- if (self.health <= -autocvar_sv_gibhealth && self.modelindex != 0)
+ if (self.health <= -autocvar_sv_gibhealth && !(self.effects & CSQCMODEL_EF_INVISIBLE))
{
// don't use any animations as a gib
self.frame = 0;
self.view_ofs = '0 0 4';
Violence_GibSplash(self, 1, 1, attacker);
- self.modelindex = 0; // restore later
+ self.effects |= CSQCMODEL_EF_INVISIBLE;
self.solid = SOLID_NOT; // restore later
}
}
float w;
w = DEATH_WEAPONOF(deathtype);
if(WEP_VALID(w))
- if(self.classname == "player")
- if(self != attacker)
+ if(accuracy_isgooddamage(attacker, self))
attacker.accuracy.(accuracy_frags[w-1]) += 1;
if(deathtype == DEATH_HURTTRIGGER && g_freezetag)
accuracy.qh
csqcprojectile.qh
-../csqcmodel/settings.qh
-../csqcmodel/common.qh
-../csqcmodel/sv_model.qh
+../common/csqcmodel_settings.qh
+../csqcmodellib/common.qh
+../csqcmodellib/sv_model.qh
csqceffects.qc
anticheat.qh
accuracy.qc
-../csqcmodel/sv_model.qc
+../csqcmodellib/sv_model.qc
csqcprojectile.qc
playerdemo.qc
if(score)
if(scores_label[scorefield] != "")
s.SendFlags |= pow(2, scorefield);
- PlayerStats_Event(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label[scorefield]), score);
- s.(scores_accumulated[scorefield]) += score;
+ if(!inWarmupStage)
+ PlayerStats_Event(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label[scorefield]), score);
return (s.(scores[scorefield]) += score);
}
.float scores[MAX_SCORE];
.float teamscores[MAX_TEAMSCORE];
-.float scores_accumulated[MAX_SCORE]; // for player stats only
-
/**
* Attaches a PlayerScore entity to a player. Use that in ClientConnect.
* Remember to detach it in ClientDisconnect!
if(self.classname != "minstagib")
return FALSE;
- if(self.items == IT_STRENGTH || self.items == IT_INVINCIBLE)
+ if(self.flags & FL_POWERUP)
{
if(autocvar_g_powerups > 0)
return TRUE;
case IT_FUEL_REGEN: name = "item-fuelregen"; rgb = '1 0.5 0'; break;
case IT_JETPACK: name = "item-jetpack"; rgb = '0.5 0.5 0.5'; break;
}
+ if(!name)
+ {
+ print("Unknown powerup-marked item is wanting to respawn\n");
+ localcmd(sprintf("prvm_edict server %d\n", num_for_edict(self)));
+ }
if(name)
{
WaypointSprite_Spawn(name, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb);
self.items = itemid;
self.weapons = weaponid;
+ self.flags = FL_ITEM | itemflags;
// is it a dropped weapon?
if (self.classname == "droppedweapon")
self.respawntimejitter = defaultrespawntimejitter;
}
self.netname = itemname;
- self.flags = FL_ITEM | itemflags;
self.touch = Item_Touch;
setmodel (self, self.mdl); // precision set below
self.effects |= EF_LOWPRECISION;