Need More Fixes ?

Posts about Nelsona's findings in UT!
Post Reply
User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Sun Feb 16, 2014 5:49 am

quote at some old forum
How to trigger a monster ?
Depends on what we want. All normal triggering related to human player cannot be compared with Bot. Bot is a mess in triggering monsters. To test a map pathed having DistanceViewTriggers things aren't cute speaking about Bot. But... MyLevel is always a handy tool to inflict different custom stuff. For sure with or without spectating this one clones desired prototype of MonsterHunt(ing).

Code: Select all

class MHViewTrigger extends Triggers;

function Trigger( actor Other, pawn EventInstigator )
{
	local Pawn P;

	for ( P=Level.PawnList; P!=None; P=P.NextPawn )
	{
		if ( (abs(Location.Z - P.Location.Z) < CollisionHeight + P.CollisionHeight)
			&& (VSize(Location - P.Location) < CollisionRadius) )
		{
			if ( P.IsA('ScriptedPawn') && !EventInstigator.IsA('ScriptedPawn') && P.Health > 0 )
			{
				ScriptedPawn(P).Hated = EventInstigator;
				ScriptedPawn(P).Enemy = EventInstigator;
				ScriptedPawn(P).GotoState('Attacking');
//				log (ScriptedPawn(P).GetHumanName()$" has been triggered by "$EventInstigator.GetHumanName()); //just testing
			}
			P.Trigger(Other, EventInstigator);
		}
	}
}

defaultproperties
{
     bGameRelevant=True
}
Monsters placed covered by this trigger having some Tag, when are receiving an Event from another trigger matching the TAG, starts to get mad at pawn instigator doesn't matter if is Player or Bot, doesn't matter if are in a cave, behind a house, if they have a path to their enemy are going to start hunting shortly.
Question 2) So, distanceviewtrigger works in the mod coded by ME?
Answer: YES, I have solved these tricks if are used (Zacman, Me, Others ?)

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Fri Mar 07, 2014 12:25 pm

Back. Relationship between MH and other games ?
I looked at some CTF and DM maps highly rated.
There I saw a MH work by VATCILI done using a well-known technology having MyLevel-ed unhappy ends - not a bad ideea at all.
Then I decided to see if I can solve that specific bad end for such case.
After a long argue with Engine, I used a place-holder actor and later I dealed with Core getting over Engine.
First results were good.
For testing, I used LostSouls, I just had a... trouble (skipping too much triggering subject) Bots (only 2) fired redeemer bonuses killing to many Mercs.
I got confirmation: "You have lost the match" (I doubt to win looking at those mad Bots).

At least now works properly. Of course TeamMonster won't fill HDD space with errors because I just tested it and I won't insist too much. Also at 7 Bots used, looks like Merc is sleeping nice without to unlock last door as supposed... Eh, no problem will see next one.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Mon Mar 10, 2014 1:39 am

And "Alice" not worked as supposed. Alice being a Bot is part of Hunters - not so killable - common Bots ignored her, also she was interested by Me not by other Bots (????). She even received a redeemer bonus. She fired redeemer killing (friendlyfire on) 3 of us (hunters) and was punished with death - mission completed because of teamkill.

I'm not very interested to mock again with "AddToTeam", neither with "IsOnTeam" and "ReduceDamage" functions because I got a stable controller following rules with 0 errors and I'm not interested to mess with a pawn working only in default MH where SkaarjOfficer cannot kill hunters and generally loading a bunch of errors before even to start game.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Mon Mar 10, 2014 2:53 pm

Thinking at a few messed settings from a few supposed maps I think mapper wanted to have a kinda bad end at a moment and he simply ruined a mover. You wanna set a clocked war in last area or such prototype ? I think is not a problem. I just tested unsual ends for UT generally not only MH but functional even in MH.
Imagine scenario: "You have entered the castle. I give you 5 minutes to find and kill Boss".

Maybe you will say: LOL, anybody already knows where is Boss because we played map 30 times.

If mapper has 0 skill at A.I. and cannot setup a patrol or such thing to make monster to move then expect to find it easily. But we speak about... those 5 minutes or 3 minutes.
First use some math skill and compute 3 (minutes) × 60 (seconds) = 180. Value 180 will be added as an event to a Dispatcher acting after 180 seconds. Event launched by Dispatcher will be against a custom Trigger (a big one covering that area) which can be MyLevel-ed as follows:

Code: Select all

class aBadEnd expands Trigger;

function Touch( actor Other )
{
	local actor A;

	if( IsRelevant( Other ) )
	{
		if ( ReTriggerDelay > 0 )
		{
			if ( Level.TimeSeconds - TriggerTime < ReTriggerDelay )
				return;
			TriggerTime = Level.TimeSeconds;
		}
		if( Event != '' )
		foreach AllActors( class 'Actor', A, Event )
		{
			A.Trigger( Other, Other.Instigator );
			if (Level.Game.bGameEnded)
				break;
		}
		if ( Other.IsA('Pawn') && (Pawn(Other).SpecialGoal == self) )
			Pawn(Other).SpecialGoal = None;
				
		if( Message != "" )
			Other.Instigator.ClientMessage( Message );
		TriggerObjective();
		if( bTriggerOnceOnly )
			SetCollision(False);
		else if ( RepeatTriggerTime > 0 )
			SetTimer(RepeatTriggerTime, false);
	}
}

