Avoid teleporting of Queens

Discussions about Coding and Scripting

Avoid teleporting of Queens

Postby Barbie » Tue Jun 12, 2018 9:38 pm

I tried to avoid teleporting Queens. The only parts where a Queen goes into State Teleporting are the following state functions in the code of Queen:
Code: Select all
state TacticalMove
{
ignores SeePlayer, HearNoise;

   function PickDestination(bool bNoCharge)
   {
      if ( FRand() < 0.26 )
         GotoState('Teleporting');
      else
         Super.PickDestination(bNoCharge);
   }
}

state Hunting
{
ignores EnemyNotVisible;

   function PickDestination()
   {
      GotoState('Teleporting');
   }
}
I changed that to
Code: Select all
state TacticalMove
{
ignores SeePlayer, HearNoise;

   function PickDestination(bool bNoCharge)
   {
      if ((FRand() < 0.26) && bHaveQueenDests)
         GotoState('Teleporting');
      else
         Super.PickDestination(bNoCharge);
   }
}


state Hunting
{
ignores EnemyNotVisible;

   function PickDestination()
   {
      if (bHaveQueenDests)
         GotoState('Teleporting');
      else
         Super.PickDestination();
   }
}
and although bHaveQueenDests is false, the Queen can teleport.

Any hints?
Attachments
TestQueenTelefrag3.unr.7z
Queen teleport test map
(5.39 KiB) Downloaded 26 times
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
Barbie
Godlike
 
Posts: 1497
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Avoid teleporting of Queens

Postby MrLoathsome » Tue Jun 12, 2018 10:31 pm

Change these lines: GotoState('Teleporting');

To: GotoState('Wandering'); or GotoState('Roaming'); or GotoState('Attacking');* *maybe
(maybe lose the check on bHaveQueenDests)
Let us know what happens...
blarg
MrLoathsome
Inhuman
 
Posts: 956
Joined: Wed Mar 31, 2010 9:02 pm
Location: MrLoathsome fell out of the world!
Personal rank: I am quite rank.

Re: Avoid teleporting of Queens

Postby Barbie » Tue Jun 12, 2018 11:19 pm

MrLoathsome wrote:Change these lines: GotoState('Teleporting');
Same result: Queens are still teleporting.

They stop teleporting, if I use empty state functions for PickDestination(). So State Teleporting it must be entered in Super.PickDestination().
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
Barbie
Godlike
 
Posts: 1497
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Avoid teleporting of Queens

Postby sektor2111 » Wed Jun 13, 2018 6:19 am

In some package NsMonster, queen was disturbing. What I did step by step I cannot entirely recall right now but definitely I recall that I was looking everywhere about string
GoToState('Teleporting'), but EVERYWHERE in code Including Hunting. Definitely when Queen doesn't see enemy it should stay the hell in place else it does dumb shit with that encroachment. As I could see so far, even in "nice" XC deal a map still went broken (counted queens have vaporized) so I disabled the fix (using that Configurable UScript part of XCGE - posted by me) and I left the "original" code to run but I think next days worth a small revision here. I could see if Queen is busy with an enemy not visible and camping (Bot Stackout or such), it will be invulnerable and visible closer enemies will exhaust ammo firing weaponry USELESS. This stupidity will be removed, I might think at checking pawns around would have a benefit from time time and getting a new enemy rather than stupidly teleporting awaiting enemy to show up - probably this code won't be net compatible so maybe the first solution is more suitable here... unless a sort of new XC_Stuff like that DripGenerator and XC_Titans will have compatibility and code will be executed from a better Queen, for sure it will be required to be permanent, even for maps which don't have queens but factories spawning them - there also will be a master tweak, slowing to 1 QUEEN per row, capturing potential counters and capping values. There is still work to do here - maps patching or common code...

Presumed fixing situation:
Queen wants a QueenDest closer to visible pawn enemy. If there is None, then Stackout as other monster if cannot see enemy else it will be RANGEDATTACK. If did not see any enemy for a while (LastSeenTime or such), Enemy - None (OldEnemy - None) WhatToDoNext - DONE. By dropping queen here and there is not an answer, if Queen is a guardian will leave guarding spot and chances to go back are probably NONE due to it's size and "fascinating" paths which mapper is doing, so excuse me but Teleporting to a PathNode is not the solution here and neither dropping it behind a door/wall.
Another "fix":
Leave all code and Do NOT Ignore TakeDamage in state Teleporting - has to be well tested...

Edit: A bit concerning what is in state Teleporting
Code: Select all
ignores TakeDamage, SeePlayer, EnemyNotVisible, HearNoise, KilledBy, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, Died;
Ignoring Died and KilledBy ? In my opinion This state is not finished. I'm not surprised to see that it breaks events then... I think is removed skipping the most important things...
User avatar
sektor2111
Godlike
 
Posts: 3521
Joined: Sun May 09, 2010 6:15 pm
Location: vect(1,1,1)

Re: Avoid teleporting of Queens

Postby Barbie » Sun Jun 17, 2018 2:27 am

Meanwhile I have found out why my sub classed Queen teleports: I defined it as
Code: Select all
class QueenSB expands Queen;
and then I call
Code: Select all
Super.PickDestination(bNoCharge);
what executes the original Queen's code - including teleporting. Maybe I was too tired when I did that... :roll:


But the next problem follows: now I want to skip original Queen's state function and execute Queen's parent state function instead. The code for this should be
Code: Select all
Super(ScriptedPawn).PickDestination(bNoCharge)
and I did that with QueenSB in state "TacticalMove" (see full code below). But the compiler says Unknown function 'PickDestination' in Class UnrealShare.ScriptedPawn - but ScriptedPawn has a function "PickDestination" in state "TacticalMove". How to tell the compiler my wish?

Appendix:
Full code
Code: Select all
class QueenSB expands Queen;

var() bool bHaveQueenDests;

state TacticalMove
{
ignores SeePlayer, HearNoise;

   function PickDestination(bool bNoCharge)
   {
      if ((FRand() < 0.26) && bHaveQueenDests)
         GotoState('Teleporting');
// This does not compile:
      else
         Super(ScriptedPawn).PickDestination(bNoCharge);
   }
}
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
Barbie
Godlike
 
Posts: 1497
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Avoid teleporting of Queens

