Challenge class on high level of difficulty

Discussions about Coding and Scripting
User avatar
Gadavre
Experienced
Posts: 140
Joined: Sun Jan 18, 2015 7:55 am

Challenge class on high level of difficulty

Post by Gadavre » Sat Nov 18, 2017 7:12 am

Hallo! How to do it? My goal is to call class"ShootTarget in PostBeginPlay on a high level of difficulty (inhuman and godlike)

Code: Select all

function PostBeginPlay()
{
       Super.PostBeginPlay();
      Spawn(class'ShootTarget');

}

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 » Sat Nov 18, 2017 12:33 pm

Perhaps something like:

Code: Select all

function PostBeginPlay()
{
    Super.PostBeginPlay();
    if (DeathMatchPlus(Level.Game).BotConfig.Difficulty >= 6) {
        Spawn(class'ShootTarget');
    }
}

User avatar
Gadavre
Experienced
Posts: 140
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre » Sat Nov 18, 2017 4:44 pm

I wrote:

Code: Select all

function PostBeginPlay()
{
        Super.PostBeginPlay();
        if (Level.NetMode == NM_Standalone && DeathMatchPlus(Level.Game).BotConfig.Difficulty >= 6)
                Spawn(class'ShootTarget');
}
The code does not work. Are there any other solutions?

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 » Sat Nov 18, 2017 7:02 pm

Did you try the code I gave you "as it is" at all? Just to check if it actually worked?

You should only add your own stuff into it once you've tested the given solution "as is" and after you see it working.
Picking up a solution, adding your own stuff in the mix, trying and not working, and then coming back saying "it doesn't work", it's a bit disrespectful to say in the least, don't you think?
You're not helping yourself that way at all.

Also, you missed to say what exactly didn't work... did it compile? Does it run but throws some kind of warning or error into the log file? Doesn't it run at all?

Assuming that you're running this in a practice session, and that your actor is actually something you have placed in a map rather than spawning it from something else, and that it compiled successfully and you simply didn't check the logs for warnings, I think I may have a clue on why that might indeed not work.
So this might work instead:

Code: Select all

function PostBeginPlay()
{
    Super.PostBeginPlay();
    if (DeathMatchPlus(Level.Game).BotConfigType.default.Difficulty >= 6) {
        Spawn(class'ShootTarget');
    }
}
But do try this as it is first, do not add anything to it until you're sure this bit works as intended.

If it still doesn't, please give more information, such as which class are you extending (the full class code is preferable even), how are you using it (are you spawning it or adding it to a map), in which gametype are you testing this, perhaps even the overall context of what you want to do.

I would also suggest you to use something like UnCodex to navigate through the code so you can also understand how things are connected and where to retrieve the info you want, such as here for example:
http://www.madrixis.de/undox/classtree.html
in this specific case, these classes in specific:
http://www.madrixis.de/undox/Source_bot ... tinfo.html
http://www.madrixis.de/undox/Source_bot ... hplus.html

User avatar
Gadavre
Experienced
Posts: 140
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre » Sat Nov 18, 2017 8:45 pm

nogardilaref
Sorry. Your code works!!! :tu:

Code: Select all

function PostBeginPlay()
{
           Super.PostBeginPlay();
           if (Level.NetMode == NM_Standalone && DeathMatchPlus(Level.Game).BotConfigType.default.Difficulty >= 6) 
              Spawn(class'ShootTarget');
}
Class 'ShootTarget' as a bot controller allows bots to shoot the player at long range. Bots in the original game can not do this. See how this feature works in this video
https://youtu.be/O2pvSggE7ok

I used this line

Code: Select all

if (Level.NetMode == NM_Standalone)
, because this Feature does not work in the network game. I dont know much about multiplayer code. My Modification works with this Feature in multiplayer very slowly. And so this line removes this feature from the network game. If I give you the code in a personal message, can you fix it?

User avatar
sektor2111
Godlike
Posts: 5336
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Challenge class on high level of difficulty

Post by sektor2111 » Sat Nov 18, 2017 9:15 pm

Level.NetMode == NM_Standalone - means this thing runs ONLY in LOCAL GAMES - StandAlone.
For having full operation you can get rid of this condition. It's only restricting action to local gaming... What for this restriction ?
Else I would use Level.Game. Difficulty for Net games - Spawn that controller when difficulty is 3 - game difficulty, not Bot's difficulty.

User avatar
Gadavre
Experienced
Posts: 140
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre » Sat Nov 18, 2017 9:26 pm

sektor2111 wrote:Level.NetMode == NM_Standalone - means this thing runs ONLY in LOCAL GAMES - StandAlone.
For having full operation you can get rid of this condition. It's only restricting action to local gaming... What for this restriction ?
Without this restriction, one coder told me that a game on the net with bots would not be possible. This Feature (class'ShootTarget') slows down network game with bots.

User avatar
sektor2111
Godlike
Posts: 5336
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Challenge class on high level of difficulty

Post by sektor2111 » Sun Nov 19, 2017 12:18 am

