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
16 void Item_SetAlpha(entity this)
18 bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
20 if(!veh_hud && (this.ItemStatus & ITS_AVAILABLE))
23 this.colormod = '1 1 1';
24 this.glowmod = this.item_glowmod;
28 this.alpha = autocvar_cl_ghost_items;
29 this.colormod = this.glowmod = autocvar_cl_ghost_items_color;
32 if((!veh_hud) && (this.ItemStatus & ITS_STAYWEP))
34 this.colormod = this.glowmod = autocvar_cl_weapon_stay_color;
35 this.alpha = autocvar_cl_weapon_stay_alpha;
38 this.drawmask = ((this.alpha <= 0) ? 0 : MASK_NORMAL);
41 void ItemDraw(entity this)
45 Movetype_Physics_MatchServer(this, false);
47 { // For some reason avelocity gets set to '0 0 0' here ...
48 this.oldorigin = this.origin;
51 if(autocvar_cl_animate_items)
52 { // ... so reset it if animations are requested.
53 if(this.ItemStatus & ITS_ANIMATE1)
54 this.avelocity = '0 180 0';
56 if(this.ItemStatus & ITS_ANIMATE2)
57 this.avelocity = '0 -90 0';
60 // delay is for blocking item's position for a while;
61 // it's a workaround for dropped weapons that receive the position
62 // another time right after they spawn overriding animation position
63 this.onground_time = time + 0.5;
66 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)
68 if(this.ItemStatus & ITS_ANIMATE1)
70 this.angles += this.avelocity * frametime;
71 float fade_in = bound(0, time - this.onground_time, 1);
72 setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2)));
75 if(this.ItemStatus & ITS_ANIMATE2)
77 this.angles += this.avelocity * frametime;
78 float fade_in = bound(0, time - this.onground_time, 1);
79 setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3)));
86 void Item_PreDraw(entity this)
88 if(warpzone_warpzones_exist)
90 setpredraw(this, func_null); // no need to keep running this
94 vector org = getpropertyvec(VF_ORIGIN);
95 //if(!checkpvs(org, this)) // this makes sense as long as we don't support recursive warpzones
96 //alph = 0; // this shouldn't be needed, since items behind walls are culled anyway
99 if(vdist(org - this.origin, >, this.fade_end))
100 alph = 0; // save on some processing
101 else if(vdist(org - this.origin, <, this.fade_start))
102 alph = 1; // more processing saved
104 alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
108 //printf("%v <-> %v\n", view_origin, this.origin + 0.5 * (this.mins + this.maxs));
109 if(!hud && (this.ItemStatus & ITS_AVAILABLE))
114 //this.drawmask = MASK_NORMAL; // reset by the setalpha function
117 void ItemRemove(entity this)
122 HashMap ENT_CLIENT_ITEM_simple;
123 STATIC_INIT(ENT_CLIENT_ITEM_simple)
125 HM_NEW(ENT_CLIENT_ITEM_simple);
127 SHUTDOWN(ENT_CLIENT_ITEM_simple)
129 HM_DELETE(ENT_CLIENT_ITEM_simple);
132 NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
136 if(sf & ISF_LOCATION)
138 this.origin = ReadVector();
139 setorigin(this, this.origin);
140 this.oldorigin = this.origin;
145 this.angles = ReadAngleVector();
150 setsize(this, '-16 -16 0', '16 16 48');
153 if(sf & ISF_STATUS) // need to read/write status first so model can handle simple, fb etc.
155 this.ItemStatus = ReadByte();
159 if(this.ItemStatus & ITS_ALLOWFB)
160 this.effects |= EF_FULLBRIGHT;
162 this.effects &= ~EF_FULLBRIGHT;
164 if(this.ItemStatus & ITS_GLOW)
166 if(this.ItemStatus & ITS_AVAILABLE)
167 this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
169 this.effects &= ~(EF_ADDITIVE | EF_FULLBRIGHT);
175 this.drawmask = MASK_NORMAL;
176 set_movetype(this, MOVETYPE_TOSS);
177 if (isnew) IL_PUSH(g_drawables, this);
178 this.draw = ItemDraw;
179 this.solid = SOLID_TRIGGER;
180 //this.flags |= FL_ITEM;
182 this.fade_end = ReadShort();
183 this.fade_start = ReadShort();
184 if(!warpzone_warpzones_exist && this.fade_start && !autocvar_cl_items_nofade)
185 setpredraw(this, Item_PreDraw);
189 string _fn = ReadString();
190 this.item_simple = false; // reset it!
192 if(autocvar_cl_simple_items && (this.ItemStatus & ITS_ALLOWSI))
194 string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
195 this.item_simple = true;
197 #define extensions(x) \
203 #define tryext(ext) { \
204 string s = strcat(_fn2, autocvar_cl_simpleitems_postfix, "." #ext); \
205 string cached = HM_gets(ENT_CLIENT_ITEM_simple, s); \
206 if (cached == "") { \
207 HM_sets(ENT_CLIENT_ITEM_simple, s, cached = fexists(s) ? "1" : "0"); \
209 if (cached != "0") { \
210 strcpy(this.mdl, s); \
216 this.item_simple = false;
217 LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
223 if(!this.item_simple)
224 strcpy(this.mdl, _fn);
227 LOG_WARNF("this.mdl is unset for item %s", this.classname);
229 precache_model(this.mdl);
230 _setmodel(this, this.mdl);
232 setsize(this, '-16 -16 0', '16 16 48');
235 if(sf & ISF_COLORMAP)
237 this.colormap = ReadShort();
238 this.item_glowmod_x = ReadByte() / 255.0;
239 this.item_glowmod_y = ReadByte() / 255.0;
240 this.item_glowmod_z = ReadByte() / 255.0;
246 this.pushable = true;
247 //this.angles = '0 0 0';
248 set_movetype(this, MOVETYPE_TOSS);
249 this.velocity = ReadVector();
250 setorigin(this, this.oldorigin);
254 this.move_time = time;
255 this.spawntime = time;
258 this.move_time = max(this.move_time, time);
261 if(autocvar_cl_animate_items)
263 if(this.ItemStatus & ITS_ANIMATE1)
264 this.avelocity = '0 180 0';
266 if(this.ItemStatus & ITS_ANIMATE2)
267 this.avelocity = '0 -90 0';
270 this.entremove = ItemRemove;