Postby MrLoathsome » Sun Jun 17, 2018 4:33 am

Copy ALL the Queen source into your QueenSB.Queen class.
Have your QueenSB.Queen Class extend ScriptedPawn.

Then change PickDestination as needed.
Last edited by MrLoathsome on Mon Jun 18, 2018 4:23 pm, edited 1 time in total.
blarg
MrLoathsome
Inhuman
 
Posts: 956
Joined: Wed Mar 31, 2010 9:02 pm
Location: MrLoathsome fell out of the world!
Personal rank: I am quite rank.

Re: Avoid teleporting of Queens

Postby sektor2111 » Sun Jun 17, 2018 7:37 am

Barbie wrote:But the next problem follows: now I want to skip original Queen's state function and execute Queen's parent state function instead.
That was/is the same problem from "Humane" repeating Trooper code (and spawning 2 weapons not one) because of Super.CrapFunction() called. All these are things doable >>
CASE1) as follows:
- USE ALL code from ScriptedPawn and never call Super in here. This Super in such case will not prevent original Queen to mess the new class... and will prevent ruining mutators using "IsA('Queen')" magic code... :|
Case2)
- rewrite Queen from UnrealI and conform package with the stock from year 2000 whatever UT436, and... forget new bHasQueenDest variable. It won't help you. Recommending in state Hunting to put a random or a visual condition WITHOUT any new bool. Else, return Hunting to some attack if QueenDest from NavigationPointList is None so to speak there is no such destination available (because mapper was paying for stuff and did not have money for it :loool: ), also preventing mutators to mess with another "Queen". Here you can adjust those stupid collision values as well probably speeding up collision processing - lol, EPIC...

Edit:
Reason. Some stock different Queen which I have to test intensive according to code bellow:
Code: Select all
//=============================================================================
// Queen.
//=============================================================================
class Queen expands ScriptedPawn;

#exec MESH IMPORT MESH=SkQueen ANIVFILE=MODELS\queen_a.3D DATAFILE=MODELS\queen_d.3D X=0 Y=0 Z=0
#exec MESH ORIGIN MESH=SkQueen X=0 Y=-130 Z=80 YAW=64 ROLL=-64

#exec MESH SEQUENCE MESH=Skqueen SEQ=All      STARTFRAME=0   NUMFRAMES=171
#exec MESH SEQUENCE MESH=Skqueen SEQ=ThreeHit   STARTFRAME=0   NUMFRAMES=18   RATE=15  Group=Attack
#exec MESH SEQUENCE MESH=Skqueen SEQ=Claw      STARTFRAME=18   NUMFRAMES=10   RATE=15  Group=Attack
#exec MESH SEQUENCE MESH=Skqueen SEQ=Gouge      STARTFRAME=28   NUMFRAMES=13   RATE=15  Group=Attack
#exec MESH SEQUENCE MESH=Skqueen SEQ=Jump      STARTFRAME=41   NUMFRAMES=1
#exec MESH SEQUENCE MESH=Skqueen SEQ=Land      STARTFRAME=42   NUMFRAMES=1
#exec MESH SEQUENCE MESH=Skqueen SEQ=Meditate   STARTFRAME=43   NUMFRAMES=8      RATE=6
#exec MESH SEQUENCE MESH=Skqueen SEQ=OutCold   STARTFRAME=51   NUMFRAMES=21   RATE=15
#exec MESH SEQUENCE MESH=Skqueen SEQ=TakeHit   STARTFRAME=52   NUMFRAMES=1
#exec MESH SEQUENCE MESH=Skqueen SEQ=Run      STARTFRAME=72   NUMFRAMES=10   RATE=17
#exec MESH SEQUENCE MESH=Skqueen SEQ=Scream      STARTFRAME=82   NUMFRAMES=23   RATE=15
#exec MESH SEQUENCE MESH=Skqueen SEQ=Fighter   STARTFRAME=105  NUMFRAMES=1
#exec MESH SEQUENCE MESH=Skqueen SEQ=Shoot1      STARTFRAME=105  NUMFRAMES=23   RATE=15  Group=Attack
#exec MESH SEQUENCE MESH=Skqueen SEQ=Stab      STARTFRAME=128  NUMFRAMES=8      RATE=15  Group=Attack
#exec MESH SEQUENCE MESH=Skqueen SEQ=Walk      STARTFRAME=136  NUMFRAMES=15   RATE=17
#exec MESH SEQUENCE MESH=Skqueen SEQ=Shield      STARTFRAME=151  NUMFRAMES=20   RATE=25


#exec TEXTURE IMPORT NAME=JQueen1 FILE=MODELS\queen.PCX GROUP=Skins
#exec MESHMAP SCALE MESHMAP=Skqueen X=0.22 Y=0.22 Z=0.44
#exec MESHMAP SETTEXTURE MESHMAP=Skqueen NUM=1 TEXTURE=Jqueen1

#exec MESH NOTIFY MESH=Skqueen SEQ=Shoot1 TIME=0.167 FUNCTION=SpawnShot
#exec MESH NOTIFY MESH=Skqueen SEQ=Shoot1 TIME=0.255 FUNCTION=SpawnShot
#exec MESH NOTIFY MESH=Skqueen SEQ=Shoot1 TIME=0.344 FUNCTION=SpawnShot
#exec MESH NOTIFY MESH=Skqueen SEQ=Shoot1 TIME=0.433 FUNCTION=SpawnShot
#exec MESH NOTIFY MESH=Skqueen SEQ=OutCold TIME=0.60 FUNCTION=LandThump
#exec MESH NOTIFY MESH=Skqueen SEQ=Claw   TIME=0.5   FUNCTION=ClawDamageTarget
#exec MESH NOTIFY MESH=Skqueen SEQ=Gouge  TIME=0.4   FUNCTION=ClawDamageTarget
#exec MESH NOTIFY MESH=Skqueen SEQ=Stab   TIME=0.33  FUNCTION=StabDamageTarget
#exec MESH NOTIFY MESH=Skqueen SEQ=Walk   TIME=0.26  FUNCTION=FootStep
#exec MESH NOTIFY MESH=Skqueen SEQ=Walk   TIME=0.76  FUNCTION=FootStep
#exec MESH NOTIFY MESH=Skqueen SEQ=Run    TIME=0.25  FUNCTION=FootStep
#exec MESH NOTIFY MESH=Skqueen SEQ=Run    TIME=0.75  FUNCTION=FootStep
#exec MESH NOTIFY MESH=Skqueen SEQ=Shield TIME=0.75  FUNCTION=SpawnShield

