X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Ft_items.qc;h=3151d7cdb1c86fb696128d439ef6a38213cff553;hp=79fa97801ed45c615b631b214ede506fcbff6c5d;hb=2f215c603bf1b4dd44b9d166180f535c88602e9f;hpb=9f1b7db1e3034be3219e9a2d2f5189951a48b73d diff --git a/qcsrc/common/t_items.qc b/qcsrc/common/t_items.qc index 79fa97801e..3151d7cdb1 100644 --- a/qcsrc/common/t_items.qc +++ b/qcsrc/common/t_items.qc @@ -58,8 +58,7 @@ void Item_SetAlpha(entity this) this.alpha = -1; } - if(!veh_hud) - if(this.ItemStatus & ITS_STAYWEP) + if((!veh_hud) && (this.ItemStatus & ITS_STAYWEP)) { this.colormod = this.glowmod = autocvar_cl_weapon_stay_color; this.alpha = autocvar_cl_weapon_stay_alpha; @@ -449,28 +448,30 @@ void Item_Show (entity e, float mode) e.spawnshieldtime = 1; e.ItemStatus &= ~ITS_AVAILABLE; } - else { - bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.weapons & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons - || e.team // weapon stay isn't supported for teamed weapons - ; - if(def.instanceOfWeaponPickup && !nostay && g_weapon_stay) - { - // make the item translucent and not touchable - e.model = e.mdl; - e.solid = SOLID_TRIGGER; // can STILL be picked up! - e.effects |= EF_STARDUST; - e.spawnshieldtime = 0; // field indicates whether picking it up may give you anything other than the weapon - e.ItemStatus |= (ITS_AVAILABLE | ITS_STAYWEP); - } else { - //setmodel(e, "null"); - e.solid = SOLID_NOT; - e.colormod = '0 0 0'; - //e.glowmod = e.colormod; - e.spawnshieldtime = 1; - e.ItemStatus &= ~ITS_AVAILABLE; - }} + bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.weapons & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons + || e.team // weapon stay isn't supported for teamed weapons + ; + if(def.instanceOfWeaponPickup && !nostay && g_weapon_stay) + { + // make the item translucent and not touchable + e.model = e.mdl; + e.solid = SOLID_TRIGGER; // can STILL be picked up! + e.effects |= EF_STARDUST; + e.spawnshieldtime = 0; // field indicates whether picking it up may give you anything other than the weapon + e.ItemStatus |= (ITS_AVAILABLE | ITS_STAYWEP); + } + else + { + //setmodel(e, "null"); + e.solid = SOLID_NOT; + e.colormod = '0 0 0'; + //e.glowmod = e.colormod; + e.spawnshieldtime = 1; + e.ItemStatus &= ~ITS_AVAILABLE; + } + } if (def.m_glow) e.ItemStatus |= ITS_GLOW; @@ -509,7 +510,7 @@ void Item_Respawn (entity this) sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM); // play respawn sound setorigin(this, this.origin); - if (Item_ItemsTime_Allow(this.itemdef) || this.weapons & WEPSET_SUPERWEAPONS) + if (Item_ItemsTime_Allow(this.itemdef) || (this.weapons & WEPSET_SUPERWEAPONS)) { float t = Item_ItemsTime_UpdateTime(this, 0); Item_ItemsTime_SetTime(this, t); @@ -537,7 +538,6 @@ void Item_RespawnCountdown (entity this) this.count += 1; if(this.count == 1) { - MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0'); do { { entity wi = Weapons_from(this.weapon); @@ -556,10 +556,11 @@ void Item_RespawnCountdown (entity this) } } } while (0); + bool mutator_returnvalue = MUTATOR_CALLHOOK(Item_RespawnCountdown, this); if(this.waypointsprite_attached) { GameItem def = this.itemdef; - if (Item_ItemsTime_SpectatorOnly(def)) + if (Item_ItemsTime_SpectatorOnly(def) && !mutator_returnvalue) WaypointSprite_UpdateRule(this.waypointsprite_attached, 0, SPRITERULE_SPECTATOR); WaypointSprite_UpdateBuildFinished(this.waypointsprite_attached, time + ITEM_RESPAWN_TICKS); } @@ -594,15 +595,18 @@ void Item_RespawnThink(entity this) void Item_ScheduleRespawnIn(entity e, float t) { // if the respawn time is longer than 10 seconds, show a waypoint, otherwise, just respawn normally - if ((Item_ItemsTime_Allow(e.itemdef) || e.weapons & WEPSET_SUPERWEAPONS) && (t - ITEM_RESPAWN_TICKS) > 0) + if ((Item_ItemsTime_Allow(e.itemdef) || (e.weapons & WEPSET_SUPERWEAPONS) || MUTATOR_CALLHOOK(Item_ScheduleRespawn, e, t)) && (t - ITEM_RESPAWN_TICKS) > 0) { setthink(e, Item_RespawnCountdown); e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS); e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS; e.count = 0; - t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime); - Item_ItemsTime_SetTime(e, t); - Item_ItemsTime_SetTimesForAllPlayers(); + if(Item_ItemsTime_Allow(e.itemdef) || (e.weapons & WEPSET_SUPERWEAPONS)) + { + t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime); + Item_ItemsTime_SetTime(e, t); + Item_ItemsTime_SetTimesForAllPlayers(); + } } else { @@ -610,6 +614,13 @@ void Item_ScheduleRespawnIn(entity e, float t) e.nextthink = time; e.scheduledrespawntime = time + t; e.wait = time + t; + + if(Item_ItemsTime_Allow(e.itemdef) || (e.weapons & WEPSET_SUPERWEAPONS)) + { + t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime); + Item_ItemsTime_SetTime(e, t); + Item_ItemsTime_SetTimesForAllPlayers(); + } } } @@ -627,7 +638,7 @@ void Item_ScheduleRespawn(entity e) void Item_ScheduleInitialRespawn(entity e) { Item_Show(e, 0); - Item_ScheduleRespawnIn(e, game_starttime - time + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e))); + Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e))); } float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode) @@ -873,7 +884,7 @@ LABEL(pickup) } }); e = RandomSelection_chosen_ent; - + Item_Show(e, 1); // reset its state so it is visible (extra sendflags doesn't matter, this happens anyway) } else e = this; @@ -959,7 +970,16 @@ float weapon_pickupevalfunc(entity player, entity item) return 0; return ammo_pickupevalfunc(player, item); } - return item.bot_pickupbasevalue; + + // reduce weapon value if bot already got a good arsenal + float c = 1; + int weapons_value = 0; + FOREACH(Weapons, it != WEP_Null && (player.weapons & it.m_wepset), { + weapons_value += it.bot_pickupbasevalue; + }); + c -= bound(0, weapons_value / 20000, 1) * 0.5; + + return item.bot_pickupbasevalue * c; } float ammo_pickupevalfunc(entity player, entity item) @@ -993,7 +1013,6 @@ float ammo_pickupevalfunc(entity player, entity item) switch(it.ammo_field) { - case ammo_shells: need_shells = true; break; case ammo_shells: need_shells = true; break; case ammo_nails: need_nails = true; break; case ammo_rockets: need_rockets = true; break; @@ -1005,51 +1024,53 @@ float ammo_pickupevalfunc(entity player, entity item) rating = item.bot_pickupbasevalue; } - if (need_shells) - if (item.ammo_shells) - if (player.ammo_shells < g_pickup_shells_max) - c = (player.ammo_shells + item.ammo_shells) / player.ammo_shells; - if (need_nails) - if (item.ammo_nails) - if (player.ammo_nails < g_pickup_nails_max) - c = (player.ammo_nails + item.ammo_nails) / player.ammo_nails; - if (need_rockets) - if (item.ammo_rockets) - if (player.ammo_rockets < g_pickup_rockets_max) - c = (player.ammo_rockets + item.ammo_rockets) / player.ammo_rockets; - if (need_cells) - if (item.ammo_cells) - if (player.ammo_cells < g_pickup_cells_max) - c = (player.ammo_cells + item.ammo_cells) / player.ammo_cells; - if (need_plasma) - if (item.ammo_plasma) - if (player.ammo_plasma < g_pickup_plasma_max) - c = (player.ammo_plasma + item.ammo_plasma) / player.ammo_plasma; - if (need_fuel) - if (item.ammo_fuel) - if (player.ammo_fuel < g_pickup_fuel_max) - c = (player.ammo_fuel + item.ammo_fuel) / player.ammo_fuel; - - rating *= min(3, c); + if ((need_shells) && (item.ammo_shells) && (player.ammo_shells < g_pickup_shells_max)) + c = item.ammo_shells / player.ammo_shells; + + if ((need_nails) && (item.ammo_nails) && (player.ammo_nails < g_pickup_nails_max)) + c = item.ammo_nails / player.ammo_nails; + + if ((need_rockets) && (item.ammo_rockets) && (player.ammo_rockets < g_pickup_rockets_max)) + c = item.ammo_rockets / player.ammo_rockets; + + if ((need_cells) && (item.ammo_cells) && (player.ammo_cells < g_pickup_cells_max)) + c = item.ammo_cells / player.ammo_cells; + + if ((need_plasma) && (item.ammo_plasma) && (player.ammo_plasma < g_pickup_plasma_max)) + c = item.ammo_plasma / player.ammo_plasma; + + if ((need_fuel) && (item.ammo_fuel) && (player.ammo_fuel < g_pickup_fuel_max)) + c = item.ammo_fuel / player.ammo_fuel; + + rating *= min(2, c); if(wpn) - // Skilled bots will grab more - rating += wpn.bot_pickupbasevalue * (0.1 + 0.1 * bound(0, skill / 10, 1)); + rating += wpn.bot_pickupbasevalue * 0.1; return rating; } +.int item_group; +.int item_group_count; float healtharmor_pickupevalfunc(entity player, entity item) { float c = 0; float rating = item.bot_pickupbasevalue; - if (item.armorvalue) - if (player.armorvalue < item.max_armorvalue) - c = (player.armorvalue + player.health + item.armorvalue) / (max(1, player.armorvalue + player.health)); - if (item.health) - if (player.health < item.max_health) - c = (player.health + item.health) / (max(1, player.health)); + float itemarmor = item.armorvalue; + float itemhealth = item.health; + + if(item.item_group) + { + itemarmor *= min(4, item.item_group_count); + itemhealth *= min(4, item.item_group_count); + } - rating *= min(3, c); + if (itemarmor && (player.armorvalue < item.max_armorvalue)) + c = itemarmor / max(1, player.armorvalue * 2/3 + player.health * 1/3); + + if (itemhealth && (player.health < item.max_health)) + c = itemhealth / max(1, player.health); + + rating *= min(2, c); return rating; } @@ -1079,6 +1100,9 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default this.item_model_ent = itemmodel; this.item_pickupsound_ent = pickupsound; + if(def.m_iteminit) + def.m_iteminit(this); + if(!this.respawntime) // both need to be set { this.respawntime = defaultrespawntime; @@ -1271,6 +1295,8 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default delete(this); return; } + + setItemGroup(this); } void StartItem(entity this, GameItem def) @@ -1283,18 +1309,63 @@ void StartItem(entity this, GameItem def) ); } +#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall)) +int group_count = 1; + +void setItemGroup(entity this) +{ + if(!IS_SMALL(this.itemdef)) + return; + + FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef), + { + if(!this.item_group) + { + if(!it.item_group) + { + it.item_group = group_count; + group_count++; + } + this.item_group = it.item_group; + } + else // spawning item is already part of a item_group X + { + if(!it.item_group) + it.item_group = this.item_group; + else if(it.item_group != this.item_group) // found an item near the spawning item that is part of a different item_group Y + { + int grY = it.item_group; + // move all items of item_group Y to item_group X + IL_EACH(g_items, IS_SMALL(it.itemdef), + { + if(it.item_group == grY) + it.item_group = this.item_group; + }); + } + } + }); +} + +void setItemGroupCount() +{ + for (int k = 1; k <= group_count; k++) + { + int count = 0; + IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { count++; }); + if (count) + IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; }); + } +} + spawnfunc(item_rockets) { - if(!this.ammo_rockets) - this.ammo_rockets = g_pickup_rockets; StartItem(this, ITEM_Rockets); } spawnfunc(item_bullets) { - if(!weaponswapping) - if(autocvar_sv_q3acompat_machineshotgunswap) - if(this.classname != "droppedweapon") + if(!weaponswapping && autocvar_sv_q3acompat_machineshotgunswap && + (this.classname != "droppedweapon")) { weaponswapping = true; spawnfunc_item_shells(this); @@ -1302,30 +1373,23 @@ spawnfunc(item_bullets) return; } - if(!this.ammo_nails) - this.ammo_nails = g_pickup_nails; StartItem(this, ITEM_Bullets); } spawnfunc(item_cells) { - if(!this.ammo_cells) - this.ammo_cells = g_pickup_cells; StartItem(this, ITEM_Cells); } spawnfunc(item_plasma) { - if(!this.ammo_plasma) - this.ammo_plasma = g_pickup_plasma; StartItem(this, ITEM_Plasma); } spawnfunc(item_shells) { - if(!weaponswapping) - if(autocvar_sv_q3acompat_machineshotgunswap) - if(this.classname != "droppedweapon") + if(!weaponswapping && autocvar_sv_q3acompat_machineshotgunswap && + (this.classname != "droppedweapon")) { weaponswapping = true; spawnfunc_item_bullets(this); @@ -1333,80 +1397,46 @@ spawnfunc(item_shells) return; } - if(!this.ammo_shells) - this.ammo_shells = g_pickup_shells; StartItem(this, ITEM_Shells); } spawnfunc(item_armor_small) { - if(!this.armorvalue) - this.armorvalue = g_pickup_armorsmall; - if(!this.max_armorvalue) - this.max_armorvalue = g_pickup_armorsmall_max; StartItem(this, ITEM_ArmorSmall); } spawnfunc(item_armor_medium) { - if(!this.armorvalue) - this.armorvalue = g_pickup_armormedium; - if(!this.max_armorvalue) - this.max_armorvalue = g_pickup_armormedium_max; StartItem(this, ITEM_ArmorMedium); } spawnfunc(item_armor_big) { - if(!this.armorvalue) - this.armorvalue = g_pickup_armorbig; - if(!this.max_armorvalue) - this.max_armorvalue = g_pickup_armorbig_max; StartItem(this, ITEM_ArmorBig); } spawnfunc(item_armor_mega) { - if(!this.armorvalue) - this.armorvalue = g_pickup_armormega; - if(!this.max_armorvalue) - this.max_armorvalue = g_pickup_armormega_max; StartItem(this, ITEM_ArmorMega); } spawnfunc(item_health_small) { - if(!this.max_health) - this.max_health = g_pickup_healthsmall_max; - if(!this.health) - this.health = g_pickup_healthsmall; StartItem(this, ITEM_HealthSmall); } spawnfunc(item_health_medium) { - if(!this.max_health) - this.max_health = g_pickup_healthmedium_max; - if(!this.health) - this.health = g_pickup_healthmedium; StartItem(this, ITEM_HealthMedium); } spawnfunc(item_health_big) { - if(!this.max_health) - this.max_health = g_pickup_healthbig_max; - if(!this.health) - this.health = g_pickup_healthbig; StartItem(this, ITEM_HealthBig); } spawnfunc(item_health_mega) { - if(!this.max_health) - this.max_health = g_pickup_healthmega_max; - if(!this.health) - this.health = g_pickup_healthmega; StartItem(this, ITEM_HealthMega); } @@ -1421,16 +1451,12 @@ spawnfunc(item_health100) { spawnfunc_item_health_mega(this); } spawnfunc(item_strength) { - if(!this.strength_finished) - this.strength_finished = autocvar_g_balance_powerup_strength_time; - StartItem(this, ITEM_Strength); + StartItem(this, ITEM_Strength); } spawnfunc(item_invincible) { - if(!this.invincible_finished) - this.invincible_finished = autocvar_g_balance_powerup_invincible_time; - StartItem(this, ITEM_Shield); + StartItem(this, ITEM_Shield); } // compatibility: @@ -1445,10 +1471,9 @@ void target_items_use(entity this, entity actor, entity trigger) return; } - if (!IS_PLAYER(actor)) - return; - if(IS_DEAD(actor)) + if (!IS_PLAYER(actor) || IS_DEAD(actor)) return; + if(trigger.solid == SOLID_TRIGGER) { EXACTTRIGGER_TOUCH(this, trigger); @@ -1465,7 +1490,7 @@ void target_items_use(entity this, entity actor, entity trigger) spawnfunc(target_items) { - int n, j; + int n; string s; this.use = target_items_use; @@ -1483,7 +1508,7 @@ spawnfunc(target_items) } else { - for(j = 0; j < n; ++j) + for(int j = 0; j < n; ++j) { if (argv(j) == "unlimited_ammo") this.items |= IT_UNLIMITED_AMMO; else if(argv(j) == "unlimited_weapon_ammo") this.items |= IT_UNLIMITED_WEAPON_AMMO; @@ -1567,7 +1592,7 @@ spawnfunc(target_items) //print(this.netname, "\n"); n = tokenize_console(this.netname); - for(j = 0; j < n; ++j) + for(int j = 0; j < n; ++j) { FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(argv(j)) == it.netname, { it.wr_init(it); @@ -1578,8 +1603,6 @@ spawnfunc(target_items) spawnfunc(item_fuel) { - if(!this.ammo_fuel) - this.ammo_fuel = g_pickup_fuel; StartItem(this, ITEM_JetpackFuel); } @@ -1595,8 +1618,6 @@ spawnfunc(item_fuel_regen) spawnfunc(item_jetpack) { - if(!this.ammo_fuel) - this.ammo_fuel = g_pickup_fuel_jetpack; if(start_items & ITEM_Jetpack.m_itemid) { spawnfunc_item_fuel(this); @@ -1896,7 +1917,11 @@ float GiveItems(entity e, float beginarg, float endarg) { .entity weaponentity = weaponentities[slot]; if(_switchweapon & BIT(slot)) - W_SwitchWeapon_Force(e, w_getbestweapon(e, weaponentity), weaponentity); + { + Weapon wep = w_getbestweapon(e, weaponentity); + if(wep != e.(weaponentity).m_switchweapon) + W_SwitchWeapon_Force(e, wep, weaponentity); + } } }