function TakeDamage( int Damage, Pawn instigatedBy, Vector hitlocation, 
						Vector momentum, name damageType)
{
	local actor A;

	if ( bInitiallyActive && (TriggerType == TT_Shoot) && (Damage >= DamageThreshold) && (instigatedBy != None) )
	{
		if ( ReTriggerDelay > 0 )
		{
			if ( Level.TimeSeconds - TriggerTime < ReTriggerDelay )
				return;
			TriggerTime = Level.TimeSeconds;
		}

		if ( Event != '' )
			foreach AllActors( class 'Actor', A, Event )
			{
				A.Trigger( instigatedBy, instigatedBy );
				if (Level.Game.bGameEnded)
					break;
			}

		if( Message != "" )
			instigatedBy.Instigator.ClientMessage( Message );

		if( bTriggerOnceOnly )
			SetCollision(False);
		TriggerObjective();
	}
}

function TriggerObjective()
{
	local TeamGamePlus TG;

	if (Level.Game.bGameEnded)
	{}
	else
	{
		TG = TeamGamePlus(Level.Game);
		if ( TG != None )
		{
			TG.GameReplicationInfo.GameEndedComments = "Your mission Failed!"; //Not for MH - MH has own fail message
			TG.TimeLimit = 2;
			TG.RemainingTime = 1;
		}
	}
}
Have fun! You wanna race in MH? Now let me see what's next.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Sun Mar 16, 2014 6:40 pm

Next small subject. A fix for MH Bot Support against normal racing.

Scenario is probably known or less known by mappers which made MH maps with Bot support.
Scenario: In first area we have a MonsterWayPoint. There is supposed to be eliminated a mini-boss or such. If Bot touch earlier WayPoint, will attempt to move forward without to mind still unkilled mini-boss. What we need then ? How to stop this stupid race ? Answer (came late indeed - better later than never) is simple, as usual simple things contains complex effects. A trigger placed over MonsterWayPoint will disable touch. Bot will go there fighting, firing... but nothing will happen if target is not eliminated so will stay around and fight. This trigger will turn on WayPoint (touch available) immediately after receiving an Event from an actor adressing the TAG defined for our trigger. How is acting ? Has a variable noticing request (Touch Disabled). After 3 seconds from PostBeginPlay will attack WayPoints placed into collision cylinder. Why 3 seconds ? Because I decided to give time for whatever MH style to be initialized properly without to alter other Touch calls (Skaarjs and CO.). Bot will continue normally his action because MonsterHunt controller is not checking Touch feature if is or not available - so Bot will keep moving. When is triggered, Waypoint(s) are available again for everybody, yes including protection from player to not break Bot Support. Being a simple code, can be MyLevel-ed as follows:

Code: Select all

class TouchSwitcher extends Triggers;

var() bool bInitiallyTouchDisabled;
var bool bIsDisabled; //variable used to control

event PostBeginPlay()
{
	Super.PostBeginPlay();
	SetTimer(3.00,False);
}

function Trigger( actor Other, pawn EventInstigator )
{
	local Keypoint K;

	foreach AllActors(class'Keypoint',K)
	{
		if ( (abs(Location.Z - K.Location.Z) < CollisionHeight + K.CollisionHeight) //Testing and solving
			&& (VSize(Location - K.Location) < CollisionRadius) )
		{
			if (bIsDisabled)
				K.Enable('Touch');
			else
				K.Disable('Touch');
		}
	}
}

singular event Timer()
{
	local Keypoint K;

	if (bInitiallyTouchDisabled)
	foreach AllActors(class'Keypoint',K)
	{
		if ( (abs(Location.Z - K.Location.Z) < CollisionHeight + K.CollisionHeight) //Testing and solving
			&& (VSize(Location - K.Location) < CollisionRadius) )
		{
			K.Disable('Touch');
			bIsDisabled = True;
		}
	}
}

defaultproperties
{
     bInitiallyTouchDisabled=True
}
And now I wanna see who is still mapping for MH with Bot Suppport. Also I have other small actors doing different tweaks: Unlock from a stucked path - run to a point timed controlled (combat strategy against a powerfull enemy), attack another prototype of pawn (Assault prototype), dynamic kicker, dynamic path, path control based on player proximity, and... I hope I did not forget something.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Thu Mar 27, 2014 3:24 pm

Return to defence. First encounter seems human defence automated (cannons). No... not defaults. Defaults are sleeping well and ought to sleep well else server will sleep well. Good, enough with sleep, let's move on:
MinigunCannon (MH version)

Code: Select all

//=============================================================================
// MHMinigunCannon.
//=============================================================================
class MHMinigunCannon extends MHTeamCannon;

var Actor MuzzFlash;

function PostBeginPlay()
{
	Super.PostBeginPlay();
	MuzzFlash = Spawn(class'CannonMuzzle');
	MuzzFlash.SetBase(self);
}

function Name PickAnim()
{
	Drop = 0;
	if (DesiredRotation.Pitch < -1000 )
	{
		if ( DesiredRotation.Pitch < -4000 )
			return 'Fire5';
		else 
			return 'Fire3';
	}
	else if (DesiredRotation.Pitch > 1000 ) 
	{
		if ( DesiredRotation.Pitch > 4000 )
			return 'Fire9';
		else 
			return 'Fire7';
	}
	else 
		return 'Fire1';
}