#exec AUDIO IMPORT FILE="Sounds\Queen\claw1Q.WAV" NAME="claw1Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\shoot1Q.WAV" NAME="shoot1Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\yell1Q.WAV" NAME="yell1Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\yell2Q.WAV" NAME="yell2Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\yell3Q.WAV" NAME="yell3Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\stab1Q.WAV" NAME="stab1Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\outcoldQ.WAV" NAME="outcoldQ" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\nearby2Q.WAV" NAME="nearby2Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Queen\amb1Q.WAV" NAME="amb1Q" GROUP="Queen"
#exec AUDIO IMPORT FILE="Sounds\Titan\step1a.WAV" NAME="step1t" GROUP="Titan"
#exec AUDIO IMPORT FILE="..\UnrealShare\Sounds\Generic\teleport1.WAV" NAME="Teleport1" GROUP="Generic"

//Queen variables;
var() int ClawDamage,
   StabDamage;
var() name ScreamEvent;

var byte row;
var(Sounds) sound footstepSound;
var(Sounds) sound ScreamSound;
var(Sounds) sound stab;
var(Sounds) sound shoot;
var(Sounds) sound claw;

var bool   bJustScreamed;
var bool   bEndFootStep;
var QueenShield Shield;
var vector TelepDest;

function PostBeginPlay()
{
   Super.PostBeginPlay();
   ProjectileSpeed = 1200 + 100 * Skill;
   GroundSpeed = GroundSpeed * (1 + 0.1 * Skill);
}

event bool EncroachingOn( actor Other )
{
   return Super(Pawn).EncroachingOn(Other);
   return false;
}

function TryToDuck(vector duckDir, bool bReversed)
{
   if ( (Shield != None) || (AnimSequence == 'Shield') )
      return;

   PlayAnim('Shield', 1.0, 0.1);
   bCrouching = true;
   GotoState('RangedAttack', 'Challenge');
}

function SpawnShield()
{
   Shield = Spawn(class'QueenShield',,,Location + 150 * Vector(Rotation));
   Shield.SetBase(self);
}

function eAttitude AttitudeToCreature(Pawn Other)
{
   if ( Other == None || Other.bDeleteMe )
      return ATTITUDE_Friendly;

   if ( Other.IsA('Skaarj') )
   {
      if ( Other.IsA('SkaarjBerserker') )
         return ATTITUDE_Hate;
      else
         return ATTITUDE_Friendly;
   }
   else if ( Other.IsA('Pupae') )
      return ATTITUDE_Friendly;
   else if ( Other.IsA('Nali') )
      return ATTITUDE_Hate;
   else
      return ATTITUDE_Ignore;
}

function ThrowOther(Pawn Other)
{
   local float dist, shake;
   local PlayerPawn aPlayer;
   local vector Momentum;

   if ( Other.mass > 500 || Other == None || Other.bDeleteMe || Other.Health <= 0 )
      return;

   aPlayer = PlayerPawn(Other);            
   if (aPlayer == None)
   {   
      if (Other.Physics != PHYS_Walking)
         return;
      dist = VSize(Location - Other.Location);
      if (dist > 500)
         return;
   }
   else
   {
      dist = VSize(Location - Other.Location);
      shake = FMax(500, 1500 - dist);
      if ( dist > 1500 )
         return;
      aPlayer.ShakeView( FMax(0, 0.35 - dist/20000), shake, 0.015 * shake);
      if ( (Other.Physics != PHYS_Walking) || (dist > 1500) )
         return;
   }
   
   Momentum = -0.5 * Other.Velocity + 100 * Normal(Other.Location - Location);
   Momentum.Z =  7000000.0/((0.5 * dist + 500) * Other.Mass);
   Other.AddVelocity(Momentum);
}

function FootStep()
{
   bEndFootstep = false;
   PlaySound(FootstepSound, SLOT_Interact, 8);
}

function Scream()
{
   local actor A;
   local pawn Thrown;

   if (ScreamEvent != '')
      foreach AllActors( class 'Actor', A, ScreamEvent )
         A.Trigger( Self, Instigator );

   PlaySound(ScreamSound, SLOT_Talk, 2 * TransientSoundVolume);
   PlaySound(ScreamSound, SLOT_None, 2 * TransientSoundVolume);
/*
   Stopping this stupidity
*/
//   PlaySound(ScreamSound, SLOT_None, 2 * TransientSoundVolume);
//   PlaySound(ScreamSound, SLOT_None, 2 * TransientSoundVolume);
   PlayAnim('Scream');
   bJustScreamed = true;
}

function PlayWaiting()
{
   local float decision;
   local float animspeed;
   
   if (bEndFootStep)
      FootStep();
   decision = FRand();
   animspeed = 0.2 + 0.5 * FRand();
   LoopAnim('Meditate', animspeed);
}

function PlayChallenge()
{
   if (bEndFootStep)
      FootStep();
   if ( IsAnimating() && (AnimSequence == 'Shield') )
      return;
   Scream();
}

function TweenToFighter(float tweentime)
{
   bEndFootStep = ( ((AnimSequence == 'Walk') || (AnimSequence == 'Run')) && (AnimFrame > 0.1) );   
   TweenAnim('Fighter', tweentime);
}

function TweenToRunning(float tweentime)
{
   if ( (AnimSequence != 'Run') || !bAnimLoop )
      TweenAnim('Run', tweentime);
}

function TweenToWalking(float tweentime)
{
   TweenAnim('Walk', tweentime);
}

function TweenToWaiting(float tweentime)
{
   TweenAnim('Meditate', tweentime);
}

function TweenToPatrolStop(float tweentime)
{
   TweenAnim('Meditate', tweentime);
}

function PlayRunning()
{
   LoopAnim('Run', -1.0/GroundSpeed,, 0.8);
}

function PlayWalking()
{
   LoopAnim('Walk', -1.0/GroundSpeed,, 0.8);
}

