]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mapobjects/func/ladder.qc
func_ladder: restore the model string unset in WarpZoneLib_ExactTrigger_Init()
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mapobjects / func / ladder.qc
1 #include "ladder.qh"
2 REGISTER_NET_LINKED(ENT_CLIENT_LADDER)
3
4 void func_ladder_think(entity this)
5 {
6 #ifdef CSQC
7         // TODO: check if this is what is causing the glitchiness when switching between them
8         float dt = time - this.move_time;
9         this.move_time = time;
10         if(dt <= 0) { return; }
11 #endif
12
13         // set myself as current ladders where possible
14         IL_EACH(g_ladderents, it.ladder_entity == this,
15         {
16                 it.ladder_entity = NULL;
17                 IL_REMOVE(g_ladderents, it);
18         });
19
20         FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, !it.ladder_entity && IS_PLAYER(it) && it.move_movetype != MOVETYPE_NOCLIP && !IS_DEAD(it),
21         {
22                 vector emin = it.absmin;
23                 vector emax = it.absmax;
24                 if(this.solid == SOLID_BSP || (IS_CSQC && this.solid == SOLID_TRIGGER)) // CSQC doesn't expand properly
25                 {
26                         emin -= '1 1 1';
27                         emax += '1 1 1';
28                 }
29                 if(boxesoverlap(emin, emax, this.absmin, this.absmax)) // quick
30                 {
31                         if(WarpZoneLib_BoxTouchesBrush(emin, emax, this, it)) // accurate
32                         {
33                                 if(!it.ladder_entity)
34                                         IL_PUSH(g_ladderents, it);
35                                 it.ladder_entity = this;
36                         }
37                 }
38         });
39
40 #ifdef SVQC
41         this.nextthink = time;
42 #endif
43 }
44
45 #ifdef SVQC
46 bool func_ladder_send(entity this, entity to, int sf)
47 {
48         WriteHeader(MSG_ENTITY, ENT_CLIENT_LADDER);
49
50         WriteString(MSG_ENTITY, this.classname);
51         WriteByte(MSG_ENTITY, this.skin);
52         WriteCoord(MSG_ENTITY, this.speed);
53
54         trigger_common_write(this, false);
55
56         return true;
57 }
58
59 void func_ladder_link(entity this)
60 {
61         trigger_link(this, func_ladder_send);
62         //this.model = "null";
63 }
64
65 void func_ladder_init(entity this)
66 {
67         string m = this.model;
68         EXACTTRIGGER_INIT;
69         // restore the model string unset in WarpZoneLib_ExactTrigger_Init()
70         // see: https://gitlab.com/xonotic/xonotic-data.pk3dir/-/issues/2838
71         this.model = m;
72         BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
73         func_ladder_link(this);
74         setthink(this, func_ladder_think);
75         this.nextthink = time;
76
77         if(min(this.absmax.x - this.absmin.x, this.absmax.y - this.absmin.y) > 100)
78                 return;
79
80         entity tracetest_ent = spawn();
81         setsize(tracetest_ent, PL_MIN_CONST, PL_MAX_CONST);
82         tracetest_ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
83
84         vector top_min = (this.absmin + this.absmax) / 2;
85         top_min.z = this.absmax.z;
86         vector top_max = top_min;
87         top_max.z += PL_MAX_CONST.z - PL_MIN_CONST.z;
88         tracebox(top_max + jumpstepheightvec, PL_MIN_CONST, PL_MAX_CONST, top_min, MOVE_NOMONSTERS, tracetest_ent);
89         if(trace_startsolid)
90         {
91                 tracebox(top_max + stepheightvec, PL_MIN_CONST, PL_MAX_CONST, top_min, MOVE_NOMONSTERS, tracetest_ent);
92                 if(trace_startsolid)
93                 {
94                         tracebox(top_max, PL_MIN_CONST, PL_MAX_CONST, top_min, MOVE_NOMONSTERS, tracetest_ent);
95                         if(trace_startsolid)
96                         {
97                                 if(this.absmax.x - this.absmin.x > PL_MAX_CONST.x - PL_MIN_CONST.x
98                                         && this.absmax.y - this.absmin.y < this.absmax.x - this.absmin.x)
99                                 {
100                                         // move top on one side
101                                         top_max.y = top_min.y = this.absmin.y + (PL_MAX_CONST.y - PL_MIN_CONST.y) * 0.75;
102                                 }
103                                 else if(this.absmax.y - this.absmin.y > PL_MAX_CONST.y - PL_MIN_CONST.y
104                                         && this.absmax.x - this.absmin.x < this.absmax.y - this.absmin.y)
105                                 {
106                                         // move top on one side
107                                         top_max.x = top_min.x = this.absmin.x + (PL_MAX_CONST.x - PL_MIN_CONST.x) * 0.75;
108                                 }
109                                 tracebox(top_max, PL_MIN_CONST, PL_MAX_CONST, top_min, MOVE_NOMONSTERS, tracetest_ent);
110                                 if(trace_startsolid)
111                                 {
112                                         if(this.absmax.x - this.absmin.x > PL_MAX_CONST.x - PL_MIN_CONST.x
113                                                 && this.absmax.y - this.absmin.y < this.absmax.x - this.absmin.x)
114                                         {
115                                                 // alternatively on the other side
116                                                 top_max.y = top_min.y = this.absmax.y - (PL_MAX_CONST.y - PL_MIN_CONST.y) * 0.75;
117                                         }
118                                         else if(this.absmax.y - this.absmin.y > PL_MAX_CONST.y - PL_MIN_CONST.y
119                                                 && this.absmax.x - this.absmin.x < this.absmax.y - this.absmin.y)
120                                         {
121                                                 // alternatively on the other side
122                                                 top_max.x = top_min.x = this.absmax.x - (PL_MAX_CONST.x - PL_MIN_CONST.x) * 0.75;
123                                         }
124                                         tracebox(top_max, PL_MIN_CONST, PL_MAX_CONST, top_min, MOVE_NOMONSTERS, tracetest_ent);
125                                 }
126                         }
127                 }
128         }
129         delete(tracetest_ent);
130         if(trace_startsolid || trace_endpos.z < this.absmax.z)
131         {
132                 return;
133         }
134
135         this.bot_pickup = true; // allow bots to make use of this ladder
136         float cost = waypoint_getlinearcost(trace_endpos.z - this.absmin.z);
137         top_min = trace_endpos;
138         waypoint_spawnforteleporter_boxes(this, WAYPOINTFLAG_LADDER, this.absmin, this.absmax, top_min, top_min, cost);
139 }
140
141 spawnfunc(func_ladder)
142 {
143         IL_PUSH(g_ladders, this); // TODO: also func_water? bots currently loop through func_ladder only
144
145         func_ladder_init(this);
146 }
147
148 spawnfunc(func_water)
149 {
150         func_ladder_init(this);
151 }
152
153 #elif defined(CSQC)
154 .float speed;
155
156 void func_ladder_draw(entity this) { func_ladder_think(this); }
157
158 void func_ladder_remove(entity this)
159 {
160         IL_EACH(g_ladderents, it.ladder_entity == this,
161         {
162                 it.ladder_entity = NULL;
163                 IL_REMOVE(g_ladderents, it);
164         });
165         strfree(this.classname);
166 }
167
168 NET_HANDLE(ENT_CLIENT_LADDER, bool isnew)
169 {
170         this.classname = strzone(ReadString());
171         this.skin = ReadByte();
172         this.speed = ReadCoord();
173         this.solid = SOLID_TRIGGER;
174
175         trigger_common_read(this, false);
176
177         if(isnew)
178                 IL_PUSH(g_drawables, this);
179         this.draw = func_ladder_draw;
180         this.drawmask = MASK_NORMAL;
181
182         this.move_time = time;
183         this.entremove = func_ladder_remove;
184
185         // NOTE: CSQC's version of setorigin doesn't expand
186         this.absmin -= '1 1 1';
187         this.absmax += '1 1 1';
188
189         return true;
190 }
191 #endif