]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'bones_was_here/q3compat' into 'master'
authorMario <mario.mario@y7mail.com>
Fri, 10 Sep 2021 15:34:51 +0000 (15:34 +0000)
committerMario <mario.mario@y7mail.com>
Fri, 10 Sep 2021 15:34:51 +0000 (15:34 +0000)
Merge branch bones_was_here/q3compat

Closes #2465

See merge request xonotic/xonotic-data.pk3dir!849

1  2 
qcsrc/common/mutators/mutator/powerups/powerup/invisibility.qh
qcsrc/common/mutators/mutator/powerups/powerup/speed.qh
qcsrc/server/client.qc
qcsrc/server/items/items.qc
xonotic-server.cfg

index 8120b25457aa643f876583d5b1bc32c5350a463a,f4e59b58cf2e9be7314f7e23b62ac448474be554..d920aab9f22ed3cf8710e67501e19c054a01b5d2
@@@ -9,36 -9,26 +9,36 @@@
  #endif
  
  #ifdef GAMEQC
 -MODEL(Invisibility_ITEM, Item_Model("g_strength.md3"));
 +//MODEL(Invisibility_ITEM, Item_Model("g_strength.md3")); // TODO: new model required
  SOUND(Invisibility, Item_Sound("powerup"));
  #endif
  
  #ifdef SVQC
  .float invisibility_finished;
  
 +bool autocvar_g_powerups_invisibility = 1;
  float autocvar_g_balance_powerup_invisibility_alpha = 0.15;
  float autocvar_g_balance_powerup_invisibility_time = 30;
  void powerup_invisibility_init(Pickup this, entity item)
  {
      if(!item.invisibility_finished)
 -        item.invisibility_finished = autocvar_g_balance_powerup_invisibility_time;
 +        item.invisibility_finished = (item.count) ? item.count : autocvar_g_balance_powerup_invisibility_time;
  }
  #endif
  REGISTER_ITEM(Invisibility, Powerup) {
      this.m_canonical_spawnfunc = "item_invisibility";
 +#ifdef SVQC
 +    if(autocvar_g_powerups_invisibility)
 +        this.spawnflags = ITEM_FLAG_NORMAL;
 +    else
 +        this.spawnflags = ITEM_FLAG_MUTATORBLOCKED;
 +
 +    this.m_iteminit         =   powerup_invisibility_init;
 +#endif
  #ifdef GAMEQC
 -      this.spawnflags = ITEM_FLAG_MUTATORBLOCKED; // TODO: ITEM_FLAG_NORMAL (once it has a model!)
 -    this.m_model            =   MDL_Invisibility_ITEM;
 +    this.m_itemid           =   IT_INVISIBILITY;
 +    this.m_model            =   MDL_BUFF; // TODO: MDL_Invisibility_ITEM when new model available
 +    this.m_skin             =   12;
      this.m_sound            =   SND_Invisibility;
      this.m_glow             =   true;
      this.m_respawnsound     =   SND_STRENGTH_RESPAWN;
      this.m_color            =   '0.5 0.5 1';
      this.m_waypoint         =   _("Invisibility");
      this.m_waypointblink    =   2;
 -#ifdef GAMEQC
 -    this.m_itemid           =   IT_INVISIBILITY;
 -#endif
 -#ifdef SVQC
 -    this.m_iteminit         =   powerup_invisibility_init;
 -#endif
  }
  
  SPAWNFUNC_ITEM(item_invisibility, ITEM_Invisibility)
- // compat
- SPAWNFUNC_ITEM(item_invis, ITEM_Invisibility)
  
  CLASS(Invisibility, Powerups)
      ATTRIB(Invisibility, netname, string, "invisibility");