simulated function SpawnBase()
{
	GunBase = Spawn(class'GrBase', self);
	GunBase.bAnimByOwner = true;
}

function PlayDeactivate()
{
	TweenAnim('Activate', 1.5);
}

function StartDeactivate()
{
	PlaySound(ActivateSound, SLOT_None,5.0);
	Mesh = mesh'Botpack.GrMockGunM';
	AnimSequence = 'Fire1';
	AnimFrame = 0.0;
	SetPhysics(PHYS_Rotating);
	DesiredRotation = StartingRotation;
	PrePivot = vect(0,0,0);
}

function ActivateComplete()
{
	Mesh = mesh'Botpack.GrFinalGunM';
	PrePivot = vect(0,0,40);
}

function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z)
{
	local int rndDam;
	local UT_Shellcase s;
	
	s = Spawn(class'UT_ShellCase',, '', PrePivot + Location + 20 * X + 10 * Y + 30 * Z);
	if ( s != None )
		s.Eject(((FRand()*0.3+0.4)*X + (FRand()*0.2+0.2)*Y + (FRand()*0.3+1.0) * Z)*160);              
	if (Other == Level) 
		Spawn(class'UT_LightWallHitEffect',,, HitLocation+HitNormal, Rotator(HitNormal));
	else if ( (Other!=self) && (Other != None) ) 
	{
		if ( !Other.bIsPawn && !Other.IsA('Carcass') )
			spawn(class'UT_SpriteSmokePuff',,,HitLocation+HitNormal*9);
		rndDam = 5 + Rand(4);
		if ( DeathMatchPlus(Level.Game).bNoviceMode )
			rnddam *= (0.4 + 0.15 * Level.game.Difficulty);
		if (Other != None)
			Other.TakeDamage(rndDam, self, HitLocation, rndDam*500.0*X, 'shot');
	}
}

function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation, 
					Vector momentum, name damageType)
{
	MakeNoise(1.0);
	Health -= NDamage;
	if (Health <0) 
	{
		PlaySound(DeActivateSound, SLOT_None,5.0);
		NextState = 'Idle';
		Enemy = None;
		Spawn(class'UT_BlackSmoke');
		GotoState('DamagedState');
	}
	else if ( instigatedBy == None || InstigatedBy.IsA('TeamCannon') )
		return;
	else if ( (Enemy == None) && (!instigatedBy.bIsPlayer || !Level.Game.bTeamGame || !SameTeamAs(instigatedBy.PlayerReplicationInfo.Team)) )
	{	
		Enemy = instigatedBy;
//////////////// MH Needs 1) accidental damaged
		if (InstigatedBy.IsA('ScriptedPawn'))
		{
			ScriptedPawn(InstigatedBy).Hated=Self; //Claim enemy because I think I'll attack
			ScriptedPawn(InstigatedBy).Enemy=Self;
			//Should be enough
		}
///////////////
		GotoState('ActiveCannon'); //Probably yes
	}
}

function Shoot()
{
	local Actor HitActor;
	local Vector HitLocation, HitNormal, EndTrace, ProjStart, X,Y,Z;
	local rotator ShootRot;
	if (DesiredRotation.Pitch < -10000) Return;
	if ( AmbientSound == None )
		PlaySound(FireSound, SLOT_None,5.0);
	if ( Enemy != None )
	{
		GetAxes(Rotation,X,Y,Z);
		ProjStart = PrePivot + Location + X*20 + 12 * Y + 16 * Z;
		ShootRot = rotator(Enemy.Location - ProjStart);
		ShootRot.Yaw = ShootRot.Yaw + 1024 - Rand(2048);
		DesiredRotation = ShootRot;
		ShootRot.Pitch = ShootRot.Pitch + 256 - Rand(512);
		GetAxes(ShootRot,X,Y,Z);
		PlayAnim(PickAnim());
		MuzzFlash.SetLocation(ProjStart);
		if ( FRand() < 0.4 )
			Spawn(class'MTracer',,, ProjStart, ShootRot);
		HitActor = TraceShot(HitLocation,HitNormal,ProjStart + 10000 * X,ProjStart);
		ProcessTraceHit(HitActor, HitLocation, HitNormal, X,Y,Z);
		bShoot = false;
		ShootRot.Pitch = ShootRot.Pitch & 65535;
		if ( ShootRot.Pitch < 32768 )
			ShootRot.Pitch = Min(ShootRot.Pitch, 5000);
		else
			ShootRot.Pitch = Max(ShootRot.Pitch, 60535);
		MuzzFlash.SetRotation(ShootRot);
		ShootRot.Pitch = 0;
		SetRotation(ShootRot);
	}
	else
		{
			GotoState('Idle');
			return;
		}
			
}