Gadavre wrote: one coder told me that a game on the net with bots would not be possible.
That one perhaps is drunk or doesn't have any clue what is NM_StandAlone and probably not about "!=" VS "==" operators. With that condition it won't work in Net games EVER. Why mutator should be blocked to not run in servers ?
Next chapter
Gadavre wrote:...slows down network game with bots.
depending how is coded, I coded dumb stuff for maps in "ShootTarget" purposes with no single issue to not mention each seconds brain which MBot_F is using when XCGE is detected + map runners because Paths were crapped up. A few minutes ago I was playing some MH with 4 Bots and 700+ creatures. What exactly slows down a game with 7 Bots when I had over 700 creatures, with at least 30 of them tracking me ?
I used a client 1400 MHz AMD CPU and server is a PentiumD 2800 MHz - game was smoother as oil, but I had to stop because I had a lot of hours playing (today I was free like birds) and having fun and I feel tired a bit.

No, man, if you check things with logs, clocking functions, testing games/mods in different maps, you will step ahead and you don't have to listen at presumptions. With some exercises you'll reach to your goal not with riddles and stories which others are saying. Bot is a bit of resources consumer but is not that evil as described by Bot haters, trust me those talking crap are unable to put up a clean and special Path-Net and neither to write a good A.I. rating stuff... they are hating Bots and that's all.

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 » Sun Nov 19, 2017 12:35 pm

So, first an explanation why:
DeathMatchPlus(Level.Game).BotConfig.Difficulty
doesn't work, and why:
DeathMatchPlus(Level.Game).BotConfigType.default.Difficulty
does.

In my understanding, your actor is placed in the map itself, so the chain and order of events will be fairly different from an actor which is spawned in the map after it starts.
The ChallengeBotInfo is only spawned by the DeathMatchPlus class on PostBeginPlay, and it so happens that, although the DeathMatchPlus is spawned before the map play really starts, it's still spawned after anything else already placed in the map.

So when the time comes when the PostBeginPlay function is called, the DeathMatchPlus one is one of the very last ones to be called, hence by the time the same event is called in your actor, the BotConfig is still None since PostBeginPlay didn't even run yet in DeathMatchPlus.
Thus, rather than using the BotConfig reference, the BotConfigType can be used instead, since it's a class reference set in the defaults of DeathMatchPlus.

This is not necessarily the most correct way to do it, it was actually more to confirm if this was really the case, as there are still ways to get a valid BotConfig reference (such as using PostNetBeginPlay instead, which is called after PostBeginPlay).



As for the online play, I understand what you wanted to make with the extra NM_Standalone condition, but just like Sektor said, it's only slow in multiplayer if your addition is coded in a really bad way.
But I even am going ahead and say that, even without looking at your code, I can pretty much guess that it's actually not slow at all, although it's perceived as such because your target probably moves around, and in an online game it appears to be "laggy" when doing so.

If this is the case, then this is not the mod being slower, it's just a classical case of the multiplayer aspect of the code not having been set up properly. The mod is probably actually as fast as standalone, but it's missing some tweaks so its movements are smooth online.

As for the PM, I guess you want to avoid to post here the whole code, perhaps in fear of it getting stolen, and I am sorry but I simply do not have the time to dedicate to your problem right now.
So, the best way is really to post here the full code, from at least your ShootTarget class, even because that way will get more help from more directions, and me alone wouldn't probably be able to help you as much as more people in the forum together.

User avatar
papercoffee
Godlike
Posts: 9869
Joined: Wed Jul 15, 2009 11:36 am
Personal rank: coffee addicted !!!
Location: Cologne, the city with the big cathedral.

Re: Challenge class on high level of difficulty

Post by papercoffee » Sun Nov 19, 2017 12:38 pm

sektor2111 wrote:they are hating Bots and that's all.
Because they don't know how to path or play maps which are bad pathed and then are the bots the culprits for a bad gaming experience. :wth:

User avatar
Gadavre
Experienced
Posts: 140
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre » Sun Nov 19, 2017 7:56 pm

nogardilaref, sektor2111
Class'ShootTarget' is external controller for bots and allows bots to shoot the player at long range. How?

In the middle of each player's head is an invisible object. Let's call it ShootTarget. If the bot sees only this object, then it shoots at the object and the player dies. Thus, the bot can kill any player, which shows one head. This function is implemented for DeathMatchPlus and TeamGamePlus. If the bot carries a flag, then it can not shoot at ShootTarget. Bots Campers in ctf can also shoot at each other at long range. TSniperRifle - the only weapon in the game. This code uses a timer, but in another way it was impossible to achieve the goal. I'm a novice coder and I did not write this complex code. If you have a good desire to help, then I ask help me to optimize the code for maximum performance online. But do not change the values ​​of my variables, I spent many days to fine-tune.

With respect to all the talented coders of this site...

P.S. Sorry for my English. Perhaps you understand me bad. But I try to write accurately. English is not my native language.
You do not have the required permissions to view the files attached to this post.
Last edited by Gadavre on Mon Nov 20, 2017 6:44 am, edited 4 times in total.

User avatar
sektor2111
Godlike
Posts: 5336
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Challenge class on high level of difficulty

