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