state ActiveCannon
{
	ignores SeePlayer;

	function EnemyNotVisible()
	{
		local Pawn P;

		Enemy = None;
		for ( P=Level.PawnList; P!=None; P=P.NextPawn )
               if ( P.bCollideActors && !P.bDeleteMe && !P.bHidden && P.bIsPlayer && (!Level.Game.bTeamGame || !SameTeamAs(P.PlayerReplicationInfo.Team))
				&& (P.Health > 0) && !P.IsA('TeamCannon')
				&& LineOfSightTo(P) || (LineOfSightTo(P) && P.PlayerReplicationInfo == None && !P.IsA('StationaryPawn') && MyTeam == 0))
			{
				Enemy = P;
				if ( P.IsA('ScriptedPawn') && FRand() > 0.6 && ScriptedPawn(P).Enemy!=Self) //2) Convince Monster about this threat randomly
				{
					ScriptedPawn(P).Hated=Self;
					ScriptedPawn(P).Enemy=Self;
				}
				return;
			}
		GotoState('Idle');
	}

	function Killed(pawn Killer, pawn Other, name damageType)
	{
		Global.Killed(Killer,Other,damagetype);
		if ( Other == Enemy )
		{
			EnemyNotVisible();
		}
	}

	function Timer()
	{
		local Pawn P;

		if (Enemy != None && !Enemy.bHidden && !Enemy.bDeleteMe && LineOfSightTo(Enemy))
		{
			if ( Target == None )
				Target = Enemy;
		
		if ( Target == None )
		{
			GotoState('Idle');
			return;
		}
			DesiredRotation = rotator(Target.Location - Location - PrePivot);
			DesiredRotation.Yaw = DesiredRotation.Yaw & 65535;
			MuzzFlash.bHidden = false;
			if ( bShoot )
				Shoot();
			else 
			{
				TweenAnim(PickAnim(), 0.2);
				bShoot=True;			
				SetTimer(SampleTime,True);
			}
		}
		else
			{ GotoState('Idle'); return; }
	}

	function BeginState()
	{
		Super.BeginState();
	}

	function EndState()
	{
		AmbientSound = None;
		MuzzFlash.bHidden = true;
	}

Begin:
	Disable('Timer');
	FinishAnim();
	PlayActivate();
	FinishAnim();
	ActivateComplete();
	Enable('Timer');
	SetTimer(SampleTime,True);
	RotationRate.Yaw = TrackingRate;
	SetPhysics(PHYS_Rotating);
	AmbientSound = Class'Minigun2'.Default.FireSound;
	bShoot=True;

FaceEnemy:
	if (Enemy != None && LineOfSightTo(Enemy))
	{
		TurnToward(Enemy);
		Goto('FaceEnemy');
	}
	else{ Target = None; Enemy = None; GotoState('Idle');}
}

defaultproperties
{
     FireSound=Sound'UnrealI.Rifle.RifleShot'
     SampleTime=0.100000
     Mesh=LodMesh'Botpack.grmockgunM'
     SoundRadius=96
     SoundVolume=255
     CollisionHeight=24.000000
}
Would be more easier to add uc files but seems unallowed so ...
The deal is: Cannon with MyTeam=0 will be player's friend else in MyTeam=1 will hunt player. Cannon friend of player will hunt monster, monster will respond if gets mad. Player defence being ready I have to setup monster mission things. I'll see ...
Last edited by Nelsona on Thu Mar 27, 2014 3:30 pm, edited 1 time in total.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Thu Mar 27, 2014 3:28 pm

And the second class of defence systems (in fact is the first):

Code: Select all

//=============================================================================
// MHTeamCannon.
//=============================================================================
class MHTeamCannon extends TeamCannon; //Keep this family

function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation, 
					Vector momentum, name damageType)
{
	MakeNoise(1.0);
	Health -= NDamage;
	if (Health <0) 
	{
		PlaySound(DeActivateSound, SLOT_None,5.0);
		NextState = 'Idle';
		Enemy = None;
		Spawn(class'UT_BlackSmoke');
		GotoState('DamagedState');
	}
	else if ( instigatedBy == None || InstigatedBy.IsA('TeamCannon') )
		return;
	else if ( (Enemy == None) && (!instigatedBy.bIsPlayer || !Level.Game.bTeamGame || !SameTeamAs(instigatedBy.PlayerReplicationInfo.Team)) )
	{	
		Enemy = instigatedBy;
//////////////// MH Needs 1) accidental damaged by Monster
		if (InstigatedBy.IsA('ScriptedPawn'))
		{
			ScriptedPawn(InstigatedBy).Hated=Self;
			ScriptedPawn(InstigatedBy).Enemy=Self;
			//Should be enough
		}
///////////////
		GotoState('ActiveCannon'); //Start firing
	}
}

function Trigger( actor Other, pawn EventInstigator )
{
	if ( EventInstigator.bHidden || EventInstigator.health < 1 || EventInstigator == Self || EventInstigator == None )
		return;
	if (EventInstigator.PlayerReplicationInfo != None && EventInstigator.bIsPlayer)
		GotoState('DeActivated');
	else //This must be tested properly
	{
		if ( EventInstigator.PlayerReplicationInfo == None && !EventInstigator.IsA('StationaryPawn'))
		{
			Enemy = EventInstigator;
			GotoState('ActiveCannon');
		}
	}
}

function Shoot()
{
	local Vector FireSpot, ProjStart;
	local Projectile p;

	if ( Target != None ) //Exist something or you fire in mountains ?
	{
	if (DesiredRotation.Pitch < -20000) Return;
	PlaySound(FireSound, SLOT_None,5.0);
	PlayAnim(PickAnim());

	ProjStart = Location+Vector(DesiredRotation)*100 - Vect(0,0,1)*Drop;
	if ( bLeadTarget )
	{
		FireSpot = Target.Location + FMin(1, 0.7 + 0.6 * FRand()) * (Target.Velocity * VSize(Target.Location - ProjStart)/ProjectileType.Default.Speed);
		if ( !FastTrace(FireSpot, ProjStart) )
			FireSpot = 0.5 * (FireSpot + Target.Location);
		DesiredRotation = Rotator(FireSpot - ProjStart);
	}
	p = Spawn (ProjectileType,,,ProjStart,DesiredRotation);
	if ( DeathMatchPlus(Level.Game).bNoviceMode )
		P.Damage *= (0.4 + 0.15 * Level.game.Difficulty);
	if ( Target.IsA('WarShell') && Target != None )
		p.speed *= 2;
	bShoot=False;
	SetTimer(0.05,True);
	}
}