function PlayThreatening()
{
   DesiredSpeed = 0.0;

   if ( FRand() < 0.75)
      PlayAnim('Meditate', 0.4 + 0.6 * FRand(), 0.3);
   else
   {
      TweenAnim('Fighter', 0.3);
      PlayThreateningSound();
   }
}

function PlayTurning()
{
   if (bEndFootStep)
      FootStep();
   DesiredSpeed = 0.0;
   TweenAnim('Run', 0.4);
}

function PlayDying(name DamageType, vector HitLocation)
{
   PlayAnim('OutCold', 0.7, 0.1);
   PlaySound(Die, SLOT_Talk);   
}

function PlayTakeHit(float tweentime, vector HitLoc, int Damage)
{
   TweenAnim('TakeHit', tweentime);
}

function SpawnShot()
{
   local vector X,Y,Z, projStart;

   GetAxes(Rotation,X,Y,Z);
   
   if (row == 0)
      MakeNoise(1.0);
   
   projStart = Location + 1 * CollisionRadius * X + ( 0.7 - 0.2 * row) * CollisionHeight * Z + 0.2 * CollisionRadius * Y;
   spawn(RangedProjectile ,self,'',projStart,AdjustAim(ProjectileSpeed, projStart, 400 * (4 - row)/(3.5-skill), false, bWarnTarget));

   projStart = Location + 1 * CollisionRadius * X + ( 0.7 - 0.2 * row) * CollisionHeight * Z - 0.2 * CollisionRadius * Y;
   spawn(RangedProjectile ,self,'',projStart,AdjustAim(ProjectileSpeed, projStart, 400 * (4 - row)/(3.5-skill), true, bWarnTarget));
   row++;
}

function PlayVictoryDance()
{
   if (bEndFootStep)
      FootStep();
   DesiredSpeed = 0.0;
   PlayAnim('ThreeHit', 0.7, 0.15); //gib the enemy here!
   PlaySound(Threaten, SLOT_Talk);      
}

function ClawDamageTarget()
{
   if ( Target != None )
      if ( MeleeDamageTarget(ClawDamage, (50000.0 * (Normal(Target.Location - Location)))) )
         PlaySound(Claw, SLOT_Interact);
}

function StabDamageTarget()
{
   local vector X,Y,Z;

   if ( Target != None )
   {
      GetAxes(Rotation,X,Y,Z);
      if ( MeleeDamageTarget(StabDamage, (15000.0 * ( Y + vect(0,0,1)))) )
         PlaySound(Stab, SLOT_Interact);
   }
}

function PlayMeleeAttack()
{
   local float decision;

   if (bEndFootStep)
      FootStep();
   decision = FRand();
   if (decision < 0.4)
   {
      PlaySound(Stab, SLOT_Interact);
      PlayAnim('Stab');
   }
   else if (decision < 0.7)
   {
      PlaySound(Claw, SLOT_Interact);
      PlayAnim('Claw');
   }
   else
   {
      PlaySound(Claw, SLOT_Interact);
      PlayAnim('Gouge');
   }
}

function TweenToFalling()
{
   TweenAnim('Jump', 0.2);
}

function PlayInAir()
{
   TweenAnim('Jump', 0.5);
}

function PlayLanded(float impactVel)
{
   local Pawn Thrown;

   TweenAnim('Land', 0.1);

   //throw all nearby creatures, and play sound
   Thrown = Level.PawnList;
   While ( Thrown != None )
   {
      ThrowOther(Thrown);
      Thrown = Thrown.nextPawn;
   }
}

function PlayRangedAttack()
{
   if (Target != None)
   {
      if (bEndFootStep)
         FootStep();

      if ( !bJustScreamed && (FRand() < 0.15) )
         Scream();
      else if ( (Shield != None) && (FRand() < 0.5)
         && (((Target.Location - Location) Dot (Shield.Location - Location)) > 0) )
         Scream();
      else
      {
         if ( Shield != None )
            Shield.Destroy();
         row = 0;
         bJustScreamed = false;
         PlayAnim('Shoot1');
         PlaySound(Shoot, SLOT_Interact);         
      }
   }
}

state TacticalMove
{
ignores SeePlayer, HearNoise;

   function PickDestination(bool bNoCharge)
   {
      if ( FRand() < 0.26 )
         GotoState('Teleporting');
      else
         Super.PickDestination(bNoCharge);
   }
}      
      
state Hunting
{
ignores EnemyNotVisible;

   function PickDestination()
   {
      if ( (Enemy == Self) || (Enemy == None) || (Enemy.Health <= 0) || (Enemy.bDeleteMe) )
      {
         WhatToDoNext('','');
         return;
      }
      if ( LineOfSightTo(Enemy) )
      {
         GotoState('RangedAttack','Challenge');
         return;
      }
      if ( FRand() < 0.2 )
         GotoState('Teleporting');
      else
         Super.PickDestination();
   }
}


