3 #include <common/items/_mod.qh>
5 #include <client/main.qh>
6 #include <common/physics/movetypes/movetypes.qh>
7 #include <common/weapons/_all.qh>
8 #include <lib/csqcmodel/cl_model.qh>
9 #include <lib/csqcmodel/common.qh>
10 #include <lib/warpzone/common.qh>
12 bool autocvar_cl_ghost_items_vehicle = true;
14 .bool item_simple; // probably not really needed, but better safe than sorry
17 void Item_SetAlpha(entity this)
19 bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
21 if(!veh_hud && (this.ItemStatus & ITS_AVAILABLE))
24 this.colormod = '1 1 1';
25 this.glowmod = this.item_glowmod;
29 this.alpha = autocvar_cl_ghost_items;
30 this.colormod = this.glowmod = autocvar_cl_ghost_items_color;
33 if((!veh_hud) && (this.ItemStatus & ITS_STAYWEP))
35 this.colormod = this.glowmod = autocvar_cl_weapon_stay_color;
36 this.alpha = autocvar_cl_weapon_stay_alpha;
39 this.drawmask = ((this.alpha <= 0) ? 0 : MASK_NORMAL);
42 void ItemDraw(entity this)
46 Movetype_Physics_MatchServer(this, false);
48 { // For some reason avelocity gets set to '0 0 0' here ...
49 this.oldorigin = this.origin;
52 if(autocvar_cl_animate_items)
53 { // ... so reset it if animations are requested.
54 if(this.ItemStatus & ITS_ANIMATE1)
55 this.avelocity = '0 180 0';
57 if(this.ItemStatus & ITS_ANIMATE2)
58 this.avelocity = '0 -90 0';
61 // delay is for blocking item's position for a while;
62 // it's a workaround for dropped weapons that receive the position
63 // another time right after they spawn overriding animation position
64 this.onground_time = time + 0.5;
67 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)
69 if(this.ItemStatus & ITS_ANIMATE1)
71 this.angles += this.avelocity * frametime;
72 float fade_in = bound(0, time - this.onground_time, 1);
73 setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2)));
76 if(this.ItemStatus & ITS_ANIMATE2)
78 this.angles += this.avelocity * frametime;
79 float fade_in = bound(0, time - this.onground_time, 1);
80 setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3)));
87 void Item_PreDraw(entity this)
89 if(warpzone_warpzones_exist)
91 setpredraw(this, func_null); // no need to keep running this
95 vector org = getpropertyvec(VF_ORIGIN);
96 //if(!checkpvs(org, this)) // this makes sense as long as we don't support recursive warpzones
97 //alph = 0; // this shouldn't be needed, since items behind walls are culled anyway
100 if(vdist(org - this.origin, >, this.fade_end))
101 alph = 0; // save on some processing
102 else if(vdist(org - this.origin, <, this.fade_start))
103 alph = 1; // more processing saved
105 alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
109 //printf("%v <-> %v\n", view_origin, this.origin + 0.5 * (this.mins + this.maxs));
110 if(!hud && (this.ItemStatus & ITS_AVAILABLE))
115 //this.drawmask = MASK_NORMAL; // reset by the setalpha function
118 void ItemRemove(entity this)
123 HashMap ENT_CLIENT_ITEM_simple;
124 STATIC_INIT(ENT_CLIENT_ITEM_simple)
126 HM_NEW(ENT_CLIENT_ITEM_simple);
128 SHUTDOWN(ENT_CLIENT_ITEM_simple)
130 HM_DELETE(ENT_CLIENT_ITEM_simple);
133 NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
137 if(sf & ISF_LOCATION)
139 this.origin = ReadVector();
140 setorigin(this, this.origin);
141 this.oldorigin = this.origin;
146 this.angles = ReadAngleVector();
151 setsize(this, '-16 -16 0', '16 16 48');
154 if(sf & ISF_STATUS) // need to read/write status first so model can handle simple, fb etc.
156 this.ItemStatus = ReadByte();
160 if(this.ItemStatus & ITS_ALLOWFB)
161 this.effects |= EF_FULLBRIGHT;
163 this.effects &= ~EF_FULLBRIGHT;
165 if(this.ItemStatus & ITS_GLOW)
167 if(this.ItemStatus & ITS_AVAILABLE)
168 this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
170 this.effects &= ~(EF_ADDITIVE | EF_FULLBRIGHT);
176 this.drawmask = MASK_NORMAL;
177 set_movetype(this, MOVETYPE_TOSS);
178 if (isnew) IL_PUSH(g_drawables, this);
179 this.draw = ItemDraw;
180 this.solid = SOLID_TRIGGER;
181 //this.flags |= FL_ITEM;
183 this.fade_end = ReadShort();
184 this.fade_start = ReadShort();
185 if(!warpzone_warpzones_exist && this.fade_start && !autocvar_cl_items_nofade)
186 setpredraw(this, Item_PreDraw);
190 string _fn = ReadString();
191 this.item_simple = false; // reset it!
193 if(autocvar_cl_simple_items && (this.ItemStatus & ITS_ALLOWSI))
195 string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
196 this.item_simple = true;
198 #define extensions(x) \
204 #define tryext(ext) { \
205 string s = strcat(_fn2, autocvar_cl_simpleitems_postfix, "." #ext); \
206 string cached = HM_gets(ENT_CLIENT_ITEM_simple, s); \
207 if (cached == "") { \
208 HM_sets(ENT_CLIENT_ITEM_simple, s, cached = fexists(s) ? "1" : "0"); \
210 if (cached != "0") { \
211 strcpy(this.mdl, s); \
217 this.item_simple = false;
218 LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
224 if(!this.item_simple)
225 strcpy(this.mdl, _fn);
228 LOG_WARNF("this.mdl is unset for item %s", this.classname);
230 precache_model(this.mdl);
231 _setmodel(this, this.mdl);
233 setsize(this, '-16 -16 0', '16 16 48');
236 if(sf & ISF_COLORMAP)
238 this.colormap = ReadShort();
239 this.item_glowmod_x = ReadByte() / 255.0;
240 this.item_glowmod_y = ReadByte() / 255.0;
241 this.item_glowmod_z = ReadByte() / 255.0;
247 this.pushable = true;
248 //this.angles = '0 0 0';
249 set_movetype(this, MOVETYPE_TOSS);
250 this.velocity = ReadVector();
251 setorigin(this, this.oldorigin);
255 this.move_time = time;
256 this.spawntime = time;
259 this.move_time = max(this.move_time, time);
262 if(autocvar_cl_animate_items)
264 if(this.ItemStatus & ITS_ANIMATE1)
265 this.avelocity = '0 180 0';
267 if(this.ItemStatus & ITS_ANIMATE2)
268 this.avelocity = '0 -90 0';
271 this.entremove = ItemRemove;