auto state Idle
{
	ignores EnemyNotVisible;

	function SeePlayer(Actor SeenPlayer) //Monsters somehow aren't cute if are already around - bStasis ? Engine things ?
	{									//I think is a need for other method
        if ( SeenPlayer.bCollideActors 
			&& ((Pawn(SeenPlayer).PlayerReplicationInfo.Team != MyTeam)
			|| !Level.Game.bTeamGame || (Pawn(SeenPlayer).PlayerReplicationInfo == None && !Pawn(SeenPlayer).IsA('StationaryPawn')) ))
		{
			Enemy = Pawn(SeenPlayer);
			GotoState('ActiveCannon');
		}
	}

	function timer() //Yes I need something
	{
		local Pawn P;
		if ( Enemy == None && Target == None && MyTeam == 0)
		for ( P=Level.PawnList; P!=None; P=P.NextPawn )
		{
			if (P != None && P.PlayerReplicationInfo==None && !P.IsA('StationaryPawn') && CanSee(P) //This should be enough for the moment
			&& !P.bDeleteMe && !P.bHidden)
			{
				Enemy = P;
				GotoState('ActiveCannon');
				break;
			}
		}
	}

	function BeginState()
	{
		Enemy = None;
	}

Begin:
	TweenAnim(AnimSequence, 0.25);
	Sleep(5.0);
	StartDeactivate();
	Sleep(0.0);
	PlayDeactivate();
	Sleep(2.0);
	SetPhysics(PHYS_None);
	SetTimer(1.0,True);
}

state ActiveCannon
{
	ignores SeePlayer;

	function EnemyNotVisible()
	{
		local Pawn P;

		Enemy = None;
		for ( P=Level.PawnList; P!=None; P=P.NextPawn )
               if ( P.bCollideActors && !P.bDeleteMe && !P.bHidden && P.bIsPlayer && (!Level.Game.bTeamGame || !SameTeamAs(P.PlayerReplicationInfo.Team))
				&& (P.Health > 0) && !P.IsA('TeamCannon')
				&& LineOfSightTo(P) || ( LineOfSightTo(P) && P.PlayerReplicationInfo == None && !P.IsA('StationaryPawn') && MyTeam == 0 ))
			{
				Enemy = P;
				if ( P.IsA('ScriptedPawn') && FRand() > 0.6 && ScriptedPawn(P).Enemy!=Self) //2) Convince Monster about this threat randomly
				{
					ScriptedPawn(P).Hated=Self;
					ScriptedPawn(P).Enemy=Self;
				}
				return;
			}
		GotoState('Idle');
	}
	
	function Killed(pawn Killer, pawn Other, name damageType)
	{
		Global.Killed(Killer,Other,damagetype); //Meh, I think I won't stuck something here. Bullshit stopped.
		if ( Other == Enemy )
		{
			EnemyNotVisible(); //Seek next one
		}
	}

	function Timer()
	{
		local Pawn P;
		if ( Enemy != None && !Enemy.bHidden && !Enemy.bDeleteMe && LineOfSightTo(Enemy) ) //LOLZ
		{
			if ( Target == None ) //No target but exist enemy
				Target = Enemy; //Claim enemy as target
			if (Target == None )
			{
				GotoState('Idle');
				return;
			}
			DesiredRotation = rotator(Target.Location - Location); //track the target then
			DesiredRotation.Yaw = DesiredRotation.Yaw & 65535;
			if ( bShoot && (DesiredRotation.Pitch < 2000)
				&& ((Abs(DesiredRotation.Yaw - (Rotation.Yaw & 65535)) < 1000)
				|| (Abs(DesiredRotation.Yaw - (Rotation.Yaw & 65535)) > 64535)) )
				Shoot(); //Fire !!!
			else 
			{
				TweenAnim(PickAnim(), 0.25);
				bShoot=True;			
				SetTimer(SampleTime,True);
			}
			if (Enemy.IsA('ScriptedPawn') && FRand() > 0.6) //Monster is not glad
			{
				ScriptedPawn(Enemy).Hated=Self;
				ScriptedPawn(Enemy).Enemy=Self;
			}
		}
	}

	function BeginState()
	{
		if ( Enemy != None && !Enemy.bHidden && !Enemy.bDeleteMe && Target == None && LineOfSightTo(Enemy)) //Something much better
			Target = Enemy; //Right at begining
	}

Begin:
	Disable('Timer');
	FinishAnim();
	PlayActivate();
	FinishAnim();
	ActivateComplete();
	Enable('Timer');
	SetTimer(SampleTime,True);
	RotationRate.Yaw = TrackingRate;
	SetPhysics(PHYS_Rotating);
	bShoot=True;

FaceEnemy:
	if ( Enemy != None && LineOfSightTo(Enemy) ) //IF IF IF !!!
	{
		TurnToward(Enemy);
		Goto('FaceEnemy');
	}
	else {Target = None; Enemy = None; GotoState('Idle');} //Else stop hunting ghosts (probably your dead grandma haunts you)
}

