]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/trigger/viewloc.qc
Change the internal database value name to _ranked
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / 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 <server/defs.qh>
7 #endif
8
9 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC)
10 REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC_TRIGGER)
11
12 #ifdef SVQC
13
14 void viewloc_think(entity this)
15 {
16         entity e;
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         for(e = NULL; (e = findentity(e, viewloc, this)); )
22                 e.viewloc = NULL;
23
24                 for(e = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); e; e = e.chain)
25                         if(!e.viewloc)
26                                 if(IS_PLAYER(e)) // should we support non-player entities with this?
27                                 //if(!IS_DEAD(e)) // death view is handled separately, we can't override this just yet
28                                 {
29                                         vector emin = e.absmin;
30                                         vector emax = e.absmax;
31                                         if(this.solid == SOLID_BSP)
32                                         {
33                                                 emin -= '1 1 1';
34                                                 emax += '1 1 1';
35                                         }
36                                         if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
37                                                 if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, e)) // accurate
38                                                         e.viewloc = this;
39                                 }
40
41         this.nextthink = time;
42 }
43
44 bool trigger_viewloc_send(entity this, entity to, int sf)
45 {
46         // CSQC doesn't need to know our origin (yet), as we're only available for referencing
47         WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC_TRIGGER);
48
49         WriteEntity(MSG_ENTITY, this.enemy);
50         WriteEntity(MSG_ENTITY, this.goalentity);
51
52         WriteCoord(MSG_ENTITY, this.origin_x);
53         WriteCoord(MSG_ENTITY, this.origin_y);
54         WriteCoord(MSG_ENTITY, this.origin_z);
55
56         return true;
57 }
58
59 void viewloc_init(entity this)
60 {
61         entity e;
62         for(e = NULL; (e = find(e, targetname, this.target)); )
63                 if(e.classname == "target_viewlocation_start")
64                 {
65                         this.enemy = e;
66                         break;
67                 }
68         for(e = NULL; (e = find(e, targetname, this.target2)); )
69                 if(e.classname == "target_viewlocation_end")
70                 {
71                         this.goalentity = e;
72                         break;
73                 }
74
75         if(!this.enemy) { LOG_INFO("^1FAIL!"); delete(this); return; }
76
77         if(!this.goalentity)
78                 this.goalentity = this.enemy; // make them match so CSQC knows what to do
79
80         Net_LinkEntity(this, false, 0, trigger_viewloc_send);
81
82         setthink(this, viewloc_think);
83         this.nextthink = time;
84 }
85
86 spawnfunc(trigger_viewlocation)
87 {
88         // we won't check target2 here yet, as it may not even need to exist
89         if(this.target == "") { LOG_INFO("^1FAIL!"); delete(this); return; }
90
91         EXACTTRIGGER_INIT;
92         InitializeEntity(this, viewloc_init, INITPRIO_FINDTARGET);
93 }
94
95 bool viewloc_send(entity this, entity to, int sf)
96 {
97         WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
98
99         WriteByte(MSG_ENTITY, this.cnt);
100
101         WriteCoord(MSG_ENTITY, this.origin_x);
102         WriteCoord(MSG_ENTITY, this.origin_y);
103         WriteCoord(MSG_ENTITY, this.origin_z);
104
105         WriteAngle(MSG_ENTITY, this.angles_x);
106         WriteAngle(MSG_ENTITY, this.angles_y);
107         WriteAngle(MSG_ENTITY, this.angles_z);
108
109         return true;
110 }
111
112 .float angle;
113 void viewloc_link(entity this)
114 {
115         if(this.angle)
116                 this.angles_y = this.angle;
117         Net_LinkEntity(this, false, 0, viewloc_send);
118 }
119
120 spawnfunc(target_viewlocation_start)
121 {
122         this.classname = "target_viewlocation_start";
123         this.cnt = 1;
124         viewloc_link(this);
125 }
126 spawnfunc(target_viewlocation_end)
127 {
128         this.classname = "target_viewlocation_end";
129         this.cnt = 2;
130         viewloc_link(this);
131 }
132
133 // compatibility
134 spawnfunc(target_viewlocation) { spawnfunc_target_viewlocation_start(this); }
135
136 #elif defined(CSQC)
137
138 void trigger_viewloc_updatelink(entity this)
139 {
140         this.enemy = findfloat(NULL, entnum, this.cnt);
141         this.goalentity = findfloat(NULL, entnum, this.count);
142 }
143
144 NET_HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER, bool isnew)
145 {
146         float point1 = ReadShort();
147         float point2 = ReadShort();
148
149         this.enemy = findfloat(NULL, entnum, point1);
150         this.goalentity = findfloat(NULL, entnum, point2);
151
152         this.origin_x = ReadCoord();
153         this.origin_y = ReadCoord();
154         this.origin_z = ReadCoord();
155
156         return = true;
157
158         setorigin(this, this.origin);
159
160         this.cnt = point1;
161         this.count = point2;
162
163         setthink(this, trigger_viewloc_updatelink);
164         this.nextthink = time + 1; // we need to delay this or else
165
166         this.classname = "trigger_viewlocation";
167         this.drawmask = MASK_NORMAL; // not so concerned, but better keep it alive
168 }
169
170 NET_HANDLE(ENT_CLIENT_VIEWLOC, bool isnew)
171 {
172         this.cnt = ReadByte();
173
174         this.origin_x = ReadCoord();
175         this.origin_y = ReadCoord();
176         this.origin_z = ReadCoord();
177         setorigin(this, this.origin);
178
179         this.movedir_x = ReadAngle();
180         this.movedir_y = ReadAngle();
181         this.movedir_z = ReadAngle();
182
183         return = true;
184
185         this.classname = ((this.cnt == 2) ? "target_viewlocation_end" : "target_viewlocation_start");
186         this.drawmask = MASK_NORMAL; // don't cull it
187 }
188
189 #endif