Xonotic
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)
7  #include <common/weapons/_all.qh>
8  #include <common/stats.qh>
9 #endif
10 
11 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC)
12 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC_TRIGGER)
13 
14 #ifdef SVQC
15 
16 void viewloc_think(entity this)
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  vector emin = it.absmin;
36  vector emax = it.absmax;
37  if(this.solid == SOLID_BSP)
38  {
39  emin -= '1 1 1';
40  emax += '1 1 1';
41  }
42  if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
43  {
44  if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, it)) // accurate
45  it.viewloc = this;
46  }
47  });
48 #else
49 
50  for(e = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); e; e = e.chain)
51  if(!e.viewloc)
52  if(IS_PLAYER(e)) // should we support non-player entities with this?
53  //if(!IS_DEAD(e)) // death view is handled separately, we can't override this just yet
54  {
55  vector emin = e.absmin;
56  vector emax = e.absmax;
57  if(this.solid == SOLID_BSP)
58  {
59  emin -= '1 1 1';
60  emax += '1 1 1';
61  }
62  if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
63  if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, e)) // accurate
64  e.viewloc = this;
65  }
66 #endif
67 
68  this.nextthink = time;
69 }
70 
71 bool trigger_viewloc_send(entity this, entity to, int sf)
72 {
73  // CSQC doesn't need to know our origin (yet), as we're only available for referencing
74  WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC_TRIGGER);
75 
76  WriteByte(MSG_ENTITY, this.spawnflags);
77 
78  WriteEntity(MSG_ENTITY, this.enemy);
79  WriteEntity(MSG_ENTITY, this.goalentity);
80 
81  WriteVector(MSG_ENTITY, this.origin);
82 
83  return true;
84 }
85 
86 void viewloc_init(entity this)
87 {
88  entity e;
89  for(e = NULL; (e = find(e, targetname, this.target)); )
90  if(e.classname == "target_viewlocation_start")
91  {
92  this.enemy = e;
93  break;
94  }
95  for(e = NULL; (e = find(e, targetname, this.target2)); )
96  if(e.classname == "target_viewlocation_end")
97  {
98  this.goalentity = e;
99  break;
100  }
101 
102  if(!this.enemy) { LOG_INFO("^1FAIL!"); delete(this); return; }
103 
104  if(!this.goalentity)
105  this.goalentity = this.enemy; // make them match so CSQC knows what to do
106 
107  Net_LinkEntity(this, false, 0, trigger_viewloc_send);
108 
109  setthink(this, viewloc_think);
110  this.nextthink = time;
111 }
112 
113 spawnfunc(trigger_viewlocation)
114 {
115  // we won't check target2 here yet, as it may not even need to exist
116  if(this.target == "") { LOG_INFO("^1FAIL!"); delete(this); return; }
117 
119  InitializeEntity(this, viewloc_init, INITPRIO_FINDTARGET);
120 }
121 
122 bool viewloc_send(entity this, entity to, int sf)
123 {
124  WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
125 
126  WriteByte(MSG_ENTITY, this.cnt);
127 
128  WriteVector(MSG_ENTITY, this.origin);
129 
130  WriteAngleVector(MSG_ENTITY, this.angles);
131 
132  return true;
133 }
134 
135 .float angle;
136 void viewloc_link(entity this)
137 {
138  if(this.angle)
139  this.angles_y = this.angle;
140  Net_LinkEntity(this, false, 0, viewloc_send);
141 }
142 
143 spawnfunc(target_viewlocation_start)
144 {
145  this.cnt = 1;
146  viewloc_link(this);
147 }
148 spawnfunc(target_viewlocation_end)
149 {
150  this.cnt = 2;
151  viewloc_link(this);
152 }
153 
154 // compatibility
155 spawnfunc(target_viewlocation)
156 {
157  spawnfunc_target_viewlocation_start(this);
158 }
159 
160 #elif defined(CSQC)
161 
162 void trigger_viewloc_updatelink(entity this)
163 {
164  this.enemy = findfloat(NULL, entnum, this.cnt);
165  this.goalentity = findfloat(NULL, entnum, this.count);
166 }
167 
168 NET_HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER, bool isnew)
169 {
170  this.spawnflags = ReadByte();
171 
172  float point1 = ReadShort();
173  float point2 = ReadShort();
174 
175  this.enemy = findfloat(NULL, entnum, point1);
176  this.goalentity = findfloat(NULL, entnum, point2);
177 
178  this.origin = ReadVector();
179 
180  return = true;
181 
182  setorigin(this, this.origin);
183 
184  this.cnt = point1;
185  this.count = point2;
186 
187  setthink(this, trigger_viewloc_updatelink);
188  this.nextthink = time + 1; // we need to delay this or else
189 
190  this.drawmask = MASK_NORMAL; // not so concerned, but better keep it alive
191 }
192 
193 NET_HANDLE(ENT_CLIENT_VIEWLOC, bool isnew)
194 {
195  this.cnt = ReadByte();
196 
197  this.origin = ReadVector();
198  setorigin(this, this.origin);
199 
200  this.movedir = ReadAngleVector();
201 
202  return = true;
203 
204  this.classname = ((this.cnt == 2) ? "target_viewlocation_end" : "target_viewlocation_start");
205  this.drawmask = MASK_NORMAL; // don't cull it
206 }
207 
208 #endif
#define REGISTER_NET_LINKED(id)
Definition: net.qh:67
#define EXACTTRIGGER_INIT
Definition: common.qh:117
entity() spawn
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
#define NET_HANDLE(id, param)
Definition: net.qh:12
entity to
Definition: self.qh:96
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
origin
Definition: ent_cs.qc:114
string classname
Definition: csprogsdefs.qc:107
float spawnflags
Definition: progsdefs.qc:191
vector absmax
Definition: csprogsdefs.qc:92
vector movedir
Definition: progsdefs.qc:203
entity enemy
Definition: sv_ctf.qh:143
float cnt
Definition: powerups.qc:24
ERASEABLE float boxesoverlap(vector m1, vector m2, vector m3, vector m4)
requires that m2>m1 in all coordinates, and that m4>m3
Definition: vector.qh:73
float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig)
Definition: common.qc:138
entity goalentity
Definition: progsdefs.qc:189
#define NULL
Definition: post.qh:17
#define LOG_INFO(...)
Definition: log.qh:70
const float MASK_NORMAL
Definition: csprogsdefs.qc:164
float drawmask
Definition: csprogsdefs.qc:95
float nextthink
Definition: csprogsdefs.qc:121
string target2
Definition: sv_onslaught.qh:45
vector(float skel, float bonenum) _skel_get_boneabs_hidden
entity viewloc
Definition: viewloc.qh:13
const float SOLID_BSP
Definition: csprogsdefs.qc:248
void InitializeEntity(entity e, void(entity this) func, int order)
Definition: world.qc:2146
float count
Definition: powerups.qc:22
string targetname
Definition: progsdefs.qc:194
setorigin(ent, v)
#define setthink(e, f)
vector angles
Definition: csprogsdefs.qc:104
string target
Definition: progsdefs.qc:193
vector absmin
Definition: csprogsdefs.qc:92
float time
Definition: csprogsdefs.qc:16
float entnum
Definition: csprogsdefs.qc:94
#define IS_PLAYER(v)
Definition: utils.qh:9
float solid
Definition: csprogsdefs.qc:99