index 1f56bd0ad8ea68e2b66c83335208bb6db35ff1f6,fff1fd9b8c5a8ba34d6a8879fc36bfa7179260bf..5b71df8083bd88e45e698fb5b88d6c526280d984
@@@ -9,37 -9,27 +9,37 @@@
  #endif
  
  #ifdef GAMEQC
 -MODEL(Speed_ITEM, Item_Model("g_invincible.md3"));
 +//MODEL(Speed_ITEM, Item_Model("g_invincible.md3")); // TODO: new model required
  SOUND(Speed, Item_Sound("powerup_shield"));
  #endif
  
  #ifdef SVQC
  .float speed_finished;
  
 +bool autocvar_g_powerups_speed = 1;
  float autocvar_g_balance_powerup_speed_attackrate = 0.8;
  float autocvar_g_balance_powerup_speed_highspeed = 1.5;
  float autocvar_g_balance_powerup_speed_time = 30;
  void powerup_speed_init(Pickup this, entity item)
  {
      if(!item.speed_finished)
 -        item.speed_finished = autocvar_g_balance_powerup_speed_time;
 +        item.speed_finished = (item.count) ? item.count : autocvar_g_balance_powerup_speed_time;
  }
  #endif
  REGISTER_ITEM(Speed, Powerup) {
      this.m_canonical_spawnfunc = "item_speed";
 +#ifdef SVQC
 +    if(autocvar_g_powerups_speed)
 +        this.spawnflags = ITEM_FLAG_NORMAL;
 +    else
 +        this.spawnflags = ITEM_FLAG_MUTATORBLOCKED;
 +
 +    this.m_iteminit         =   powerup_speed_init;
 +#endif
  #ifdef GAMEQC
 -      this.spawnflags = ITEM_FLAG_MUTATORBLOCKED; // TODO: ITEM_FLAG_NORMAL (once it has a model!)
 -    this.m_model            =   MDL_Speed_ITEM;
 +    this.m_itemid           =   IT_SPEED;
 +    this.m_model            =   MDL_BUFF; // TODO: MDL_Speed_ITEM when new model available
 +    this.m_skin             =   9;
      this.m_sound            =   SND_Speed;
      this.m_glow             =   true;
      this.m_respawnsound     =   SND_SHIELD_RESPAWN;
      this.m_color            =   '0.1 1 0.84';
      this.m_waypoint         =   _("Speed");
      this.m_waypointblink    =   2;
 -#ifdef GAMEQC
 -    this.m_itemid           =   IT_SPEED;
 -#endif
 -#ifdef SVQC
 -    this.m_iteminit         =   powerup_speed_init;
 -#endif
  }
  
  SPAWNFUNC_ITEM(item_speed, ITEM_Speed)
- // compat
- SPAWNFUNC_ITEM(item_haste, ITEM_Speed)
- SPAWNFUNC_ITEM(item_scout, ITEM_Speed)
  
  CLASS(Speed, Powerups)
      ATTRIB(Speed, netname, string, "speed");
diff --combined qcsrc/server/client.qc
index dadc04b5bae7cda9766655e88f721ec846bd684f,69e416826174e1bd04397cfac2b4c1d8033e2f52..804025ace1e5efab8a88d140ff2db5808a72b2eb
@@@ -618,8 -618,7 +618,7 @@@ void PutPlayerInServer(entity this
        this.respawn_flags = 0;
        this.respawn_time = 0;
        STAT(RESPAWN_TIME, this) = 0;
-       bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox;
-       this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale);
+       this.scale = ((q3compat && autocvar_sv_q3compat_changehitbox) ? 0.9 : autocvar_sv_player_scale);
        this.fade_time = 0;
        this.pain_finished = 0;
        this.pushltime = 0;
