]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mapobjects/trigger/viewloc.qc
Tidy up classnames
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mapobjects / trigger / viewloc.qc
1 #include "viewloc.qh"
2 #if defined(CSQC)
3 #elif defined(MENUQC)
4 #elif defined(SVQC)
5     #include <lib/warpzone/util_server.qh>
6         #include <common/mapobjects/triggers.qh>
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
118         EXACTTRIGGER_INIT;
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