defaultproperties
{
     FireSound=Sound'UnrealI.Cannon.CannonShot'
     ActivateSound=Sound'UnrealI.Cannon.CannonActivate'
     SampleTime=0.330000
     TrackingRate=25000
     Drop=60.000000
     ProjectileType=Class'Botpack.CannonShot'
     PostKillMessage="was killed by an automatic cannon!"
     SightRadius=3000.000000
     FovAngle=90.000000
     Health=220
     MenuName="automatic cannon!"
     NameArticle="an "
     RemoteRole=ROLE_SimulatedProxy
     AnimSequence=Activate
     Mesh=LodMesh'Botpack.cdgunmainM'
     CollisionRadius=28.000000
     RotationRate=(Yaw=25000)
}
Both classes ought to work MyLevel-ed by skilled mappers and I think are cute in helping hunters (SPAWN PROTECTION AREA). Cya later!

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Sat Mar 29, 2014 3:37 am

Q: What kinda Trooper fixes and teaming monsters are possible even for default MH directly in map ?
A: Small tunes with cute effects a la 2014.
MyLevel says:

Code: Select all

class MonsterTeam expands Actor;

var() name MyTag; //Declare team password manually by mapper

event PostBeginPlay()
{
	SetTimer(0.8,True); //won't touch anything first 800 ms but start timer
	Super.PostBeginPlay(); //keep going
}

singular event Timer() //time for party
{
	local Pawn P; //use pawn root
	local ScriptedPawn S; //and interest for Monster
	local Weapon W, W1; //We will toy a bit with wepsy

	foreach AllActors (class 'Weapon', W) //Debate craps first
	{
		if ( W != None && W.MyMarker == None && W.RespawnTime == 0 && W.Instigator == None && W.bRotatingPickup && W.bHeldItem && W.Owner == None) //Exist a weapon not added by mapper and replaced by some stupid mutator ?
		foreach W.RadiusActors (class 'ScriptedPawn',S,W.CollisionRadius) //look for a clown arround touching range
		if ( S != None && S.Intelligence == BRAINS_Human && S.Health > 0 && S.Weapon == None ) //is a chess player here alive
		{
			if (!S.bIsPlayer) //Possible to not be player ?
				S.bIsPlayer = True; //Fix his hands
			W1 = Spawn (W.class,,,W.Location); //Spawn a copy because older is too early initialized and the dude will drop invisible manure
			if (W1 != None) //No worry, is class already replaced, 0.8 seconds passed
			{
				W.Destroy(); //Then destroy the mess
				W1.Touch(S); //New thing touch this player
			}
			else W.Touch(S); //else if Karma bugs me, old wep do the job :(
		}
	}
// Keep moving faster
	for ( P=Level.PawnList;P!=None;P=P.NextPawn )
	{
		S = ScriptedPawn(P); //from pawns we are interested about Monsters
		if ( S != None && S.Health > 0 ) //If exist any alive
		{
			if ( S.IsA('Nali') || S.IsA('Cow') ) //stupids excepted
				continue;
			if (S.TeamTag == ''); //not used anything here ?
				S.TeamTag = MyTag; //use our thing
			if (S.bIsPlayer)
				S.bIsPlayer=False; //If a dude mock here
			if ( S.Enemy != None && S.Enemy.IsA('ScriptedPawn') ) //block monster with enemy other monster
			{
				S.Hated = None;
				S.Enemy = None;
				S.bHunting = False;
				if (S.OldEnemy != None && S.OldEnemy.IsA('ScriptedPawn'))
					S.OldEnemy = None;
				if ( S.Orders != '' ) //if has an order perform it
					S.GotoState(S.Orders);
				else //else sleep well, is one of your best skills
					S.GotoState('Waiting');
			}
		}
	}
}
defaultproperties
{
     bHidden=True
}
I think now things are more relaxed and we can use fresh content from monsters initialized correctly.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Sat Mar 29, 2014 2:46 pm

Wait a moment, what if we want a nice Christmas map and PrecipitationGenerator cannot be so recommended.

Code: Select all

ScriptWarning: PrecipitationGenerator MH-(Ph)TheMines.PrecipitationGenerator0 (Function MH-(Ph)TheMines.PrecipitationGenerator.Timer:00D2) Accessed None
ScriptWarning: PrecipitationGenerator MH-(Ph)TheMines.PrecipitationGenerator0 (Function MH-(Ph)TheMines.PrecipitationGenerator.Timer:00DA) Attempt to assigned variable through None
... // SPAM !!!
Meh... Back to Mr. None dude
Timer Old ?

Code: Select all

d = Spawn(class'PrecipParticle',,,NewLoc);
d.DrawScale = ParticleSize;  
d.Texture = ParticleTexture;
d.Style = ParticleStyle;
d.bLOS = bLineOfSiteCheck;
d.Velocity=vVelocity + FRand() * (vVelocity * 0.2);
if(Rand(100) < SpawnWhenlandPercentage && SpawnWhenlandPercentage > 0 && SpawnWhenLand != None)
{
	d.LSpawn = True;
	d.LSpawnType = SpawnWhenLand;
	d.LSpawnSize = SpawnWhenLandDrawscale;
}
And 0 error code:

