4 #include <lib/warpzone/util_server.qh>
5 #include <server/defs.qh>
8 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC)
9 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC_TRIGGER)
13 void viewloc_think(entity this)
17 // 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 // set myself as current viewloc where possible
20 for(e = NULL; (e = findentity(e, viewloc, this)); )
23 for(e = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); e; e = e.chain)
25 if(IS_PLAYER(e)) // should we support non-player entities with this?
26 //if(!IS_DEAD(e)) // death view is handled separately, we can't override this just yet
28 vector emin = e.absmin;
29 vector emax = e.absmax;
30 if(this.solid == SOLID_BSP)
35 if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
36 if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, e)) // accurate
40 this.nextthink = time;
43 bool trigger_viewloc_send(entity this, entity to, int sf)
45 // CSQC doesn't need to know our origin (yet), as we're only available for referencing
46 WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC_TRIGGER);
48 WriteEntity(MSG_ENTITY, this.enemy);
49 WriteEntity(MSG_ENTITY, this.goalentity);
51 WriteCoord(MSG_ENTITY, this.origin_x);
52 WriteCoord(MSG_ENTITY, this.origin_y);
53 WriteCoord(MSG_ENTITY, this.origin_z);
58 void viewloc_init(entity this)
61 for(e = NULL; (e = find(e, targetname, this.target)); )
62 if(e.classname == "target_viewlocation_start")
67 for(e = NULL; (e = find(e, targetname, this.target2)); )
68 if(e.classname == "target_viewlocation_end")
74 if(!this.enemy) { LOG_INFO("^1FAIL!\n"); delete(this); return; }
77 this.goalentity = this.enemy; // make them match so CSQC knows what to do
79 Net_LinkEntity(this, false, 0, trigger_viewloc_send);
81 setthink(this, viewloc_think);
82 this.nextthink = time;
85 spawnfunc(trigger_viewlocation)
87 // we won't check target2 here yet, as it may not even need to exist
88 if(this.target == "") { LOG_INFO("^1FAIL!\n"); delete(this); return; }
91 InitializeEntity(this, viewloc_init, INITPRIO_FINDTARGET);
94 bool viewloc_send(entity this, entity to, int sf)
96 WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
98 WriteByte(MSG_ENTITY, this.cnt);
100 WriteCoord(MSG_ENTITY, this.origin_x);
101 WriteCoord(MSG_ENTITY, this.origin_y);
102 WriteCoord(MSG_ENTITY, this.origin_z);
104 WriteCoord(MSG_ENTITY, this.angles_x);
105 WriteCoord(MSG_ENTITY, this.angles_y);
106 WriteCoord(MSG_ENTITY, this.angles_z);
112 void viewloc_link(entity this)
115 this.angles_y = this.angle;
116 Net_LinkEntity(this, false, 0, viewloc_send);
119 spawnfunc(target_viewlocation_start)
121 this.classname = "target_viewlocation_start";
125 spawnfunc(target_viewlocation_end)
127 this.classname = "target_viewlocation_end";
133 spawnfunc(target_viewlocation) { spawnfunc_target_viewlocation_start(this); }
137 void trigger_viewloc_updatelink(entity this)
139 this.enemy = findfloat(NULL, entnum, this.cnt);
140 this.goalentity = findfloat(NULL, entnum, this.count);
143 NET_HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER, bool isnew)
145 float point1 = ReadShort();
146 float point2 = ReadShort();
148 this.enemy = findfloat(NULL, entnum, point1);
149 this.goalentity = findfloat(NULL, entnum, point2);
151 this.origin_x = ReadCoord();
152 this.origin_y = ReadCoord();
153 this.origin_z = ReadCoord();
157 setorigin(this, this.origin);
162 setthink(this, trigger_viewloc_updatelink);
163 this.nextthink = time + 1; // we need to delay this or else
165 this.classname = "trigger_viewlocation";
166 this.drawmask = MASK_NORMAL; // not so concerned, but better keep it alive
169 NET_HANDLE(ENT_CLIENT_VIEWLOC, bool isnew)
171 this.cnt = ReadByte();
173 this.origin_x = ReadCoord();
174 this.origin_y = ReadCoord();
175 this.origin_z = ReadCoord();
176 setorigin(this, this.origin);
178 this.movedir_x = ReadCoord();
179 this.movedir_y = ReadCoord();
180 this.movedir_z = ReadCoord();
184 this.classname = ((this.cnt == 2) ? "target_viewlocation_end" : "target_viewlocation_start");
185 this.drawmask = MASK_NORMAL; // don't cull it