State Teleporting
{
ignores TakeDamage, SeePlayer, EnemyNotVisible, HearNoise, /*KilledBy,*/ Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget /*, Died*/;

   function Tick(float DeltaTime)
   {
      local int NewFatness;
      local rotator EnemyRot;

      if ( TelepDest == Location || ( FRand() > 0.5 && Enemy != None && !LineOfSightTo(Enemy) ) ) //50% chances to NOT go retarded or do nothing if destination is the same location - NO QueenDest HERE
      {
         GoToState('RangedAttack','Challenge');
         return;
      }
/*
To check: checking if dealing with Style is helpful - OR NOT
*/
      if ( Style == STY_Translucent )
      {
         ScaleGlow -= 3 * DeltaTime;
         if ( ScaleGlow < 0.3 )
         {
            Spawn(class'QueenTeleportEffect',,, TelepDest);
            Spawn(class'QueenTeleportLight',,, TelepDest);
            EnemyRot = rotator(Enemy.Location - Location);
            EnemyRot.Pitch = 0;
            if ( TelepDest != Location ) //No need to teleport in the same location - only if it's not already there, geniuses !
               SetLocation(TelepDest);
            setRotation(EnemyRot);
            PlaySound(sound'Teleport1', SLOT_Interface);
            GotoState('Attacking');
         }
         return;
      }
      else
      {
         NewFatness = fatness - 100 * DeltaTime;
         if ( NewFatness < 80 )
         {
            bUnlit = true;
            ScaleGlow = 2.0;
            Style = STY_Translucent;
         }
      }

      fatness = Clamp(NewFatness, 0, 255);
   }

   function ChooseDestination()
   {
      local NavigationPoint N;
      local vector ViewPoint, HitLocation, HitNormal, Best;
      local actor HitActor;
      local float rating, newrating;

      N = Level.NavigationPointList;
      Best = Location;
      rating = 0;

      while ( N != None )
      {
         if ( N.IsA('QueenDest') ) // rate it
         {
            newrating = 0;
            if ( Best == Location )
               Best = N.Location;
            ViewPoint = N.Location + EyeHeight * vect(0,0,1);
            HitActor = Trace(HitLocation, HitNormal, Enemy.Location, ViewPoint, false);
            if ( HitActor == None )
               newrating = 20000;

            newrating = newrating - VSize(N.Location - Enemy.Location) + 1000 * FRand()
                     + 4 * VSize(N.Location - Location);
            if ( N.Location.Z > Enemy.Location.Z )
               newrating += 1000;
            
            if ( newrating > rating )
            {
               rating = newrating;
               Best = N.Location;
            }
         }

         N = N.nextNavigationPoint;
      }

      TelepDest = Best;
   }

   function BeginState()
   {
      Acceleration = Vect(0,0,0);
      ChooseDestination();
   }

   function EndState()
   {
      bUnlit = false;
      Style = STY_Normal;
      ScaleGlow = 1.0;
      fatness = Default.fatness;
   }
}
Eh, we do not have to remove teleporting, we have to LOVE teleporting when is done different... :agree1: .
Firsts results:
- will not telefrag nobody - that was really stupid;
- might teleport as a combat feature not as a default insane lousy habit;
- assumption for now: I think won't break events as was doing before.
User avatar
sektor2111
Godlike
 
Posts: 3521
Joined: Sun May 09, 2010 6:15 pm
Location: vect(1,1,1)

Re: Avoid teleporting of Queens

Postby EvilGrins » Sun Jun 17, 2018 10:57 pm

For whatever it's worth, I find by not going anywhere near the Queens or just not shooting at them... they don't teleport.
:mrgreen: :highfive: :wtf:
http://unreal-games.livejournal.com/
Image
medor wrote:Replace Skaarj with EvilGrins :mrgreen:
User avatar
EvilGrins
Godlike
 
Posts: 6021
Joined: Thu Jun 30, 2011 8:12 pm
Location: Palo Alto, CA
Personal rank: God of Fudge

Re: Avoid teleporting of Queens

Postby sektor2111 » Mon Jun 18, 2018 6:10 am

