X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Ft_items.qc;h=c5ffb163684bf8a3cd5e0599c42738df93debe96;hp=ca441e18a1dab21891007996530ca57141375aec;hb=00f75fd083e3ac717cd68f73cc8c1db3c46e8a72;hpb=a8e4e2497120bb8b8b3600f3b48276148c83285a diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc index ca441e18a..c5ffb1636 100644 --- a/qcsrc/server/t_items.qc +++ b/qcsrc/server/t_items.qc @@ -1,3 +1,232 @@ +#define ISF_LOCATION 2 +#define ISF_MODEL 4 +#define ISF_STATUS 8 + #define ITS_STAYWEP 1 + #define ITS_ANIMATE1 2 + #define ITS_ANIMATE2 4 + #define ITS_AVAILABLE 8 + #define ITS_ALLOWFB 16 + #define ITS_ALLOWSI 32 + #define ITS_POWERUP 64 +#define ISF_COLORMAP 16 +#define ISF_DROP 32 + +.float ItemStatus; + +#ifdef CSQC + +float autocvar_cl_ghost_items; +vector autocvar_cl_ghost_items_color; +float autocvar_cl_simple_items; +float autocvar_cl_fullbright_items; +vector autocvar_cl_staywep_color; +float autocvar_cl_staywep_alpha; + +.float spawntime; +.float gravity; +.vector colormod; +void ItemDraw() +{ + if(self.ItemStatus & ITS_ANIMATE1) + { + self.angles += '0 180 0' * frametime; + setorigin(self, '0 0 10' + self.oldorigin + '0 0 8' * sin(time * 2)); + } + + if(self.ItemStatus & ITS_ANIMATE2) + { + self.angles += '0 -90 0' * frametime; + setorigin(self, '0 0 8' + self.oldorigin + '0 0 4' * sin(time * 3)); + } + + if(self.gravity) + Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); +} + +void ItemDrawSimple() +{ + if(self.gravity) + Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); +} + +float csqcitems_started; // remove this after a release or two +void csqcitems_start() +{ + autocvar_cl_ghost_items = bound(0, autocvar_cl_ghost_items, 1); + if(autocvar_cl_ghost_items == 1) + autocvar_cl_ghost_items = 0.55; + + string _tmp = cvar_string("cl_ghost_items_color"); + if(_tmp == "") + autocvar_cl_ghost_items_color = '-1 -1 -1'; + + csqcitems_started = TRUE; +} + +void ItemRead(float _IsNew) +{ + if(!csqcitems_started) + csqcitems_start(); + + float sf = ReadByte(); + + if(sf & ISF_LOCATION) + { + self.origin_x = ReadCoord(); + self.origin_y = ReadCoord(); + self.origin_z = ReadCoord(); + setorigin(self, self.origin); + self.oldorigin = self.origin; + } + + if(sf & ISF_STATUS) // need to read/write status frist so model can handle simple, fb etc. + { + self.ItemStatus = ReadByte(); + + if(self.ItemStatus & ITS_AVAILABLE) + { + self.alpha = 1; + self.colormod = self.glowmod = '1 1 1'; + } + else + { + if (autocvar_cl_ghost_items) + { + self.alpha = autocvar_cl_ghost_items; + self.colormod = self.glowmod = autocvar_cl_ghost_items_color; + } + else + self.alpha = -1; + } + + if(autocvar_cl_fullbright_items) + if(self.ItemStatus & ITS_ALLOWFB) + self.effects |= EF_FULLBRIGHT; + + if(self.ItemStatus & ITS_STAYWEP) + { + self.colormod = self.glowmod = autocvar_cl_staywep_color; + self.alpha = autocvar_cl_staywep_alpha; + + } + + if(self.ItemStatus & ITS_POWERUP) + { + if(self.ItemStatus & ITS_AVAILABLE) + self.effects |= (EF_ADDITIVE | EF_FULLBRIGHT); + else + self.effects &~= (EF_ADDITIVE | EF_FULLBRIGHT); + } + } + + if(sf & ISF_MODEL) + { + self.drawmask = MASK_NORMAL; + self.movetype = MOVETYPE_NOCLIP; + + if(self.mdl) + strunzone(self.mdl); + + self.mdl = ""; + string _fn = ReadString(); + + if(autocvar_cl_simple_items && (self.ItemStatus & ITS_ALLOWSI)) + { + string _fn2 = substring(_fn, 0 , strlen(_fn) -4); + + if(fexists(strcat(_fn2, "_simple.md3"))) + self.mdl = strzone(strcat(_fn2, "_simple.md3")); + else if(fexists(strcat(_fn2, "_simple.dpm"))) + self.mdl = strzone(strcat(_fn2, "_simple.dpm")); + else if(fexists(strcat(_fn2, "_simple.iqm"))) + self.mdl = strzone(strcat(_fn2, "_simple.iqm")); + else if(fexists(strcat(_fn2, "_simple.obj"))) + self.mdl = strzone(strcat(_fn2, "_simple.obj")); + else + { + self.mdl = ""; + dprint("Simple item requested for ", _fn, " but no model exsist for it\n"); + } + } + + if(self.mdl == "") + { + self.mdl = strzone(_fn); + self.draw = ItemDraw; + } + else + self.draw = ItemDrawSimple; + + precache_model(self.mdl); + setmodel(self, self.mdl); + } + + if(sf & ISF_COLORMAP) + self.colormap = ReadShort(); + + if(sf & ISF_DROP) + { + self.effects |= EF_FLAME; + self.gravity = 1; + self.move_movetype = MOVETYPE_TOSS; + self.move_velocity_x = ReadCoord(); + self.move_velocity_y = ReadCoord(); + self.move_velocity_z = ReadCoord(); + self.velocity = self.move_velocity; + self.move_origin = self.oldorigin; + + if(!self.move_time) + { + self.move_time = time; + self.spawntime = time; + } + else + self.move_time = max(self.move_time, time); + } +} +#endif + +#ifdef SVQC +float autocvar_sv_simple_items; +float ItemSend(entity to, float sf) +{ + if(self.gravity) + sf |= ISF_DROP; + else + sf &~= ISF_DROP; + + WriteByte(MSG_ENTITY, ENT_CLIENT_ITEM); + WriteByte(MSG_ENTITY, sf); + + + //WriteByte(MSG_ENTITY, self.cnt); + if(sf & ISF_LOCATION) + { + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + } + + if(sf & ISF_STATUS) + WriteByte(MSG_ENTITY, self.ItemStatus); + + if(sf & ISF_MODEL) + WriteString(MSG_ENTITY, self.mdl); + + if(sf & ISF_COLORMAP) + WriteShort(MSG_ENTITY, self.colormap); + + if(sf & ISF_DROP) + { + WriteCoord(MSG_ENTITY, self.velocity_x); + WriteCoord(MSG_ENTITY, self.velocity_y); + WriteCoord(MSG_ENTITY, self.velocity_z); + } + + return TRUE; +} + + float have_pickup_item(void) { // minstagib: only allow filtered items @@ -78,7 +307,7 @@ string Item_CounterFieldName(float it) .float max_armorvalue; .float pickup_anyway; - +/* float Item_Customize() { if(self.spawnshieldtime) @@ -103,80 +332,63 @@ float Item_Customize() return FALSE; } } +*/ void Item_Show (entity e, float mode) -{ +{ e.effects &~= EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST; + e.ItemStatus &~= ITS_STAYWEP; if (mode > 0) { // make the item look normal, and be touchable e.model = e.mdl; e.solid = SOLID_TRIGGER; - e.colormod = '0 0 0'; - self.glowmod = self.colormod; - e.alpha = 0; - e.customizeentityforclient = func_null; - e.spawnshieldtime = 1; + e.ItemStatus |= ITS_AVAILABLE; } else if (mode < 0) { // hide the item completely e.model = string_null; e.solid = SOLID_NOT; - e.colormod = '0 0 0'; - self.glowmod = self.colormod; - e.alpha = 0; - e.customizeentityforclient = func_null; - e.spawnshieldtime = 1; + e.ItemStatus &~= ITS_AVAILABLE; } else if((e.flags & FL_WEAPON) && !(e.flags & FL_NO_WEAPON_STAY) && g_weapon_stay) { // make the item translucent and not touchable e.model = e.mdl; e.solid = SOLID_TRIGGER; // can STILL be picked up! - e.colormod = '0 0 0'; - self.glowmod = self.colormod; e.effects |= EF_STARDUST; - e.customizeentityforclient = Item_Customize; - e.spawnshieldtime = 0; // field indicates whether picking it up may give you anything other than the weapon - } - else if(g_ghost_items) - { - // make the item translucent and not touchable - e.model = e.mdl; - e.solid = SOLID_NOT; - e.colormod = stov(autocvar_g_ghost_items_color); - e.glowmod = e.colormod; - e.alpha = g_ghost_items; - e.customizeentityforclient = func_null; - - e.spawnshieldtime = 1; + e.ItemStatus |= (ITS_AVAILABLE | ITS_STAYWEP); } else { - // hide the item completely - e.model = string_null; + //setmodel(e, "null"); e.solid = SOLID_NOT; e.colormod = '0 0 0'; e.glowmod = e.colormod; - e.alpha = 0; - e.customizeentityforclient = func_null; - e.spawnshieldtime = 1; + e.ItemStatus &~= ITS_AVAILABLE; } - - if (e.items & (IT_STRENGTH | IT_INVINCIBLE)) - e.effects |= EF_ADDITIVE | EF_FULLBRIGHT; + + if (e.items & IT_STRENGTH || e.items & IT_INVINCIBLE) + e.ItemStatus |= ITS_POWERUP; + if (autocvar_g_nodepthtestitems) e.effects |= EF_NODEPTHTEST; - if (autocvar_g_fullbrightitems) - e.effects |= EF_FULLBRIGHT; + + + if (autocvar_g_fullbrightitems) + e.ItemStatus |= ITS_ALLOWFB; + + if (autocvar_sv_simple_items) + e.ItemStatus |= ITS_ALLOWSI; // relink entity (because solid may have changed) setorigin(e, e.origin); + e.SendFlags |= ISF_STATUS; } void Item_Respawn (void) @@ -378,8 +590,6 @@ float Item_GiveTo(entity item, entity player) if (WEPSET_CONTAINS_EW(item, WEP_MINSTANEX)) W_GiveWeapon (player, WEP_MINSTANEX, item.netname); - if (item.ammo_cells) - player.ammo_cells = bound(player.ammo_cells, 999, player.ammo_cells + autocvar_g_minstagib_ammo_drop); player.health = 100; } @@ -448,10 +658,8 @@ float Item_GiveTo(entity item, entity player) { pickedup = TRUE; for(i = WEP_FIRST; i <= WEP_LAST; ++i) - { if(WEPSET_CONTAINS_AW(it, i)) W_GiveWeapon (player, i, item.netname); - } } } @@ -499,11 +707,15 @@ void Item_Touch (void) entity e, head; // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky) - if (((trace_dpstartcontents | trace_dphitcontents) & DPCONTENTS_NODROP) || (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)) + if(self.classname == "droppedweapon") { - remove(self); - return; + if (ITEM_TOUCH_NEEDKILL()) + { + remove(self); + return; + } } + if (other.classname != "player") return; if (other.deadflag) @@ -555,6 +767,7 @@ void Item_Touch (void) } } e = RandomSelection_chosen_ent; + } else e = self; @@ -731,18 +944,44 @@ float commodity_pickupevalfunc(entity player, entity item) return item.bot_pickupbasevalue * c; } +void Item_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if(ITEM_DAMAGE_NEEDKILL(deathtype)) + RemoveItem(); +} .float is_item; void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, float defaultrespawntimejitter, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue) { startitem_failed = FALSE; + if(self.model == "") + self.model = itemmodel; + + if(self.item_pickupsound == "") + self.item_pickupsound = pickupsound; + + if(!self.respawntime) // both need to be set + { + self.respawntime = defaultrespawntime; + self.respawntimejitter = defaultrespawntimejitter; + } + self.items = itemid; self.weapon = weaponid; + if(weaponid) WEPSET_COPY_EW(self, weaponid); + self.flags = FL_ITEM | itemflags; + if(MUTATOR_CALLHOOK(FilterItem)) // error means we do not want the item + { + startitem_failed = TRUE; + remove(self); + return; + } + // is it a dropped weapon? if (self.classname == "droppedweapon") { @@ -754,6 +993,9 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, self.think = RemoveItem; self.nextthink = time + 20; + self.takedamage = DAMAGE_YES; + self.event_damage = Item_Damage; + if(self.strength_finished || self.invincible_finished || self.superweapons_finished) /* if(self.items == 0) @@ -782,13 +1024,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, } else { - if(MUTATOR_CALLHOOK(FilterItem)) // error means we do not want the item - { - startitem_failed = TRUE; - remove(self); - return; - } - if(!have_pickup_item()) { startitem_failed = TRUE; @@ -796,11 +1031,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, return; } - if(self.model != "") - itemmodel = self.model; - if(self.item_pickupsound != "") - pickupsound = self.item_pickupsound; - self.reset = Item_Reset; // it's a level item if(self.spawnflags & 1) @@ -843,6 +1073,7 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, entity otheritem; for(otheritem = findradius(self.origin, 3); otheritem; otheritem = otheritem.chain) { + // why not flags & fl_item? if(otheritem.is_item) { dprint("XXX Found duplicated item: ", itemname, vtos(self.origin)); @@ -855,8 +1086,8 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, WEPSET_OR_AW(weaponsInMap, weaponid); - precache_model (itemmodel); - precache_sound (pickupsound); + precache_model (self.model); + precache_sound (self.item_pickupsound); precache_sound ("misc/itemrespawncountdown.wav"); if(!g_minstagib && itemid == IT_STRENGTH) @@ -873,42 +1104,54 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, self.bot_pickup = TRUE; self.bot_pickupevalfunc = pickupevalfunc; self.bot_pickupbasevalue = pickupbasevalue; - self.mdl = itemmodel; - self.item_pickupsound = pickupsound; - // let mappers override respawntime - if(!self.respawntime) // both set - { - self.respawntime = defaultrespawntime; - self.respawntimejitter = defaultrespawntimejitter; - } + self.mdl = self.model; self.netname = itemname; self.touch = Item_Touch; - setmodel (self, self.mdl); // precision set below - self.effects |= EF_LOWPRECISION; + setmodel(self, "null"); // precision set below + //self.effects |= EF_LOWPRECISION; + if((itemflags & FL_POWERUP) || self.health || self.armorvalue) - setsize (self, '-16 -16 0', '16 16 48'); + { + self.pos1 = '-16 -16 0'; + self.pos2 = '16 16 48'; + } else - setsize (self, '-16 -16 0', '16 16 32'); + { + self.pos1 = '-16 -16 0'; + self.pos2 = '16 16 32'; + } + setsize (self, self.pos1, self.pos2); + + if(itemflags & FL_POWERUP) + self.ItemStatus |= ITS_ANIMATE1; + + if(self.armorvalue || self.health) + self.ItemStatus |= ITS_ANIMATE2; + if(itemflags & FL_WEAPON) - self.modelflags |= MF_ROTATE; - - if (self.classname != "droppedweapon") // if dropped, colormap is already set up nicely - if (itemflags & FL_WEAPON) { - // neutral team color for pickup weapons - self.colormap = 1024; // color shirt=0 pants=0 grey + if (self.classname != "droppedweapon") // if dropped, colormap is already set up nicely + self.colormap = 1024; // color shirt=0 pants=0 grey + else + self.gravity = 1; + + self.ItemStatus |= ITS_ANIMATE1; + self.ItemStatus |= ISF_COLORMAP; } self.state = 0; - if(self.team) + if(self.team) // broken, no idea why. { if(!self.cnt) self.cnt = 1; // item probability weight - self.effects = self.effects | EF_NODRAW; // marker for item team search + + self.effects |= EF_NODRAW; // marker for item team search InitializeEntity(self, Item_FindTeam, INITPRIO_FINDTARGET); } else Item_Reset(); + + Net_LinkEntity(self, FALSE, 0, ItemSend); } /* replace items in minstagib @@ -916,10 +1159,10 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, * IT_NAILS = extra lives * IT_INVINCIBLE = speed */ -void minstagib_items (float itemid) +void minstagib_items (float itemid) // will be deleted soon. { float rnd; - self.classname = "minstagib"; + self.classname = "minstagib"; // ...? // replace rocket launchers and nex guns with ammo cells if (itemid == IT_CELLS) @@ -990,8 +1233,23 @@ void weapon_defaultspawnfunc(float wpn) if(self.classname != "droppedweapon" && self.classname != "replacedweapon") { e = get_weaponinfo(wpn); - s = cvar_string(strcat("g_weaponreplace_", e.netname)); - if(s == "0") + + if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED) + { + print("Attempted to spawn a mutator-blocked weapon; these guns will in the future require a mutator\n"); + /* + objerror("Attempted to spawn a mutator-blocked weapon rejected"); + startitem_failed = TRUE; + return; + */ + } + + s = W_Apply_Weaponreplace(e.netname); + ret_string = s; + other = e; + MUTATOR_CALLHOOK(SetWeaponreplace); + s = ret_string; + if(s == "") { remove(self); startitem_failed = TRUE; @@ -1024,7 +1282,7 @@ void weapon_defaultspawnfunc(float wpn) } self = oldself; } - if(t >= 1) + if(t >= 1) // always the case! { s = argv(0); wpn = 0; @@ -1097,6 +1355,11 @@ void weapon_defaultspawnfunc(float wpn) if(self.team) f |= FL_NO_WEAPON_STAY; + // stupid minstagib hack, don't ask + if(g_minstagib) + if(self.ammo_cells) + self.ammo_cells = autocvar_g_minstagib_ammo_drop; + StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue); if (self.modelindex) // don't precache if self was removed weapon_action(e.weapon, WR_PRECACHE); @@ -1327,7 +1590,7 @@ void spawnfunc_item_invincible (void) { void spawnfunc_item_minst_cells (void) { if (g_minstagib) { - minst_no_auto_cells = 1; + minst_no_auto_cells = TRUE; minstagib_items(IT_CELLS); } else @@ -1712,7 +1975,8 @@ float GiveItems(entity e, float beginarg, float endarg) { wi = get_weaponinfo(j); if(wi.weapon) - got += GiveWeapon(e, j, op, val); + if not(wi.spawnflags & WEP_FLAG_MUTATORBLOCKED) + got += GiveWeapon(e, j, op, val); } case "allammo": got += GiveValue(e, ammo_cells, op, val); @@ -1840,3 +2104,4 @@ float GiveItems(entity e, float beginarg, float endarg) return got; } +#endif