Code: Select all

		d = Spawn(class'PrecipParticle',,,NewLoc);
		if ( d != None ) //Probably not always spawned, right ?
		{
			d.DrawScale = ParticleSize;  
			d.Texture = ParticleTexture;
			d.Style = ParticleStyle;
			d.bLOS = bLineOfSiteCheck;
			d.Velocity=vVelocity + FRand() * (vVelocity * 0.2);
			if(Rand(100) < SpawnWhenlandPercentage && SpawnWhenlandPercentage > 0 && SpawnWhenLand != None)
			{
				d.LSpawn = True;
				d.LSpawnType = SpawnWhenLand;
				d.LSpawnSize = SpawnWhenLandDrawscale;
			}
		}
Now let it rain smoother.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Wed Apr 02, 2014 3:37 pm

Back to MonsterTeam Actor. I think it is too wick at teaming - I set a small modification. Using this oportunity I considered that time come to bring on stage SKAARJOFFICER originally ruined. Let's see how is Actor:

Code: Select all

class MonsterTeam expands Actor;

var() name MyTag; //Must DEFINE Something here

event PostBeginPlay()
{
	local Ammo Am;

	SetTimer(0.8,True);
	Super.PostBeginPlay();
	foreach AllActors(class'Ammo',Am)
	{
		if (Am != None && Am.PickupMessageClass == None )
		{
			Am.PickupMessageClass = class 'Botpack.PickupMessagePlus';
		}
	}
}

singular event Timer()
{
	local Pawn P;
	local ScriptedPawn S;
	local Weapon W,W1,W2;

	foreach AllActors (class 'Weapon', W)
	{
		if ( W != None && W.MyMarker == None && W.RespawnTime == 0 && W.Instigator == None &&
		 W.bRotatingPickup && W.bHeldItem && W.Owner == None )
		foreach W.RadiusActors (class 'ScriptedPawn',S,W.CollisionRadius)
		if ( S != None && S.Intelligence == BRAINS_Human && S.Health > 0 && S.Weapon == None )
		{
			if (!S.bIsPlayer)
				S.bIsPlayer = True;
			W1 = Spawn (W.class,,,W.Location);
			W1.RespawnTime = 0.00;
			log (W1$" spawned for "$W);
			if (!S.bIsPlayer)
				S.bIsPlayer = True;
			if (W1 != None)
			{
				W.Destroy();
				W1.Touch(S);
			}
			else W.Touch(S);
			break;
		}
	}

	for ( P=Level.PawnList;P!=None;P=P.NextPawn )
	{
		S = ScriptedPawn(P);
		if ( S != None && S.Health > 0 )
		{
			if ( S.IsA('Nali') || S.IsA('Cow') )
				continue;
			if (S.IsA('SkaarjOfficer') && S.Weapon == None)
			{
				W2 = spawn(class'MonsterHunt.OLRazorJack',,,S.Location);
				if (W2 != None)
				{
					W2.RespawnTime = 0;
					S.bIsPlayer = True;
					W2.Touch(S);
				}
			}
			if (S.TeamTag == '' || S.TeamTag == S.Default.TeamTag);
				S.TeamTag = MyTag;
			if (S.bIsPlayer)
				S.bIsPlayer=False;
			if ( S.Enemy != None && S.Enemy.IsA('ScriptedPawn') )
			{
				S.Hated = None;
				S.Enemy = None;
				S.bHunting = False;
				if (S.OldEnemy != None && S.OldEnemy.IsA('ScriptedPawn'))
					S.OldEnemy = None;
				if ( S.Orders != '' )
					S.GotoState(S.Orders);
				else
					S.GotoState('Waiting');
			}
			S.Team = 1;
		}
	}
}

defaultproperties
{
     bHidden=True
}
I'll bet you haven't seen it working in original MH, time come to restore order.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Thu Sep 11, 2014 12:43 am

Silence is just cute. Another kind of mapping triggers spirit of server to cry in console:

Code: Select all

...Error - use creature factory to spawn pawns
...Error - use creature factory to spawn pawns
...Error - use creature factory to spawn pawns
I'm not sure if even in 2014 after many years of UT anyone can deal properly with these. If not, I'm not worried, enjoy the mess and I'll enjoy a peacefully console without those lines, else spoken I found another solution to ruin old spawnpoints using mine (basically to fix this, you need Editor to repair map), also my SpawnPoint will fool ThingFactory to negotiate with them (even I removed some check to increase stability and to gain speed). You read well, some people are using ThingFactory not CreatureFactory and that's why we have those messages. Also more than 16 SpawnPoints are useless because internal ThingFactory's array will capture firsts 16 SpawnPoints others being useless. I'm not expecting to see some people returning to UT in purpose to fix their "works" so have fun ruining them if you are hating dumb spam into your server-console.

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Wed Oct 01, 2014 5:21 pm

This isn't probably a fixes debate.

I was testing XC_Engine01 and 02. I'll keep 01. 02 was addressing to AMD core problems but it contains some GetWeapon fix. Not sure why, in Uscript a small actor might tune up monster and Bot very OK. Problem... server looks like crashed or suddenly quit without any valid readable log. Not happened in version 01. If GetWeapon fixation mocks Uscript fixes then I expect troubles.
Attached info: XC_Engine is a new engine extension working with original one in purpose to perform a few fixes.