@@@ -2643,30 -2642,14 +2642,30 @@@ void PlayerPostThink (entity this
                int totalClients = 0;
                if(autocvar_sv_maxidle > 0 && autocvar_sv_maxidle_slots > 0)
                {
 -                      FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_maxidle_slots_countbots,
 +                      // maxidle disabled in local matches by not counting clients (totalClients 0)
 +                      if (server_is_dedicated)
 +                      {
 +                              FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_maxidle_slots_countbots,
 +                              {
 +                                      ++totalClients;
 +                              });
 +                              if (maxclients - totalClients > autocvar_sv_maxidle_slots)
 +                                      totalClients = 0;
 +                      }
 +              }
 +              else if (IS_PLAYER(this) && autocvar_sv_maxidle_playertospectator > 0)
 +              {
 +                      FOREACH_CLIENT(IS_REAL_CLIENT(it),
                        {
                                ++totalClients;
                        });
                }
  
 -              if (autocvar_sv_maxidle > 0 && autocvar_sv_maxidle_slots > 0 && (maxclients - totalClients) > autocvar_sv_maxidle_slots)
 -              { /* do nothing */ }
 +              if (totalClients < autocvar_sv_maxidle_minplayers)
 +              {
 +                      // idle kick disabled
 +                      CS(this).parm_idlesince = time;
 +              }
                else if (time - CS(this).parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
                {
                        if (CS(this).idlekick_lasttimeleft)
index db9b3fece9609190313bf71a0693cf062ff8212d,7408b4de8f7ab7dadbd6aa9e557a9e7a78a85bd4..932db7a553dd2f663c7a1549d15cfa52f54d160c
@@@ -63,9 -63,9 +63,9 @@@ bool ItemSend(entity this, entity to, i
                        LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
  
                WriteString(MSG_ENTITY, this.mdl);
 +              WriteByte(MSG_ENTITY, bound(0, this.skin, 255));
        }
  
 -
        if(sf & ISF_COLORMAP)
        {
                WriteShort(MSG_ENTITY, this.colormap);
@@@ -551,42 -551,22 +551,42 @@@ bool Item_GiveTo(entity item, entity pl
        if (item.strength_finished)
        {
                pickedup = true;
 -              StatusEffects_apply(STATUSEFFECT_Strength, player, max(StatusEffects_gettime(STATUSEFFECT_Strength, player), time) + item.strength_finished, 0);
 +              float t = max(StatusEffects_gettime(STATUSEFFECT_Strength, player), time);
 +              if (autocvar_g_powerups_stack)
 +                      t += item.strength_finished;
 +              else
 +                      t = max(t, time + item.strength_finished);
 +              StatusEffects_apply(STATUSEFFECT_Strength, player, t, 0);
        }
        if (item.invincible_finished)
        {
                pickedup = true;
 -              StatusEffects_apply(STATUSEFFECT_Shield, player, max(StatusEffects_gettime(STATUSEFFECT_Shield, player), time) + item.invincible_finished, 0);
 +              float t = max(StatusEffects_gettime(STATUSEFFECT_Shield, player), time);
 +              if (autocvar_g_powerups_stack)
 +                      t += item.invincible_finished;
 +              else
 +                      t = max(t, time + item.invincible_finished);
 +              StatusEffects_apply(STATUSEFFECT_Shield, player, t, 0);
        }
        if (item.speed_finished)
        {
                pickedup = true;
 -              StatusEffects_apply(STATUSEFFECT_Speed, player, max(StatusEffects_gettime(STATUSEFFECT_Speed, player), time) + item.speed_finished, 0);
 +              float t = max(StatusEffects_gettime(STATUSEFFECT_Speed, player), time);
 +              if (autocvar_g_powerups_stack)
 +                      t += item.speed_finished;
 +              else
 +                      t = max(t, time + item.speed_finished);
 +              StatusEffects_apply(STATUSEFFECT_Speed, player, t, 0);
        }
        if (item.invisibility_finished)
        {
                pickedup = true;
 -              StatusEffects_apply(STATUSEFFECT_Invisibility, player, max(StatusEffects_gettime(STATUSEFFECT_Invisibility, player), time) + item.invisibility_finished, 0);
 +              float t = max(StatusEffects_gettime(STATUSEFFECT_Invisibility, player), time);
 +              if (autocvar_g_powerups_stack)
 +                      t += item.invisibility_finished;
 +              else
 +                      t = max(t, time + item.invisibility_finished);
 +              StatusEffects_apply(STATUSEFFECT_Invisibility, player, t, 0);
        }
        if (item.superweapons_finished)
        {
@@@ -1057,19 -1037,19 +1057,19 @@@ void _StartItem(entity this, entity def
  
                if(autocvar_spawn_debug >= 2)
                {
-             // why not flags & fl_item?
-                   FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
-                 LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
-                 LOG_TRACE(" vs ", it.netname, vtos(it.origin));
-                 error("Mapper sucks.");
-             });
+                       // why not flags & fl_item?
+                       FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
+                               LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
+                               LOG_TRACE(" vs ", it.netname, vtos(it.origin));
+                               error("Mapper sucks.");
+                       });
                        this.is_item = true;
                }
  
                weaponsInMap |= WepSet_FromWeapon(REGISTRY_GET(Weapons, weaponid));
  
-               if (   def.instanceOfPowerup
-                       || def.instanceOfWeaponPickup
+               if (        def.instanceOfPowerup
+                       ||  def.instanceOfWeaponPickup
                        || (def.instanceOfHealth && def != ITEM_HealthSmall)
                        || (def.instanceOfArmor && def != ITEM_ArmorSmall)
                        || (itemid & (IT_KEY1 | IT_KEY2))
        setmodel(this, MDL_Null); // precision set below
        //this.effects |= EF_LOWPRECISION;
  
 +      // support skinned models for powerups
 +      this.skin = def.m_skin;
 +      this.glowmod = def.m_color;
 +
        setsize (this, this.pos1 =  def.m_mins, this.pos2 = def.m_maxs);
  
        this.SendFlags |= ISF_SIZE;
  
  void StartItem(entity this, GameItem def)
  {
-     def = def.m_spawnfunc_hookreplace(def, this);
-     if (def.spawnflags & ITEM_FLAG_MUTATORBLOCKED)
-     {
-         delete(this);
-         return;
-     }
-     this.classname = def.m_canonical_spawnfunc;
-     _StartItem(
-       this,
-       this.itemdef = def,
-       def.m_respawntime(), // defaultrespawntime
-       def.m_respawntimejitter() // defaultrespawntimejitter
+       def = def.m_spawnfunc_hookreplace(def, this);
+       if (def.spawnflags & ITEM_FLAG_MUTATORBLOCKED)
+       {
+               delete(this);
+               return;
+       }
+       this.classname = def.m_canonical_spawnfunc;
+       _StartItem(
+               this,
+               this.itemdef = def,
+               def.m_respawntime(), // defaultrespawntime
+               def.m_respawntimejitter() // defaultrespawntimejitter
        );
  }
  
diff --combined xonotic-server.cfg
index a6213cb24a48b6b13ce159ede2f57592c8d416f1,61ba473dd024870b85b43ed2fd773be7b2f6bd66..1634c256cca1102ea23f05da17e097a0b37bc016
@@@ -197,12 -197,7 +197,12 @@@ set g_shootfromcenter 0 "weapon gets mo
  set g_shootfromfixedorigin "" "if set to a string like 0 y z, the gun is moved to the given y and z coordinates. If set to a string like x y z, the whole shot origin is used"
  set g_weapon_stay 0 "1: ghost weapons can be picked up but give no ammo, thrown guns have ammo 2: ghost weapons can be picked up and refill ammo to one pickup size, thrown guns have no ammo (to prevent infinite ammo abuse)"
  set g_weapon_throwable 1 "if set to 1, weapons can be dropped"
 -set g_powerups -1 "if set to 0 the strength and shield (invincibility) will not spawn on the map, if 1 they will spawn in all game modes, -1 is game mode default"
 +set g_powerups -1 "if set to 0 no powerups will spawn, if 1 they will spawn in all game modes, -1 is game mode default"
 +set g_powerups_stack 0 "enables stacking of powerup timers when picking up a powerup you already have; otherwise timer is reset to the time granted by the item, if greater than the time you currently have"
 +set g_powerups_strength 1 "allow strength powerups to spawn"
 +set g_powerups_shield 1 "allow shield powerups to spawn"
 +set g_powerups_speed 1 "allow speed powerups to spawn"
 +set g_powerups_invisibility 1 "allow invisibility powerups to spawn"
  set g_use_ammunition 1 "if set to 0 all weapons have unlimited ammo"
  set g_pickup_items -1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map, if 1 they are forced to spawn"
  set g_pickup_respawntime_scaling_reciprocal 0 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to 0) can be used to achieve a constant number of items spawned *per player*"
@@@ -418,7 -413,7 +418,7 @@@ set sv_maxidle 0 "kick players idle fo
  set sv_maxidle_alsokickspectators 1 "when sv_maxidle is > 0, kick idle spectators as well as players"
  set sv_maxidle_slots 0 "when not 0, only kick idlers when this many or less player slots are available"
  set sv_maxidle_slots_countbots 1 "count bots as player slots"
 -
 +set sv_maxidle_minplayers 2 "check for idlers only when there are at least this many players (only in dedicated servers)"
  set sv_maxidle_playertospectator 60 "move players idle for more than this amount of time in seconds to spectators (sv_maxidle timer starts again after sv_maxidle_playertospectator has moved a player to spectators)"
  
  sv_allowdownloads_inarchive 1 // for csprogs.dat
@@@ -499,8 -494,7 +499,7 @@@ sv_gameplayfix_consistentplayerprethin
  sv_gameplayfix_gravityunaffectedbyticrate 1
  sv_gameplayfix_nogravityonground 1
  
- set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)"
- set sv_q3defragcompat 0 "toggle for some compatibility hacks (for Q3DF map compatibility)"
+ set sv_q3compat_changehitbox 0 "use Q3 player hitbox dimensions and camera height on Q3 maps (maps with an entry in a .arena or .defi file)
  
  set g_movement_highspeed 1 "multiplier scale for movement speed (applies to sv_maxspeed and sv_maxairspeed, also applies to air acceleration when g_movement_highspeed_q3_compat is set to 0)"
  set g_movement_highspeed_q3_compat 0 "apply speed modifiers to air movement in a more Q3-compatible way (only apply speed buffs and g_movement_highspeed to max air speed, not to acceleration)"