3 #include <client/main.qh>
4 #include <common/items/_mod.qh>
5 #include <common/physics/movetypes/movetypes.qh>
6 #include <common/weapons/_all.qh>
7 #include <lib/csqcmodel/cl_model.qh>
8 #include <lib/csqcmodel/common.qh>
9 #include <lib/warpzone/common.qh>
12 .bool item_simple; // probably not really needed, but better safe than sorry
16 void ItemDraw(entity this)
20 Movetype_Physics_MatchServer(this, false);
22 { // For some reason avelocity gets set to '0 0 0' here ...
23 this.oldorigin = this.origin;
26 if(autocvar_cl_animate_items)
27 { // ... so reset it if animations are requested.
28 if(this.ItemStatus & ITS_ANIMATE1)
29 this.avelocity = '0 180 0';
31 if(this.ItemStatus & ITS_ANIMATE2)
32 this.avelocity = '0 -90 0';
35 // delay is for blocking item's position for a while;
36 // it's a workaround for dropped weapons that receive the position
37 // another time right after they spawn overriding animation position
38 this.onground_time = time + 0.5;
41 else if (autocvar_cl_animate_items && !this.item_simple) // no bobbing applied to simple items, for consistency's sake (no visual difference between ammo and weapons)
43 if(this.ItemStatus & ITS_ANIMATE1)
45 this.angles += this.avelocity * frametime;
46 float fade_in = bound(0, time - this.onground_time, 1);
47 setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2)));
50 if(this.ItemStatus & ITS_ANIMATE2)
52 this.angles += this.avelocity * frametime;
53 float fade_in = bound(0, time - this.onground_time, 1);
54 setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3)));
58 // set alpha based on distance
61 if(this.fade_end && !warpzone_warpzones_exist)
63 vector org = getpropertyvec(VF_ORIGIN);
64 if(vdist(org - this.origin, >, this.fade_end))
65 this.alpha = 0; // save on some processing
66 else if(autocvar_cl_items_fadedist > 0)
68 this.fade_start = max(500, this.fade_end - autocvar_cl_items_fadedist);
69 if(vdist(org - this.origin, >, this.fade_start))
70 this.alpha = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
77 // modify alpha based on availability and vehicle hud
78 if(this.ItemStatus & ITS_AVAILABLE)
80 if(hud) // apparently this means we're in a vehicle lol
82 this.alpha *= autocvar_cl_items_vehicle_alpha;
83 this.colormod = this.glowmod = autocvar_cl_items_vehicle_color;
85 else if(this.ItemStatus & ITS_STAYWEP)
87 this.alpha *= autocvar_cl_weapon_stay_alpha;
88 this.colormod = this.glowmod = autocvar_cl_weapon_stay_color;
92 this.colormod = '1 1 1';
93 this.glowmod = this.item_glowmod;
98 this.alpha *= autocvar_cl_ghost_items;
99 this.colormod = this.glowmod = autocvar_cl_ghost_items_color;
102 this.drawmask = this.alpha <= 0 ? 0 : MASK_NORMAL;
105 void ItemRemove(entity this)
110 HashMap ENT_CLIENT_ITEM_simple;
111 STATIC_INIT(ENT_CLIENT_ITEM_simple)
113 HM_NEW(ENT_CLIENT_ITEM_simple);
115 SHUTDOWN(ENT_CLIENT_ITEM_simple)
117 HM_DELETE(ENT_CLIENT_ITEM_simple);
120 NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
124 if(sf & ISF_LOCATION)
126 vector org = ReadVector();
127 setorigin(this, org);
128 this.oldorigin = org;
133 this.angles = ReadAngleVector();
138 setsize(this, '-16 -16 0', '16 16 48');
141 if(sf & ISF_STATUS) // need to read/write status first so model can handle simple, fb etc.
143 this.ItemStatus = ReadByte();
145 if(this.ItemStatus & ITS_ALLOWFB)
146 this.effects |= EF_FULLBRIGHT;
148 this.effects &= ~EF_FULLBRIGHT;
150 if(this.ItemStatus & ITS_GLOW)
152 if(this.ItemStatus & ITS_AVAILABLE)
153 this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
155 this.effects &= ~(EF_ADDITIVE | EF_FULLBRIGHT);
161 set_movetype(this, MOVETYPE_TOSS);
162 if (isnew) IL_PUSH(g_drawables, this);
163 this.draw = ItemDraw;
164 this.solid = SOLID_TRIGGER;
165 //this.flags |= FL_ITEM;
167 this.fade_end = ReadShort();
171 string _fn = ReadString();
172 this.item_simple = false; // reset it!
174 if(autocvar_cl_simple_items && (this.ItemStatus & ITS_ALLOWSI))
176 string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
177 this.item_simple = true;
179 #define extensions(x) \
185 #define tryext(ext) { \
186 string s = strcat(_fn2, autocvar_cl_simpleitems_postfix, "." #ext); \
187 string cached = HM_gets(ENT_CLIENT_ITEM_simple, s); \
188 if (cached == "") { \
189 HM_sets(ENT_CLIENT_ITEM_simple, s, cached = fexists(s) ? "1" : "0"); \
191 if (cached != "0") { \
192 strcpy(this.mdl, s); \
198 this.item_simple = false;
199 LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
205 if(!this.item_simple)
206 strcpy(this.mdl, _fn);
209 LOG_WARNF("this.mdl is unset for item %s", this.classname);
211 precache_model(this.mdl);
212 _setmodel(this, this.mdl);
214 this.skin = ReadByte();
216 setsize(this, '-16 -16 0', '16 16 48');
219 if(sf & ISF_COLORMAP)
221 this.colormap = ReadShort();
222 this.item_glowmod_x = ReadByte() / 255.0;
223 this.item_glowmod_y = ReadByte() / 255.0;
224 this.item_glowmod_z = ReadByte() / 255.0;
230 this.pushable = true;
231 //this.angles = '0 0 0';
232 set_movetype(this, MOVETYPE_TOSS);
233 this.velocity = ReadVector();
234 setorigin(this, this.oldorigin);
238 this.move_time = time;
239 this.spawntime = time;
242 this.move_time = max(this.move_time, time);
245 if(autocvar_cl_animate_items)
247 if(this.ItemStatus & ITS_ANIMATE1)
248 this.avelocity = '0 180 0';
250 if(this.ItemStatus & ITS_ANIMATE2)
251 this.avelocity = '0 -90 0';
254 this.entremove = ItemRemove;