A note:
I removed fixation related to PlayerCanSeeMe crash from my MH mod, and the crash has successfully returned. XC_Engine01 doesn't include major NATIVE problems related to these old crashes and neither "02", but "02" has some sort of fix for GetWeapon whatever. So I'm adding back my fixes against PlayerCanSeeMe stupidity.

I'm gonna test more maps played with Bots. Also daughter will help me (a kid is always a need in game to discover issues based on curiosity age specific).

If GetWeapon was supposed to do a Skaarj or monster weaponry fix is a wrong move. Evil Spirit comes from a messed timer coded into BotPack. Any new game-type ought to get rid of crap coded by Epic firing a double timer or multiple timer messing up all things timer-related. There IS NOT ANY MAJOR BUG into Skaarj style just a bIsPlayer dumbness which could be avoided but it was not. Anyway doing a mod with a timer timing Level Vs Mod, weapory replacement will work normally even for monster armed. We simply don't really need some GetWeapon fix. Also that RateSelf error of Bot multiple armed comes from a messed function copied from Botpack with 0 fix. Bot SHOULDN'T be forced to switch weapon to next one loaded. LEAVE A.I. to manage themselves weaponry and will see 0 error. With other words A.I. mess up weaponry based on Uscript from Mutator and or bad coded timer not from Native stuff.

Thanks for reading!

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Wed Oct 08, 2014 11:55 am

This thing used into game-types with monsters looks more friendly as long as regenerating timers match Level's timer.
Belongs to game-controller. Also PreBeginPlay will have it removed as long as we call it in INITGame ONCE.

Code: Select all

function SetGameSpeed(Float T)
{
	local float InitialSpeed; //Preserve backup slot

	GameSpeed = FMax(T,0.1); //Get value configured
	InitialSpeed = GameSpeed; //Save this one
	SaveConfig(); //Trigger saving - it looks like SaveConfig() is repeated, might screw it later
	GameSpeed = FMax(T*1.000001, 0.1); //Some love here
	Level.TimeDilation = GameSpeed; //Perform timing
	SetTimer(Level.TimeDilation, true); //Launch timer
	GameSpeed = InitialSpeed; //put value back to be later saved correctly
}

User avatar
Nelsona
Posts: 998
Joined: Sun Mar 06, 2011 11:45 am
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
Location: Still at Keyboard
Contact:

Re: Need More Fixes ?

Post by Nelsona » Wed Oct 29, 2014 1:01 pm

Okay, after testing and crashing server toying with XC_Engine and some really dumb maps, I decided to reconsider my position vs monster visibility and Bot visibility through doors looking like stupids. Using default UT bug (monster doesn't react at Bot only triggered by Game-Core) I studied how works default "Trace" function in UT (I'll tell you more about this thing later). Function helps me if I call by example "if (ValidSight(Monster, Bot))" and I have:

Code: Select all

function bool ValidSight(Pawn S,Bot aBot)
{
	local bool result;
	local actor HitActor;
	local vector HitLocation, HitNormal;

	result=False;
	if ( S == None || aBot == None )
		result=False;
	HitActor = Trace(HitLocation, HitNormal, S.Location, aBot.Location, false);
	if ( HitActor == None )
		result = True;
	return result;
}
I've been using here "S" for any pawn (not only monster). Also I put exception in "AssesBotAttitude", Bot won't hate pawn behind door at first encounter - pretty good to not see it firing door useless. Placing ValidSight near visibility checking will wrap well Bot attitude toward monster.

As for function "Trace" I checked some information at Wiki. Epic seems to failed reading WIKI - LOL :mrgreen: . They simply couldn't do a better function for Monster and Bot named "CanFireAtEnemy" based on "Trace". Anyone playing more time with Bots could see how they sometimes tends to fire in wall in enemy direction, else even Monsters tends randomly to stay firing useless in a stupid "KeepAttacking" featured content.
TRACE will draw a line or a tunnel between 2 points and checking if an actor is encountered in this space, having 2 options:
- consider actors encountered an returning True (is a barrier between them);
- consider only geometry ignoring actors (decorations, pawns, etc.).
Drawing a line from monster's center to Bot's weapon-fire-point and considering all possible actors, first actor in cause is exactly the monster's body. If this actor is monster, Bot presumes can fire weapon also checking sometimes (not always) a "FastTrace" which ignores doors, so will ignore the option for the second actor which might be a wall or other crap: floor roof, etc. Entire deal makes possible an usual mess, Bot being called stupid based on this additional... habbit. First thing that would be a need to be checked, would be a direct check ignoring actors combined with the second one, or tracing a line staring from outside of monster cylinder. Because I'm hating this dumb deal I think the time come for other MHBots for my controller. I gotta look for a direct menu and game access to override defaults. Is a bit of work around this problem but I hope I'll solve it finally.

User avatar
Hermskii
Site Admin
Posts: 8500
Joined: Sun Jul 10, 2005 9:56 pm
What is the middle number? (one, TWO, three): 2
ExtraAntiSpam: Blue
extraextraantispam: Yes
NoMoreSpam: Silver
Location: Houston, Texas
Contact:

Re: Need More Fixes ?

Post by Hermskii » Thu Oct 30, 2014 10:26 pm

I am so glad I have all of this here. Thanks!
~Peace~

Hermskii

Post Reply