5 #include <lib/warpzone/util_server.qh>
6 #include <common/mapobjects/triggers.qh>
7 #include <common/weapons/_all.qh>
8 #include <common/stats.qh>
11 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC)
12 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC_TRIGGER)
16 void viewloc_think(entity this)
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
20 // set myself as current viewloc where possible
22 FOREACH_CLIENT(IS_PLAYER(it) && it.viewloc == this,
28 for(e = NULL; (e = findentity(e, viewloc, this)); )
33 FOREACH_CLIENT(!it.viewloc && IS_PLAYER(it),
35 if (WarpZoneLib_ExactTrigger_Touch(this, it, false))
39 for(e = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); e; e = e.chain)
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))
47 this.nextthink = time;
50 bool trigger_viewloc_send(entity this, entity to, int sf)
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);
55 WriteByte(MSG_ENTITY, this.spawnflags);
57 WriteEntity(MSG_ENTITY, this.enemy);
58 WriteEntity(MSG_ENTITY, this.goalentity);
60 WriteVector(MSG_ENTITY, this.origin);
65 void viewloc_init(entity this)
68 for(e = NULL; (e = find(e, targetname, this.target)); )
69 if(e.classname == "target_viewlocation_start")
74 for(e = NULL; (e = find(e, targetname, this.target2)); )
75 if(e.classname == "target_viewlocation_end")
81 if(!this.enemy) { LOG_INFO("^1FAIL!"); delete(this); return; }
84 this.goalentity = this.enemy; // make them match so CSQC knows what to do
86 Net_LinkEntity(this, false, 0, trigger_viewloc_send);
88 setthink(this, viewloc_think);
89 this.nextthink = time;
92 spawnfunc(trigger_viewlocation)
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; }
97 WarpZoneLib_ExactTrigger_Init(this, false);
98 InitializeEntity(this, viewloc_init, INITPRIO_FINDTARGET);
101 bool viewloc_send(entity this, entity to, int sf)
103 WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
105 WriteByte(MSG_ENTITY, this.cnt);
107 WriteVector(MSG_ENTITY, this.origin);
109 WriteAngleVector(MSG_ENTITY, this.angles);
115 void viewloc_link(entity this)
118 this.angles_y = this.angle;
119 Net_LinkEntity(this, false, 0, viewloc_send);
122 spawnfunc(target_viewlocation_start)
127 spawnfunc(target_viewlocation_end)
134 spawnfunc(target_viewlocation)
136 spawnfunc_target_viewlocation_start(this);
141 void trigger_viewloc_updatelink(entity this)
143 this.enemy = findfloat(NULL, entnum, this.cnt);
144 this.goalentity = findfloat(NULL, entnum, this.count);
147 NET_HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER, bool isnew)
149 this.spawnflags = ReadByte();
151 float point1 = ReadShort();
152 float point2 = ReadShort();
154 this.enemy = findfloat(NULL, entnum, point1);
155 this.goalentity = findfloat(NULL, entnum, point2);
157 this.origin = ReadVector();
161 setorigin(this, this.origin);
166 setthink(this, trigger_viewloc_updatelink);
167 this.nextthink = time + 1; // we need to delay this or else
169 this.drawmask = MASK_NORMAL; // not so concerned, but better keep it alive
172 NET_HANDLE(ENT_CLIENT_VIEWLOC, bool isnew)
174 this.cnt = ReadByte();
176 this.origin = ReadVector();
177 setorigin(this, this.origin);
179 this.movedir = ReadAngleVector();
183 this.classname = ((this.cnt == 2) ? "target_viewlocation_end" : "target_viewlocation_start");
184 this.drawmask = MASK_NORMAL; // don't cull it