Post by sektor2111 » Mon Nov 20, 2017 12:10 am

I'll look there but first I have to talk about some hints. In XCMH I used another class entirely written by Self. It does a slow loop through pawns for sorting and counting them, having small sleep times in order to keep game smoother. I used similar method for preventing that crash from MapVoteUL2xx which was crashing at 1500 1700 maps even if it was supposed to load 2047 (...). If you learn to setup loops in a state code server will not even notice if is a load somewhere or not is like a background process, similar strategy I was using in MHBotyman4 tester. It goes passive and is checking from time to time what's the deal. When paths are found it comes to life spawning "routes".
Higor recommended states - it looks like in UE1 states are OK if are correctly written, especially when stuff doesn't need an instant load with heavy iterations at a moment. A bot will aim, after 50-100 milliseconds another one is aiming and so on and this way won't hurt nothing. You don't need timers with "foreach" for such a task.
Now let me see what is there...
Edit:
Okay, I think I'll write another stuff... an actor tracker... Else I uderstand why you say - english of course is not my native language (and for sure won't be - I think) but these small codes can be solved without any English Academy. Will take a while because now it's late and tomorrow I'll be at work...
papercoffee wrote:
sektor2111 wrote:they are hating Bots and that's all.
Because they don't know how to path or play maps which are bad pathed and then are the bots the culprits for a bad gaming experience. :wth:
Yes, well said, they don't have any clue how bad pathed are some maps (guessing work mainly) but hey, Bot is stupid because cannot do whatever stunt, not the moron placing Nodes in walls and other bad spots... ahah...

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 » Mon Nov 20, 2017 2:01 pm

Just checked the code overall, and this is just server-side stuff, nothing to be processed by the client, which makes things a lot easier when it comes to multiplayer.

Multiplayer-wise, you could just set the RemoteRole=ROLE_None in the default properties, and what will happen is simply that, since this actor only exists server-side, this will make sure it never is even attempted to be replicated at all, since there's no need for that.

Code-wise, I didn't thoroughly analyzed the code (no time for that level of help right now, as I mentioned earlier), but there's a glaring dangerous design flaw in the code which may lead for your ShootTarget to be spawned over and over and over, and it will in fact be much worse in a multiplayer game when there are more players in the game, since in each Timer iteration, it has the potential to spawn one ShootTarget per player.
I saw that you control this somewhat by assigning owners and whatnot, but this is an awful way of doing it.

Instead, here you should apply the very first "S" of "SOLID" principles in object oriented programming, which stands for SRP (Single Responsibility Principle).
This principle simply states that a class should only have a single reason to change, and should only be responsible to do and represent a specific thing.

And here, you're mixing 2 different responsibilities into the same class:
1 - The responsibility of spawning and managing the spawned targets;
2 - The responsibility of actually being a target.

In other words, rather than having all the code in a single target, you should perhaps split it into two, something like a ShootTargetManager and a ShootTarget, where the ShootTargetManager does all the spawning and require management of each ShootTarget, without ever needing to assign owners and whatnot to itself, while ShootTarget is simply a target, which at most updates itself in terms of position, and may or may not call back the manager when certain events happen perhaps.

User avatar
Gadavre
Experienced
Posts: 140
Joined: Sun Jan 18, 2015 7:55 am

Re: Challenge class on high level of difficulty

Post by Gadavre » Mon Nov 20, 2017 4:05 pm

nogardilaref
So I have to add RemoteRole=ROLE_None in the default properties of class ShootTarget? It can remove the lag in the game with bots?

If you have more time, can you help to write your version of ShootTarget and ShootTargetManager? If you agree, then please contact me via e-mail (gadavre@mail.ru). I can long not be on this website.

Perhaps sektor2111 will write their version and we compare both versions for performance in a multiplayer game..

The Maker of the best ShootTarget optimization will be indicated by me in the ReadMe of new version.

This is my Modification. In this topic this program is still a mutator, but in the new version the program will be called a modification. It will be right. InstaSniper allows you to play already in a single company. In the near future I will add Mod Menu
viewtopic.php?f=7&t=11303
Last edited by Gadavre on Mon Nov 20, 2017 8:22 pm, edited 5 times in total.

User avatar
sektor2111
Godlike
Posts: 5336
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: Challenge class on high level of difficulty

Post by sektor2111 » Mon Nov 20, 2017 6:44 pm

I will use while loop inside a state, if you have something smoother use it. Aside, I will NOT SPAWN nothing for player/bot target, Bot seeker is automated by native code in shooting something, that decoration doesn't make any sense and neither forcing Bot to rotate for target it will natively rotate itself. Not a single time I spawned shooters see MH-BatlingLottery entirely done by me. Spectate what are doing Bots there. Map is in link location posted on my signature.

Around performance you have to excuse my poor stuff from this time, but I had to build a case first for mounting a PIII at 450 MHz for testing code's speed in a weak environment, old case it's used for another machine which is moving way better but I can put clock down at 1GHz if this test is required for figuring performance, for the moment I can't go lower.

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
Show
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...