Challenge class on high level of difficulty

Discussions about Coding and Scripting
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Challenge class on high level of difficulty

Post by nogardilaref »

The RemoteRole=ROLE_None may improve things a bit, since it avoids the ShootTarget to be replicated to the owner at the very least, but not by much.
The biggest problem may be that you have a class spawning itself in a Timer, and that's pretty much the "fork-bomb" style of coding right there, given that you run the risk of the class spawning itself indefinitely.

And like I said previously, I don't have that kind of time, so no, I cannot write you one.
Feel free to ask someone else, but if you want a friendly advice, is best if you start at least trying figuring it out by yourself.

I know you're probably new at this, and that's fine (we've all been novices at this ourselves too at one point), but you will only be able to evolve and make better things if you put in the work yourself as well, rather than asking others to do it for you.
I gave you the direction and explanation, but you're the one who has to put in the work.
User avatar
Gadavre
Skilled
Posts: 169
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre »

sektor2111 wrote:
EDIT: Something basic - is not bad for any Difficulty level so I did not added any condition. This thing is closer to MBot's secondary brain... but is not a toll attached, is a mutator. For anyone interested I wrote something that can be used/compiled and logs speaks + Windowed game confirms the action.
Spoiler
class ShootingEm expands Mutator;

var Pawn P, Pe;

event PreBeginPlay()
{
//Nothing Executed
}

event PostBeginPlay()
{
InitialState='TrackShooting';
}

final function bool CleanSight(Pawn aPawn, Pawn OtherPawn)
{
local bool bResult;
local actor HitActor;
local vector HitLocation, HitNormal;

bResult = False;
if ( aPawn == None || OtherPawn == None )
bResult = False;
HitActor = Trace( HitLocation, HitNormal, OtherPawn.Location, aPawn.Location, False );
if ( HitActor == None )
bResult = True;
return bResult;
}

Auto State TrackShooting
{
Begin:
log ("Bot Tracking has been started...",'ShootingEm');
LoopingCheck:
Pe = None;
P = None;
P = Level.PawnList;
While ( P != None )
{
if ( Bot(P) != None && P.Health > 0 && ( P.Enemy == None || !P.LineOfSightTo(P.Enemy) && !P.bHidden ) )
{
//log ("#1");
if ( Level.Game.bTeamGame )
{
for ( Pe=Level.PawnList; Pe!=None; Pe=Pe.nextPawn )
{
if ( Pe != P && !Pe.bDeleteMe )
{
//log ("#2");
if ( !Pe.bHidden && Pe.Health > 0 && Pe.PlayerReplicationInfo != None )
{
if ( P.PlayerReplicationInfo.Team != Pe.PlayerReplicationInfo.Team )
{
if (CleanSight(P,Pe))
{
log (P.GetHumanName()@shooting@Pe.GetHumanName());
Bot(P).ShootTarget(Pe);
Bot(P).Enemy = Pe;
Pe = None;
break;
}
}
}
else if ( !Pe.bHidden && Pe.Health > 0 && Pe.DrawType == DT_Mesh
&& Pe.AttitudeToPlayer == ATTITUDE_Hate && Pe.PlayerReplicationInfo == None
&& Pe.ReducedDamagePct < 0.95 && Pe.ReducedDamageType != '' )
{
if (CleanSight(P,Pe))
{
log (P.GetHumanName()@shooting@Pe.GetHumanName());
Bot(P).ShootTarget(Pe);
Bot(P).Enemy = Pe;
Pe = None;
break;
}
}
}
}
}
else
{
//log ("#3");
for ( Pe=Level.PawnList; Pe!=None; Pe=Pe.nextPawn )
{
if ( Pe != P && !Pe.bHidden && Pe.Health > 0 && Pe.DrawType == DT_Mesh )
{
//log ("#4");
if (CleanSight(P,Pe))
{
log (P.GetHumanName()@shooting@Pe.GetHumanName());
Bot(P).ShootTarget(Pe);
Bot(P).Enemy = Pe;
Pe = None;
break;
}
}
}
}
Sleep(0.2);
}
Sleep(0.05);
if ( P != None ) //Recheck because during sleep something evilized might happen
P = P.NextPawn;
else
Break;
}
Sleep(RandRange(0.50,1.00));
if ( Level.Game != None && Level.Game.bGameEnded )
GoTo('JobDone');
else
GoTo('LoopingCheck');
JobDone:
GoToState('');
}
This is not a bad-ass mutator is a toy good even for medium skilled Bots making them different. Yeah, I did tests even with original Bot - now let me remove it...
Note: By compiling it, might go in a "ServerActor" chain or any authoritative thing without to be in packages...
I want to connect your class to my main class. The main class is called InstaSniperMutator I write in it:

Code: Select all

class InstaSniperMutator extends Mutator 

function PostBeginPlay()
{
              Super.PostBeginPlay();
              Spawn(class'ShootingEm');
}
In class ShootingEm, the parent class must be Decoration? I already have class Mutator in the main class.

will the bots campers in ctf shoot at Players and another bots campers? In class ShootTarget bots can do it.
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Challenge class on high level of difficulty

Post by sektor2111 »

What is the problem with this decoration obsession ? This is what I did for ANY Long range SNIPER, a common mutator. Else you can turn it into a keypoint with bStatic False. Is this such a hard task ? "class some_crap expands keypoint;".
Also can be a relevant actor for server-side, and this thing doesn't even need to be in packages or a component of it, it's a fragment of code which client doesn't even use, this is server's task.
User avatar
Gadavre
Skilled
Posts: 169
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre »

nogardilaref

Reborn, the main developer of ShootTarget, answers you:
"This line

Code: Select all

RemoteRole=ROLE_None 
does not help. The problem is that at some point, the target loses contact with the player, and respawned again. That is, the number of targets increases until the computer hangs.
I then included the following line in the script:

Code: Select all

if (owner != none && P != Owner) 
                   Spawn(class'ShootTarget',P,,(P.Location+vect(0,0,64)));
But it did not help. The game with bots now on the network with this class is impossible. We need some other way to bind the targets to the "live" players."

Maybe you have an idea how to change this line correctly?

I'm thinking of adding these 2 lines to the defaultproperties. Usually all multiplayer mutators and modes have them:

Code: Select all

defaultproperties
{
        RemoteRole=ROLE_SimulatedProxy
	bAlwaysRelevant=true
}
Spoiler
Last edited by Gadavre on Tue Nov 21, 2017 7:10 am, edited 1 time in total.
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Challenge class on high level of difficulty

Post by sektor2111 »

SimulatedProxy for things which player will not use is pointless. If mutator has visual things for player it needs to be replicated properly, but this "Keypoint" or whatever "mutator" which I wrote simply does the job from server because CLIENT DOESN'T CONTROL A.I. so adding remote role for this thing is a non-sense. I'm not going to repeat that stacking actors in the initial way of mutator is a wrong option by default. Spawn decoration for player turn bot to it and force to shoot = Borked stuff. I don't know who had this idea but I'm not writing such things, I can make Bot to shot something without anything stacking in map.
Keypoint or whatever can be spawned by mutator. If you did some tests we can speak more I'm not going to debate stacking decorations as long as what I did do works. Test it as a standalone thing and then you can copy the code where you need it. You can remove that "scientific" decoration because is does damage. If you look well at my code it is based on probing with logs not by guessing.
If you are not bother to check it then I'll share in mutators section for whoever needs it.
EDIT:
Yeah, this can be a secondary mutator in package which admin can load if uses Bots in server, if not, there is no need to mess with it and forcing it to spawn.
User avatar
Gadavre
Skilled
Posts: 169
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre »

I went to my dedicated lan server. but my weapon became invisible. But I can take it. How to fix it?
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Challenge class on high level of difficulty

Post by nogardilaref »

Gadavre wrote:nogardilaref

Reborn, the main developer of ShootTarget, answers you:
"This line

Code: Select all

RemoteRole=ROLE_None 
does not help. The problem is that at some point, the target loses contact with the player, and respawned again. That is, the number of targets increases until the computer hangs.
I then included the following line in the script:

Code: Select all

if (owner != none && P != Owner) 
                   Spawn(class'ShootTarget',P,,(P.Location+vect(0,0,64)));
But it did not help. The game with bots now on the network with this class is impossible. We need some other way to bind the targets to the "live" players."
But that's pretty much what I just said above:
nogardilaref wrote:The RemoteRole=ROLE_None may improve things a bit, since it avoids the ShootTarget to be replicated to the owner at the very least, but not by much.
The biggest problem may be that you have a class spawning itself in a Timer, and that's pretty much the "fork-bomb" style of coding right there, given that you run the risk of the class spawning itself indefinitely.
Besides, I already did a fair bit of explanation, and I already stated how you could model your classes instead to avoid that problem altogether, and yet you keep asking us the same questions and to do things for you.
I don't mind to explain things again and in a different way if you didn't understand, and to even use "samples" of code to show what I mean, but I do mind when what you're essentially requesting is for us to do all of the work for you, with no interest from your side to actually learn what's going on, and I am not going to participate on that.

This is backed by the fact that you asked me and Sektor to each one to do our own version to check which one was the fastest... wat?

So I am done here, good luck. :thuup:
User avatar
Gadavre
Skilled
Posts: 169
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre »

nogardilaref
I do not understand,what part of the code forces the modification to spawn the target endlessly? Сould you use "samples" of code to show what you mean?
User avatar
sektor2111
Godlike
Posts: 6403
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Challenge class on high level of difficulty

Post by sektor2111 »

Gadavre wrote:Сould you use "samples" of code to show what you mean?
You can add a log in PostBeginPlay from this ShootTarget and see how many spawns in a game running for 5 minutes, or if exist a chance to spawn.

Code: Select all

function PostBeginPlay()
{
        log (Self.Name@has spawned...);
        Super.PostBeginPlay();
        SetTimer (1.0, true);
}
Now do draw your conclusions...
First of all if I'm looking better and trying to figure 3 Player instance - I'm in fog.
If doesn't have owner will, set one. If have owner but others are not owner spawn this thing for them, Then each of these spawned things will do the same stuff being the same class.
And that's all if you insist with this useless thing you are on your own. BOT CAN FIRE AT PLAYER WITHOUT Decorations with timers. Else what if 3 players are traceable by Bot ? Which one is target and when ? Decoration is in other location. Actors owned generally doesn't have to move with owner as a default rule.
Else spoken what is this after all ? Player is moving, does decoration track player location ? I don't see this. Give to this thing a mesh (a lamp or such) make it not hidden and see directly what's going on with another player - that's the problem if I'm not mistaking - yeah go figure with 2 people, you can simulate 2 players in a LAN server. Draw your conclusion there.
Last edited by sektor2111 on Tue Nov 21, 2017 6:55 pm, edited 1 time in total.
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Challenge class on high level of difficulty

Post by nogardilaref »

OK, I will try to explain it through a code sample.

Right now, you have something like this:

Code: Select all

class T extends Actor
{
    function PostBeginPlay()
    {
        ...
        SetTimer(1.0, True);
    }

    function Timer()
    {
        ...
        Spawn(Class'T');
        ...
    }
}
This is an ultra simplified version of what you have.
So, do you see the problem now?

In this example, class T will be spawned indefinitely over time.
Why? Because after T is spawned, the newly spawned version will also run its own PostBeginPlay, which sets its own timer, which then also spawns more T actors, and so on and so forth.

And that condition which was added, was simply a "patch" around this kind of problem, in order to prevent the spawn. However, like its original developer mentioned, there are times where that condition will evaluate to "true" again and the whole process repeats itself once again over time.

Which is why I said that you should split this into 2 classes, as something like this:

Code: Select all

class TManager extends Actor
{
    function PostBeginPlay()
    {
        ...
        SetTimer(1.0, True);
    }

    function Timer()
    {
        ...
        Spawn(Class'T');
        ...
    }
}

Code: Select all

class T extends Actor
{
    ...
}
As you see, the responsibility of spawning the T class here was moved to a new TManager class instead, while T doesn't do any spawning whatsoever, and this makes code actually much simpler on both sides.
This prevents completely the possibility of spawning the same actor over and over and over again over time, at least in this way.

From here, this doesn't necessarily solve your problem of spawning over time, but it's a starting point towards the actual fix, since from here you only have to worry about the actual conditions which warrant a spawn.
But I am only going to continue from here after you confirmed that you understood this, and after you already did any work yourself to split it like this (or in a similar fashion, the important thing is to keep the spawning code out from the target itself).
User avatar
Gadavre
Skilled
Posts: 169
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre »

nogardilaref
How to connect this "TManager" to the main class?
For example, so?

Code: Select all

class InstaSniperMutator extends Mutator config(InstaSniper);

function PostBeginPlay()
{
        Super.PostBeginPlay();
        Spawn(class'TManager');
}
Can it be easier and faster so? This will solve the problem? I replaced the class "ShootTarget" of the class "ShootTarget" with a class "Actor"
ForEach AllActors(class'PlayerPawn', P)
{
if (P.Health <= 0 || P.weapon == None)
continue;
if (owner == none)
SetOwner(P);
if (owner != none && P != Owner)
Spawn(class'Actor',P,,(P.Location+vect(0,0,64)));
if (P == Owner)
{
if(P.bIsCrouching)
SetLocation (P.Location + Vect(0,0,4));
else
SetLocation (P.Location + Vect(0,0,29));
}
}
nogardilaref
Masterful
Posts: 577
Joined: Tue Jun 20, 2017 1:00 pm
Personal rank: ⚋⚊⚌☰⚞⌖⚟☰⚌⚊⚋

Re: Challenge class on high level of difficulty

Post by nogardilaref »

TManager was just a name I came up with to use as an example so I could explain things to you in the simplest way I could muster.
Did you understand what I meant with this separation?

Having that said, if you have your own mutator class, in this specific case the "manager" could be the mutator itself, it doesn't need to be a separate class.
Sometimes it may make sense to split the mutator from the manager, but I don't think this is one of those cases.

Also, the Actor class should not be used directly, it is a base class and should be treated as such. Extend from it instead with your own class, even because it's highly likely that you will need to customize it anyway, be it with events/functions or default properties.
Furthermore, the whole point of using a separate class to spawn the targets is exactly to avoid the kind of conditions you have shown again in your code above.
Post Reply