EvilGrins wrote:For whatever it's worth, I find by not going anywhere near the Queens or just not shooting at them... they don't teleport.
For not ending such a map worth to not vote it but another one. I don't get what exactly do you mean. If you don't shoot them and are counted maybe killing them using a telekinetic influence or letting them to die starved would help, right ? Barbie has asked a solution not an useless post. We have to solve these problems once forever rather than only making noise and annoying those which might want to see a solution for this case as well.
All I have to say in this moment is that MA-Queens randomly going broken as others with multiple queens around won't do headaches, thy won't teleport in a "busy" spot and they use teleporting more random. The same good state in 2MuchHP, going to see Demons][ with those 2 Queens, but I think I have relevant results, there is nothing lost at removing that stupid encroachment. As for mods based on some sort of Queen Telefragging Titans - a supposed replacement (a la Lucky), Good Luck with them... exist indeed a solution (or more) for such case but I'm not bother to dig in other yard.
PS:
And, Yes, MH admins, a MH server will not be the best deal with default stock files or out of replacements... any super duper MH is not helping that much when is about multiple queens under counter.
The main note:
Stock Queen from Unreal... has a string " the Queen", it's not like " a Pupae". Logic explanation: in Level you might see more that one Pupae it's just "a Pupae". But when we speak about Queen it will be " the Queen" supposed to be unique not for "spammy servers" which people are finding cool as broken as they are. For such a server it's required some work for polishing a bit the action, default files only are not an answer, are broken stuff.
User avatar
sektor2111
Godlike
 
Posts: 3521
Joined: Sun May 09, 2010 6:15 pm
Location: vect(1,1,1)

Re: Avoid teleporting of Queens

Postby Qwerty » Mon Jun 18, 2018 3:13 pm

I have seen the queen in an endless teleport loop on our servers on a few occasions. Sometimes they can't be killed unless a huge nuke is used. shooting them with non ultra powerful weapons tends to be useless. I would like to test a possible fix when available
http://www.vulpinemission.com
Image ROCKET-X8 Server
Image MONSTERHUNT w/ NALI WEAPONS 3 + RX8
Image BUNNYTRACK NY
Image SNIPER DEATHMATCH
Image ROSEBUM ROCKET-X RB
Qwerty
Masterful
 
Posts: 653
Joined: Wed Mar 12, 2008 7:14 pm
Location: New York
Personal rank: I.T Master

Re: Avoid teleporting of Queens

Postby MrLoathsome » Mon Jun 18, 2018 4:22 pm

I think I posted the solution.

If you name your Package QueenSB and the class Queen, i.e. "QueenSB.Queen" to summon/spawn,
I believe it will pass the IsA('Queen') check.

(Note, haven't actually tested that....)
blarg
MrLoathsome
Inhuman
 
Posts: 956
Joined: Wed Mar 31, 2010 9:02 pm
Location: MrLoathsome fell out of the world!
Personal rank: I am quite rank.

Re: Avoid teleporting of Queens

Postby sektor2111 » Mon Jun 18, 2018 5:00 pm

MrLoathsome wrote:If you name your Package QueenSB and the class Queen, i.e. "QueenSB.Queen" to summon/spawn,
I believe it will pass the IsA('Queen') check.
I'm sure will work as do works other things like IsA('MonsterHunt') used in a newer trigger able to finish a non default MH game, it only does a check to a 'Name', so it should be good if answer is replacing default Queen... with a class having the same Name but I hope compiler to not cry, at least in my DeathMatchPlus did not happened and was "class DeathMatchPlus expands BotPack.DeathMatchPlus" compiled without issues but taking in account to manage well those "Super" calls else everything goes down-hill executing parent borked stuff.

@Qwerty
You can speak with your coder(s), probably Mar can handle this, the modified Queen which I posted is fully compatible with default Queen, so to speak client won't be skating trying to match new class because it uses default things, nothing new, just wrapping, so it can be conformed with default UT client with no issues - I HAVE such a Queen at this moment (I must backup server again - reminder for me) and it does look tens times better - NOT RECOMMEND posting any of such package in public, these aren't for players and if a new package is being posted claimed server-fix, jesters are mindlessly loading them in 2 seconds and ACE will kick them out, to not forget potential errors which won't be a good thing. Each admin might fix these how wants, Queen which I posted is not a default rule, also fixing in this way it's a suggestion not a must be.
User avatar
sektor2111
Godlike
 
Posts: 3521
Joined: Sun May 09, 2010 6:15 pm
Location: vect(1,1,1)

Re: Avoid teleporting of Queens

Postby Barbie » Wed Jun 27, 2018 2:02 am

Got my new Queen running and checked:
QueenSB
Code: Select all
class QueenSB expands Queen;

/******************************************************************************
Changes to UnrealI.Queen:
1) Queens spawned via factory do not telefrag other queens (based on function
   EncroachingOn())
2) Queens try to teleport only once if there is no QueenDest (based on variable
   "QueenDestHave").
3) Queens do not telefrag other pawns on QueenDests.
4) *ProjectileSpeed* is used now.

Hint: if you use CheckReplacement() to exchange the Queens, you should also
exchange "Prototype" in factories.
******************************************************************************/


var enum EQueenDestHave {
  QDH_Yes, QDH_No, QDH_Unchecked
} QueenDestHave;


event bool EncroachingOn( actor Other ) {
   if ( (Other.Brush != None) || (Brush(Other) != None) || Queen(Other) != None)
      return true;

   return false;
}




function bool RadiusActorHave(Actor A, class<actor> SearchClass, float Radius) {
local Actor Result;

   foreach A.RadiusActors(SearchClass, Result, Radius, A.Location)
      return true;
   return false;
}



function PostBeginPlay() {
local float PreProjectileSpeed;

   PreProjectileSpeed = ProjectileSpeed;
   Super.PostBeginPlay();
   // same as in Queen.PostBeginPlay(), except using *ProjectileSpeed* now instead of "1200":
   ProjectileSpeed = PreProjectileSpeed + 100 * Skill;
}



state TacticalMove
{
ignores SeePlayer, HearNoise;

   function PickDestination(bool bNoCharge)
   {
   // copied all variables from ScriptedPawn.TacticalMove.PickDestination(), because "Super(ScriptedPawn).PickDestination(bNoCharge)" does not compile
   local vector pickdir, enemydir, enemyPart, Y, minDest;
   local actor HitActor;
   local vector HitLocation, HitNormal, collSpec;
   local float Aggression, enemydist, minDist, strafeSize, optDist;
   local bool success, bNoReach;

      if ((FRand() < 0.26) && QueenDestHave != QDH_No)
      {
         GotoState('Teleporting');
         Return;
      }
   // copied all remaining lines from ScriptedPawn.TacticalMove.PickDestination(), because "Super(ScriptedPawn).PickDestination(bNoCharge)" does not compile
      bChangeDir = false;
      if (Region.Zone.bWaterZone && !bCanSwim && bCanFly)
      {
         Destination = Location + 75 * (VRand() + vect(0,0,1));
         Destination.Z += 100;
         return;
      }
      if ( Enemy.Region.Zone.bWaterZone )
         bNoCharge = bNoCharge || !bCanSwim;
      else
         bNoCharge = bNoCharge || (!bCanFly && !bCanWalk);

      success = false;
      enemyDist = VSize(Location - Enemy.Location);
      Aggression = 2 * (CombatStyle + FRand()) - 1.1;
      if ( intelligence == BRAINS_Human )
      {
         if ( Enemy.bIsPlayer && (AttitudeToPlayer == ATTITUDE_Fear) && (CombatStyle > 0) )
            Aggression = Aggression - 2 - 2 * CombatStyle;
         if ( Weapon != None )
            Aggression += 2 * Weapon.SuggestAttackStyle();
         if ( Enemy.Weapon != None )
            Aggression += 2 * Enemy.Weapon.SuggestDefenseStyle();
      }

      if ( enemyDist > 1000 )
         Aggression += 1;
      if ( bIsPlayer && !bNoCharge )
         bNoCharge = ( Aggression < FRand() );

      if ( (Physics == PHYS_Walking) || (Physics == PHYS_Falling) )
      {
         if (Location.Z > Enemy.Location.Z + 140) //tactical height advantage
            Aggression = FMax(0.0, Aggression - 1.0 + CombatStyle);
         else if (Location.Z < Enemy.Location.Z - CollisionHeight) // below enemy
         {
            if ( !bNoCharge && (Intelligence > BRAINS_Reptile)
               && (Aggression > 0) && (FRand() < 0.6) )
            {
               GotoState('Charging');
               return;
            }
            else if ( (enemyDist < 1.1 * (Enemy.Location.Z - Location.Z))
                  && !actorReachable(Enemy) )
            {
               bNoReach = (Intelligence > BRAINS_None);
               aggression = -1.5 * FRand();
            }
         }
      }

      if (!bNoCharge && (Aggression > 2 * FRand()))
      {
         if ( bNoReach && (Physics != PHYS_Falling) )
         {
            TweenToRunning(0.15);
            GotoState('Charging', 'NoReach');
         }
         else
            GotoState('Charging');
         return;
      }

      if (enemyDist > FMax(VSize(OldLocation - Enemy.OldLocation), 240))
         Aggression += 0.4 * FRand();

      enemydir = (Enemy.Location - Location)/enemyDist;
      minDist = FMin(160.0, 3*CollisionRadius);
      if ( bIsPlayer )
         optDist = 80 + FMin(EnemyDist, 250 * (FRand() + FRand()));
      else
         optDist = 50 + FMin(EnemyDist, 500 * FRand());
      Y = (enemydir Cross vect(0,0,1));
      if ( Physics == PHYS_Walking )
      {
         Y.Z = 0;
         enemydir.Z = 0;
      }
      else
         enemydir.Z = FMax(0,enemydir.Z);

      strafeSize = FMax(-0.7, FMin(0.85, (2 * Aggression * FRand() - 0.3)));
      enemyPart = enemydir * strafeSize;
      strafeSize = FMax(0.0, 1 - Abs(strafeSize));
      pickdir = strafeSize * Y;
      if ( bStrafeDir )
         pickdir *= -1;
      bStrafeDir = !bStrafeDir;
      collSpec.X = CollisionRadius;
      collSpec.Y = CollisionRadius;
      collSpec.Z = FMax(6, CollisionHeight - 18);

      minDest = Location + minDist * (pickdir + enemyPart);
      HitActor = Trace(HitLocation, HitNormal, minDest, Location, false, collSpec);
      if (HitActor == None)
      {
         success = (Physics != PHYS_Walking);
         if ( !success )
         {
            collSpec.X = FMin(14, 0.5 * CollisionRadius);
            collSpec.Y = collSpec.X;
            HitActor = Trace(HitLocation, HitNormal, minDest - (18 + MaxStepHeight) * vect(0,0,1), minDest, false, collSpec);
            success = (HitActor != None);
         }
         if (success)
            Destination = minDest + (pickdir + enemyPart) * optDist;
      }

      if ( !success )
      {
         collSpec.X = CollisionRadius;
         collSpec.Y = CollisionRadius;
         minDest = Location + minDist * (enemyPart - pickdir);
         HitActor = Trace(HitLocation, HitNormal, minDest, Location, false, collSpec);
         if (HitActor == None)
         {
            success = (Physics != PHYS_Walking);
            if ( !success )
            {
               collSpec.X = FMin(14, 0.5 * CollisionRadius);
               collSpec.Y = collSpec.X;
               HitActor = Trace(HitLocation, HitNormal, minDest - (18 + MaxStepHeight) * vect(0,0,1), minDest, false, collSpec);
               success = (HitActor != None);
            }
            if (success)
               Destination = minDest + (enemyPart - pickdir) * optDist;
         }
         else
         {
            if ( (CombatStyle <= 0) || (Enemy.bIsPlayer && (AttitudeToPlayer == ATTITUDE_Fear)) )
               enemypart = vect(0,0,0);
            else if ( (enemydir Dot enemyPart) < 0 )
               enemyPart = -1 * enemyPart;
            pickDir = Normal(enemyPart - pickdir + HitNormal);
            minDest = Location + minDist * pickDir;
            collSpec.X = CollisionRadius;
            collSpec.Y = CollisionRadius;
            HitActor = Trace(HitLocation, HitNormal, minDest, Location, false, collSpec);
            if (HitActor == None)
            {
               success = (Physics != PHYS_Walking);
               if ( !success )
               {
                  collSpec.X = FMin(14, 0.5 * CollisionRadius);
                  collSpec.Y = collSpec.X;
                  HitActor = Trace(HitLocation, HitNormal, minDest - (18 + MaxStepHeight) * vect(0,0,1), minDest, false, collSpec);
                  success = (HitActor != None);
               }
               if (success)
                  Destination = minDest + pickDir * optDist;
            }
         }
      }

      if ( !success )
         GiveUpTactical(bNoCharge);
      else
      {
         pickDir = (Destination - Location);
         enemyDist = VSize(pickDir);
         if ( enemyDist > minDist + 2 * CollisionRadius )
         {
            pickDir = pickDir/enemyDist;
            HitActor = Trace(HitLocation, HitNormal, Destination + 2 * CollisionRadius * pickdir, Location, false);
            if ( (HitActor != None) && ((HitNormal Dot pickDir) < -0.6) )
               Destination = HitLocation - 2 * CollisionRadius * pickdir;
         }
      }

   }
}


state Hunting
{
ignores EnemyNotVisible;

   function PickDestination()
   {
   // copied all variables from ScriptedPawn.PickDestination(), because "Super(ScriptedPawn).PickDestination(bNoCharge)" does not compile
   local NavigationPoint path;
   local actor HitActor;
   local vector HitNormal, HitLocation, nextSpot, ViewSpot;
   local float posZ, elapsed;
   local bool bCanSeeLastSeen;

      if (QueenDestHave != QDH_No)
      {
         GotoState('Teleporting');
         Return;
      }
      // copied all remaining lines from ScriptedPawn.Hunting.PickDestination(), because "Super(ScriptedPawn).PickDestination(bNoCharge)" does not compile
      // If no enemy, or I should see him but don't, then give up
      if ( (Enemy == None) || (Enemy.Health <= 0) )
      {
         WhatToDoNext('','');
         return;
      }

      bAvoidLedges = false;
      elapsed = Level.TimeSeconds - HuntStartTime;
      if ( (elapsed > 30) && ((intelligence < BRAINS_Human) || (elapsed > 90)) )
      {
            WhatToDoNext('','');
            return;
      }

      if ( JumpZ > 0 )
         bCanJump = true;

      if ( ActorReachable(Enemy) )
      {
         if ( bIsBoss || (numHuntPaths < 8 + Skill) || (elapsed < 15)
            || ((Normal(Enemy.Location - Location) Dot vector(Rotation)) > -0.5) )
         {
            Destination = Enemy.Location;
            MoveTarget = None;
            numHuntPaths++;
         }
         else
            WhatToDoNext('','');
         return;
      }
      numHuntPaths++;

      ViewSpot = Location + EyeHeight * vect(0,0,1);
      bCanSeeLastSeen = false;
      if ( intelligence > BRAINS_Reptile )
      {
         HitActor = Trace(HitLocation, HitNormal, LastSeenPos, ViewSpot, false);
         bCanSeeLastSeen = (HitActor == None);
         if ( bCanSeeLastSeen )
         {
            HitActor = Trace(HitLocation, HitNormal, LastSeenPos, Enemy.Location, false);
            bHunting = (HitActor != None);
         }
         else
            bHunting = true;
         if ( FindBestPathToward(Enemy) )
            return;
      }

      MoveTarget = None;
      if ( bFromWall )
      {
         bFromWall = false;
         if ( !PickWallAdjust() )
         {
            if ( CanStakeOut() )
               GotoState('StakeOut');
            else
               WhatToDoNext('', '');
         }
         return;
      }

      if ( !bIsBoss && (NumHuntPaths > 20) && ((Intelligence < BRAINS_Human) || (NumHuntPaths > 60)) )
      {
         WhatToDoNext('', '');
         return;
      }

      if ( LastSeeingPos != vect(1000000,0,0) )
      {
         Destination = LastSeeingPos;
         LastSeeingPos = vect(1000000,0,0);
         HitActor = Trace(HitLocation, HitNormal, Enemy.Location, ViewSpot, false);
         if ( HitActor == None )
         {
            If (VSize(Location - Destination) < 20)
            {
               HitActor = Trace(HitLocation, HitNormal, Enemy.Location, ViewSpot, false);
               if (HitActor == None)
               {
                  SetEnemy(Enemy);
                  return;
               }
            }
            return;
         }
      }

      bAvoidLedges = ( (CollisionRadius > 42) && (Intelligence < BRAINS_Human) );
      posZ = LastSeenPos.Z + CollisionHeight - Enemy.CollisionHeight;
      nextSpot = LastSeenPos - Normal(Enemy.Location - Enemy.OldLocation) * CollisionRadius;
      nextSpot.Z = posZ;
      HitActor = Trace(HitLocation, HitNormal, nextSpot , ViewSpot, false);
      if ( HitActor == None )
         Destination = nextSpot;
      else if ( bCanSeeLastSeen )
         Destination = LastSeenPos;
      else
      {
         Destination = LastSeenPos;
         HitActor = Trace(HitLocation, HitNormal, LastSeenPos , ViewSpot, false);
         if ( HitActor != None )
         {
            // check if could adjust and see it
            if ( PickWallAdjust() || FindViewSpot() )
               GotoState('Hunting', 'AdjustFromWall');
            else if ( bIsBoss || VSize(Enemy.Location - Location) < 1200 )
               GotoState('StakeOut');
            else
            {
               WhatToDoNext('Waiting', 'TurnFromWall');
               return;
            }
         }
      }
      LastSeenPos = Enemy.Location;
   }
}



State Teleporting
{
ignores TakeDamage, SeePlayer, EnemyNotVisible, HearNoise, KilledBy, Bump, HitWall, HeadZoneChange, FootZoneChange, ZoneChange, Falling, WarnTarget, Died;



   function ChooseDestination()
   {
   local NavigationPoint N;
   local vector ViewPoint, HitLocation, HitNormal, Best;
   local actor HitActor;
   local float rating, newrating, NeededRadius;

      Best = Location;
      if (QueenDestHave != QDH_No)
      {
         N = Level.NavigationPointList;
         rating = 0;
         NeededRadius = fMax(CollisionRadius, CollisionHeight) * 1.5; // 1.5 => keep some safaty distance
         QueenDestHave = QDH_No; // will be changed in loop, if a QueenDest is found
         while ( N != None )
         {
            if ( N.IsA('QueenDest'))
            {
               QueenDestHave = QDH_Yes;
               if ( ! RadiusActorHave(N, class'Pawn' , NeededRadius) ) // don't telefrag other Pawns
               { // rate it
                  newrating = 0;
                  if ( Best == Location )
                     Best = N.Location;
                  ViewPoint = N.Location + EyeHeight * vect(0,0,1);
                  HitActor = Trace(HitLocation, HitNormal, Enemy.Location, ViewPoint, false);
                  if ( HitActor == None )
                     newrating = 20000;

                  newrating = newrating - VSize(N.Location - Enemy.Location) + 1000 * FRand() + 4 * VSize(N.Location - Location);
                  if ( N.Location.Z > Enemy.Location.Z )
                     newrating += 1000;

                  if ( newrating > rating )
                  {
                     rating = newrating;
                     Best = N.Location;
                  }
               }
            }

            N = N.nextNavigationPoint;
         }
      }
      TelepDest = Best;
   }

}



defaultproperties
{
   MenuName="Queen"
   ProjectileSpeed=1200
   CollisionRadius=90
   CollisionHeight=107
}
Changes to UnrealI.Queen:
  • Queens spawned via factory do not telefrag other queens (based on function EncroachingOn())
  • Queens try to teleport only once if there is no QueenDest (based on variable QueenDestHave).
  • Queens do not telefrag other pawns on QueenDests.
  • ProjectileSpeed is used now.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
Barbie
Godlike
 
Posts: 1497
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: Avoid teleporting of Queens

Postby sektor2111 » Wed Jun 27, 2018 6:23 am

Making things more complicated with writing patch modules - replacements, but is not the end of world here, all I have to say is Thanks so far. In other ground of deals, there is a server set by self person having fore-mentioned out-of mismatch stock queen reacting different located at unreal://64.94.238.23:7777. I could not convince them (services) to allow me to switch those files from System, so I have quit using System setting up a different configuration. By disabling XC Queen tweaking, I allow queens to run in "original". You can inspect maps with queens - including self explanatory MA-Queens and see if will ever break game as it was doing before... I'm not going to setup servers using default trash files ever.
To do: Inspecting that blob from UnrealShare, I see array error 5/5 in client so I think that is a nasty deal as long as it is... client code. Or I might try an XC_Actor there...
According to projectiles speed from me those are not going to be fixed, I have reasons for not unlocking these as configurable, some mappers likes to be retarded at random so I have no wish for doing damage with them unless you want to cap values at some normal limits for human beings living on Earth, leaving aliens to play in other location.
User avatar
sektor2111
Godlike
 
Posts: 3521
Joined: Sun May 09, 2010 6:15 pm
Location: vect(1,1,1)

Re: Avoid teleporting of Queens

Postby Barbie » Tue Oct 02, 2018 4:24 am

Finally I did a mutator ("SBQueenSaver") that replaces the Queens of package UnrealI with an improved one. The improvements of the new Queen are:
  • No telefragging of others if spawned by a factory.
  • No telefragging of others if teleporting to a QueenDest.
  • Only one teleport attempt if there are no QueenDests.
  • The minimum time between two teleleports is adjustable.
  • The shield size is adjusted to the queen's size.
  • ProjectileSpeed is used now.
Download at usual place.

PS: Avoiding telefragging is important if an event is connected to the victim. The event will not be risen on telefragging.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
User avatar
Barbie
Godlike
 
Posts: 1497
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Next

Return to Coding, Scripting

Who is online

Users browsing this forum: No registered users and 4 guests