Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
viewloc.qc
Go to the documentation of this file.
1#include "viewloc.qh"
2#if defined(CSQC)
3#elif defined(MENUQC)
4#elif defined(SVQC)
8 #include <common/stats.qh>
9#endif
10
11REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC)
12REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC_TRIGGER)
13
14#ifdef SVQC
15
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 if (WarpZoneLib_ExactTrigger_Touch(this, it, false))
36 it.viewloc = this;
37 });
38#else
39 for(e = findradius((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1); e; e = e.chain)
40 if(!e.viewloc)
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))
44 e.viewloc = this;
45#endif
46
47 this.nextthink = time;
48}
49
50bool trigger_viewloc_send(entity this, entity to, int sf)
51{
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);
54
56
59
60 WriteVector(MSG_ENTITY, this.origin);
61
62 return true;
63}
64
66{
67 entity e;
68 for(e = NULL; (e = find(e, targetname, this.target)); )
69 if(e.classname == "target_viewlocation_start")
70 {
71 this.enemy = e;
72 break;
73 }
74 for(e = NULL; (e = find(e, targetname, this.target2)); )
75 if(e.classname == "target_viewlocation_end")
76 {
77 this.goalentity = e;
78 break;
79 }
80
81 if(!this.enemy) { LOG_INFO("^1FAIL!"); delete(this); return; }
82
83 if(!this.goalentity)
84 this.goalentity = this.enemy; // make them match so CSQC knows what to do
85
86 Net_LinkEntity(this, false, 0, trigger_viewloc_send);
87
89 this.nextthink = time;
90}
91
92spawnfunc(trigger_viewlocation)
93{
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; }
96
99}
100
101bool viewloc_send(entity this, entity to, int sf)
102{
103 WriteHeader(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
104
105 WriteByte(MSG_ENTITY, this.cnt);
106
107 WriteVector(MSG_ENTITY, this.origin);
108
109 WriteAngleVector(MSG_ENTITY, this.angles);
110
111 return true;
112}
113
114.float angle;
116{
117 if(this.angle)
118 this.angles_y = this.angle;
119 Net_LinkEntity(this, false, 0, viewloc_send);
120}
121
122spawnfunc(target_viewlocation_start)
123{
124 this.cnt = 1;
125 viewloc_link(this);
126}
127spawnfunc(target_viewlocation_end)
128{
129 this.cnt = 2;
130 viewloc_link(this);
131}
132
133// compatibility
134spawnfunc(target_viewlocation)
135{
136 spawnfunc_target_viewlocation_start(this);
137}
138
139#elif defined(CSQC)
140
141void trigger_viewloc_updatelink(entity this)
142{
143 this.enemy = findfloat(NULL, entnum, this.cnt);
144 this.goalentity = findfloat(NULL, entnum, this.count);
145}
146
147NET_HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER, bool isnew)
148{
149 this.spawnflags = ReadByte();
150
151 float point1 = ReadShort();
152 float point2 = ReadShort();
153
154 this.enemy = findfloat(NULL, entnum, point1);
155 this.goalentity = findfloat(NULL, entnum, point2);
156
157 this.origin = ReadVector();
158
159 return = true;
160
161 setorigin(this, this.origin);
162
163 this.cnt = point1;
164 this.count = point2;
165
166 setthink(this, trigger_viewloc_updatelink);
167 this.nextthink = time + 1; // we need to delay this or else
168
169 this.drawmask = MASK_NORMAL; // not so concerned, but better keep it alive
170}
171
172NET_HANDLE(ENT_CLIENT_VIEWLOC, bool isnew)
173{
174 this.cnt = ReadByte();
175
176 this.origin = ReadVector();
177 setorigin(this, this.origin);
178
179 this.movedir = ReadAngleVector();
180
181 return = true;
182
183 this.classname = ((this.cnt == 2) ? "target_viewlocation_end" : "target_viewlocation_start");
184 this.drawmask = MASK_NORMAL; // don't cull it
185}
186
187#endif
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float cnt
Definition powerups.qc:24
float count
Definition powerups.qc:22
int spawnflags
Definition ammo.qh:15
#define IS_PLAYER(s)
Definition player.qh:242
const int INITPRIO_FINDTARGET
Definition constants.qh:96
string classname
float drawmask
const float MASK_NORMAL
float time
float nextthink
vector absmax
float entnum
vector origin
vector absmin
ent angles
Definition ent_cs.qc:146
angles_y
Definition ent_cs.qc:144
WriteByte(chan, ent.angles.y/DEC_FACTOR)
#define NET_HANDLE(id, param)
Definition net.qh:15
const int MSG_ENTITY
Definition net.qh:156
#define ReadVector()
Definition net.qh:349
#define ReadAngleVector()
Definition net.qh:351
#define WriteHeader(to, id)
Definition net.qh:265
#define REGISTER_NET_LINKED(id)
Definition net.qh:91
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167
int ReadByte()
bool WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher, bool touchfunc)
Definition common.qc:789
#define LOG_INFO(...)
Definition log.qh:62
void viewloc_link(entity this)
Definition viewloc.qc:115
float angle
Definition viewloc.qc:114
void viewloc_think(entity this)
Definition viewloc.qc:16
void viewloc_init(entity this)
Definition viewloc.qc:65
bool trigger_viewloc_send(entity this, entity to, int sf)
Definition viewloc.qc:50
bool viewloc_send(entity this, entity to, int sf)
Definition viewloc.qc:101
entity goalentity
Definition viewloc.qh:16
vector movedir
Definition viewloc.qh:18
entity viewloc
Definition viewloc.qh:13
entity findentity(entity start,.entity field, entity match)
entity find(entity start,.string field, string match)
float vlen(vector v)
void WriteEntity(entity data, float dest, float desto)
entity findfloat(entity start,.float field, float match)
#define NULL
Definition post.qh:14
#define setthink(e, f)
#define spawnfunc(id)
Definition spawnfunc.qh:107
entity enemy
Definition sv_ctf.qh:152
string target2
string targetname
Definition triggers.qh:56
string target
Definition triggers.qh:55
void WarpZoneLib_ExactTrigger_Init(entity this, bool unsetmodel)
Definition util_server.qc:8
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52
void InitializeEntity(entity e, void(entity this) func, int order)
Definition world.qc:2229