Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
viewloc.qc
Go to the documentation of this file.
1#include "viewloc.qh"
2#if defined(CSQC)
3#elif defined(MENUQC)
4#elif defined(SVQC)
8 #include <common/stats.qh>
9#endif
10
11REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC)
12REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC_TRIGGER)
13
14#ifdef SVQC
15
17{
18 // we abuse this method, rather than using normal .touch, because touch isn't reliable with multiple clients inside the same trigger, and can't "untouch" entities
19
20 // set myself as current viewloc where possible
21#if 1
22 FOREACH_CLIENT(IS_PLAYER(it) && it.viewloc == this,
23 {
24 it.viewloc = NULL;
25 });
26#else
27 entity e;
28 for(e = NULL; (e = findentity(e, viewloc, this)); )
29 e.viewloc = NULL;
30#endif
31
32#if 1
33 FOREACH_CLIENT(!it.viewloc && IS_PLAYER(it),
34 {
35 if (WarpZoneLib_ExactTrigger_Touch(this, it, false))
36 it.viewloc = this;
37 });
38#else
39 for(e = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); e; e = e.chain)
40 if(!e.viewloc)
41 if(IS_PLAYER(e)) // should we support non-player entities with this?
42 //if(!IS_DEAD(e)) // death view is handled separately, we can't override this just yet
43 if (WarpZoneLib_ExactTrigger_Touch(this, it, false))
44 e.viewloc = this;
45#endif
46
47 this.nextthink = time;
48}
49
50bool trigger_viewloc_send(entity this, entity to, int sf)
51{
52 // CSQC doesn't need to know our origin (yet), as we're only available for referencing
53 WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC_TRIGGER);
54
56
59
60 WriteVector(MSG_ENTITY, this.origin);
61
62 return true;
63}
64
66{
67 entity e;
68 for(e = NULL; (e = find(e, targetname, this.target)); )
69 if(e.classname == "target_viewlocation_start")
70 {
71 this.enemy = e;
72 break;
73 }
74 for(e = NULL; (e = find(e, targetname, this.target2)); )
75 if(e.classname == "target_viewlocation_end")
76 {
77 this.goalentity = e;
78 break;
79 }
80
81 if(!this.enemy) { LOG_INFO("^1FAIL!"); delete(this); return; }
82
83 if(!this.goalentity)
84 this.goalentity = this.enemy; // make them match so CSQC knows what to do
85
86 Net_LinkEntity(this, false, 0, trigger_viewloc_send);
87
89 this.nextthink = time;
90}
91
92spawnfunc(trigger_viewlocation)
93{
94 // we won't check target2 here yet, as it may not even need to exist
95 if(this.target == "") { LOG_INFO("^1FAIL!"); delete(this); return; }
96
99}
100
101bool viewloc_send(entity this, entity to, int sf)
102{
103 WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
104
105 WriteByte(MSG_ENTITY, this.cnt);
106
107 WriteVector(MSG_ENTITY, this.origin);
108
109 WriteAngleVector(MSG_ENTITY, this.angles);
110
111 return true;
112}
113
114.float angle;
116{
117 if(this.angle)
118 this.angles_y = this.angle;
119 Net_LinkEntity(this, false, 0, viewloc_send);
120}
121
122spawnfunc(target_viewlocation_start)
123{
124 this.cnt = 1;
125 viewloc_link(this);
126}
127spawnfunc(target_viewlocation_end)
128{
129 this.cnt = 2;
130 viewloc_link(this);
131}
132
133// compatibility
134spawnfunc(target_viewlocation)
135{
136 spawnfunc_target_viewlocation_start(this);
137}
138
139#elif defined(CSQC)
140
141void trigger_viewloc_updatelink(entity this)
142{
143 this.enemy = findfloat(NULL, entnum, this.cnt);
144 this.goalentity = findfloat(NULL, entnum, this.count);
145}
146
147NET_HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER, bool isnew)
148{
149 this.spawnflags = ReadByte();
150
151 float point1 = ReadShort();
152 float point2 = ReadShort();
153
154 this.enemy = findfloat(NULL, entnum, point1);
155 this.goalentity = findfloat(NULL, entnum, point2);
156
157 this.origin = ReadVector();
158
159 return = true;
160
161 setorigin(this, this.origin);
162
163 this.cnt = point1;
164 this.count = point2;
165
166 setthink(this, trigger_viewloc_updatelink);
167 this.nextthink = time + 1; // we need to delay this or else
168
169 this.drawmask = MASK_NORMAL; // not so concerned, but better keep it alive
170}
171
172NET_HANDLE(ENT_CLIENT_VIEWLOC, bool isnew)
173{
174 this.cnt = ReadByte();
175
176 this.origin = ReadVector();
177 setorigin(this, this.origin);
178
179 this.movedir = ReadAngleVector();
180
181 return = true;
182
183 this.classname = ((this.cnt == 2) ? "target_viewlocation_end" : "target_viewlocation_start");
184 this.drawmask = MASK_NORMAL; // don't cull it
185}
186
187#endif
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float cnt
Definition powerups.qc:24
float count
Definition powerups.qc:22
int spawnflags
Definition ammo.qh:15
#define IS_PLAYER(s)
Definition player.qh:243
const int INITPRIO_FINDTARGET
Definition constants.qh:96
string classname
float drawmask
const float MASK_NORMAL
float time
float nextthink
vector absmax
float entnum
vector origin
vector absmin
ent angles
Definition ent_cs.qc:121
angles_y
Definition ent_cs.qc:119
#define NET_HANDLE(id, param)
Definition net.qh:15
const int MSG_ENTITY
Definition net.qh:115
#define ReadVector()
Definition net.qh:367
#define ReadAngleVector()
Definition net.qh:369
#define WriteHeader(to, id)
Definition net.qh:221
#define REGISTER_NET_LINKED(id)
Definition net.qh:55
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:123
int ReadByte()
bool WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher, bool touchfunc)
Definition common.qc:815
#define LOG_INFO(...)
Definition log.qh:65
void viewloc_link(entity this)
Definition viewloc.qc:115
float angle
Definition viewloc.qc:114
void viewloc_think(entity this)
Definition viewloc.qc:16
void viewloc_init(entity this)
Definition viewloc.qc:65
bool trigger_viewloc_send(entity this, entity to, int sf)
Definition viewloc.qc:50
bool viewloc_send(entity this, entity to, int sf)
Definition viewloc.qc:101
entity goalentity
Definition viewloc.qh:16
vector movedir
Definition viewloc.qh:18
entity viewloc
Definition viewloc.qh:13
entity findentity(entity start,.entity field, entity match)
entity find(entity start,.string field, string match)
float vlen(vector v)
void WriteEntity(entity data, float dest, float desto)
void WriteByte(float data, float dest, float desto)
entity findfloat(entity start,.float field, float match)
#define NULL
Definition post.qh:14
#define setthink(e, f)
#define spawnfunc(id)
Definition spawnfunc.qh:96
entity enemy
Definition sv_ctf.qh:153
string target2
string targetname
Definition triggers.qh:56
string target
Definition triggers.qh:55
void WarpZoneLib_ExactTrigger_Init(entity this, bool unsetmodel)
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50
void InitializeEntity(entity e, void(entity this) func, int order)
Definition world.qc:2209