View Full Version : script problem: small mutator to punish player for killing monster
I just started workin' with scripts for UT.
Here what i want to do:
There are a few friendly monsters in my map, and i want to punish a player for killing them by taking all their heath.
Here's what i got so far, most of it was acomplished by tearing down others' code (is there an other way of learing???) :
Killcow.uc (the name of the script) doesn't get compiled. Any suggestions?
// mutator hook to prevent deaths
// WARNING - don't prevent bot suicides - they suicide when really needed
function bool PreventDeath(Pawn Killed, Controller Killer, class<DamageType> damageType, vector HitLocation)
{
if( (Killed.bIsPlayer != false)
{
if( ( Killer != None ) &&
( Killer.bIsPlayer) )
{
Other.GiveHealth( -199, 199 );
}
}
return Super.PreventDeath( Killed, Killer, damageType, HitLocation );
}
thx,
Grz, Jura
edit: took out a typo.
King Mango
12-10-2004, 03:06 PM
Sorry not much of a coder, but maybe in the meantime you could try setting your friendly monster's health UBER high and then attach a trigger to each of them which goes to a special event that damages the instigator?
I know just a band aid if that, but maybe it would work.
Good idea!! but that didn't quite work. I can trigger on the death of a monster, but can't make the damage (which is available in that trigger) hit the instigator.
Maybe a way to bypass this? Or back to the script?
King Mango
12-10-2004, 06:11 PM
I was thinking of trying it this way:
give each monster a unique events>tag
Then actually attach a trigger using the AttachTag feature in the properties>movement section of the trigger properties.
Have that trigger call a special event set up to damgeinstigator.
Been a while since I've been in UED2 but I think that's how it would work.
Or to do it your way I think (Blitz correct me if I'm wrong here) you would have to get the controller of the player from damageinstigator and then you might be able to determine who did it.
first of all thx for the replies.
I'm not getting there, i set up in a few ways but didn't get there.
Here is what i tried:
got 3 actors
- The friendly monster
Events.Event abusecow
Events.Tag cow99
- Special event
Events.Event punish
Events.Tag abusecow
Movement.Attachtag Cow99
- Special event
Tag punish
Movement.Attachtag Cow99
SpecialEvent.Damage 199
or
got 3 actors
- The friendly monster
Events.Event abusecow
Events.Tag cow99
- Special event
Events.Event punish
Events.Tag abusecow
Movement.Attachtag Cow99
- Special event
Tag punish
Movement.Attachtag abusecow
SpecialEvent.Damage 199
Maybe i didn't get what you were saying.
King Mango
12-10-2004, 07:01 PM
ok set up the cow like this:
events>tag:PleaseDontHurtMe
Pawn Health 1000000
Trigger:
Events>Event>ToldYouNotToHurtMeNoob
Movement>AttachTag>PleaseDontHurtMe
Collision>CollisionRadius>40
Collsion>CollisionHeight>40 or whatever apporximates a nali cow
Trigger>TriggerType>TT_Shoot
Special Event:
Events>Tag>ToldYouNotToHurtMeNoob
SpecialEvent>Damage>500
Message>Be kind to your animal friends
I don't think you have to mess with bStatic bNoDelete etc... with the trigger to get it to stick to the cow. So what you have is a trigger attached to a cow which calls a special event when shot. This way the trigger automatically knows who the instigator was and sends the damage in the special event. You'll have to make the cow healthy enough not to be killed cause I don't know how to attach a trigger repeatedly after a respawn.
If I made any mistakes with how a special event works you can find it on wiki no problem.
Unfortunatly this didn't work. I tried to mess around with bstatic, bMovable, bNoDelete. no result.
Stangely enough i got the message accross the screen but not all the time. Less does work than don't work, to be honnest.
The damage doesn't get inflicted at all.
2.47 am I'm off to bed now, tired and out of smokes.
Thx for your time K.Mango. If you got any idea's left let me know.
King Mango
12-10-2004, 08:04 PM
maybe you ahve to put a damage type in. Sorry I'm rusty. Try opening the actor class browser and under ummmm info>damage>utdamage there are several damage types. None of these will be what you want, and there are more I just can't remember right now. But try one of them and see what happens. I'm about to go to work so I won't be back for about thirteen hours... sweet dreams :D I'll take look on wiki and if I find anything I'll link you.
radio667
12-10-2004, 09:02 PM
Very Cool of You to Help :D - Thank You , King Mango !!!
TexasGtar
12-11-2004, 02:39 PM
I really like your idea. I mean, who would want to hurt a friendly nali rabbit for instance(unless you are in a Monty Python movie) I will think about a solution also. I think the King is on the right track tho. <putting on thinking cap>
I shall return.
Tried digging a little futher...
Thought that the problem was that i couldn't bind the trigger to the cow, because it's movable. So i tried with a brush.
Brush>tag = PleaseDontHurtMe
Trigger>Event = ToldYouNotToHurtMeNoob
Trigger>Message = TriggerTriggered
Trigger>AttachTag = PleaseDontHurtMe
Trigger>TriggerType = TT_Shoot
SpecialEvent>Tag = ToldYouNotToHurtMeNoob
SpecialEvent>Broadcast = True
SpecialEvent>Message = Be kind to your animal friends
SpecialEvent>Damage = 500
(Took out the subclasses for easier reading)
Here's what happens:
Shoot the brush nothing happens
Shoot the trigger, I get message "TriggerTriggered" and broadcast "Be kind to your animal friends". And no damage to instigator.
Conclusion, (correct me if i'm wrong here)
- The Link "Brush - Trigger" is not working.
- The instigator is not linked from trigger to special event.
Professor
12-11-2004, 04:55 PM
Hmm.. I just found this thread. You couldn't just subclass the Nali Cow, place one of the subclassed cows in your map, and override the TakeDamage function to do some detecting of who shot it then take the appropreiate actions?
Cheerz
Hmm.. I just found this thread. You couldn't just subclass the Nali Cow, place one of the subclassed cows in your map, and override the TakeDamage function to do some detecting of who shot it then take the appropreiate actions?
Abracadabra to me...
I'm clad i found that mutator hook in one of the scripts. (can't even remember where i found it) Then i started digging an found a few scripts that used the function "PreventDeath". Thought it was an easy way to punish the player. Think i was wrong.
Professor
12-12-2004, 08:13 AM
Abracadabra to me...
I'm clad i found that mutator hook in one of the scripts. (can't even remember where i found it) Then i started digging an found a few scripts that used the function "PreventDeath". Thought it was an easy way to punish the player. Think i was wrong.
Yeah whenever you look at the top of any script you'll always see a class declaration that goes something like
class SomeThing expands SomeThingElse;
The word expands above could also be used interchangeably with the word extends. What this means is that the class "SomeThing" is a "subclass(you will also hear subclasses referred to as children or child classes)" of "SomeThingElse". Now making that algebraic notation (lol) a little more clear knowing what you know now SomeThingElse is the "Parent" also known as the "Super Class" and "SomeThing" is the "Child" of the parent also known as the "Child Class" So Parent=Super Class and Child=Sub Class. You can see where this is coming from as it's a "family" type of structure which also even includes a thing called "Inheritance". A child (in this case) will *always* inherit any kind of diseases it's parent might have and you can also call those "diseases"............functions, states, variables, and defaultproperties. Functions, states, and variables are the 3 most common diseases a parent usually has to pass on the ther children. So now to clarify this a little further whenever you subclass(child) a superclass(parent) that subclass will "inherit" all of those nasty diseases the parent has like functions, states, variables, and etc. What this also means is you can subclass a class and not put any script in it at all and that subclass(child) will act exactly like it's superclass(parent). Weird I hear you say? How can a class run completely without any script added to it I also hear you say? The answer is "inheritance". Your subclass that didn't have any script at all in it "inherited" all of the script contained in its parent class. Well there's even more to it than that. Say for instance you subclassed a class and didn't put anything but the class declaration at the top of it. This new subclass will inherit all of the stuff the parent class has BUT <- and that's a very big but you can also be the "family doctor" and "Override" what is in the parent class simply by adding that function to the subclass(or the child class). In other words if you have a class that has a function that only adds 2 + 2 to yield 4 and you want it to do something else you have to subclass that class and override that function by adding that function to the subclass and in your subclass you have to name that function exactly the same and use the same parameters as the parent class uses only you will add the correct code to the subclass to make it do something else like add 4 + 4 to yield 8 instead of what the parent class does which is to add 2 + 2 to yield 4. Nice right? The child inherited that nasty 2 + 2 = 4 disease and you overrode the function and changed it into a nasty 4 + 4 = 8 disease!. Now if that's the only function from the parent class that you added to your subclass then that is the only place where your subclass will act differently from its parent. *Everything* else will be the same unless you pick yet another function that exists in the parent class, also add that to your subclass, and change that to your needs as well. Now this "inheriting" thing goes a bit further than just from a parent to a child but a child also inherits stuff from its grand parents (parents of the parents), great grand parents(Parents of the parents of the parents) and so on until you get to the highest class on the family tree called "Object". Object is the parent class of AAAAAAAAAAAAAAaaaaaaaaaallllllllllllllllllllll classes!. Everything subclasses Object!. Mostly what you'll be dealing with are the classes that subclass "Actor" though because those are the "game specific" classes that determine every conceivable thing about the game.
Okay now go back just knowing what you know now about the "family tree" way of functioning and look at some more scripts. You'll see how it all works and ties together and once you do you'll then start to understand more "code" specific things. Just for an example of something code specific if you ever see something like this in a script:
final function BlahBlah()
Do you see the word "final" above? What this means is that function BlahBlah() cannot be overridden! In no way shape or form! It is "final". So if you ever see a function like that in a class that you'd like to change you can go ahead and try to subclass and override it but it will still act just like in the parent class and not like the way you've changed it to act in your subclass.
There are lots of other code specific things you'll learn and you'll learn to work with and around them. Once you understand most of the simple things you'll then start to understand how the more complex things work (or don't work lol). For instance once you understand how the function specifiers such as the "final" specifier above works and you understand the basic "if"......."else" structure works to control program flow you'll have more than 80% of UnrealScript under your belt. Also there are small things like I saw in your first piece of code you posted like where it says "if( (Killed.bIsPlayer != false)". You could have refined that more by just merely saying "if( Killed.bIsPlayer )". The "if" statement is a conditional statement that only checks for something to be True or False so you never *have* to actually compare something in an "if" statement to True or False. The way I've rewritten it "if( Killed.bIsPlayer )" and left out the comparison to false "!= false" is much cleaner in my opinion!. Also little things like the fact that an "if" statement may or may not *ONLY EXECUTE THE VERY NEXT LINE OF CODE* depending on whether you use braces "{}" or not for instance.
if( Killed.bIsPlayer )
do this 1;
do this 2;
do this 3;
When the above lines are executed the only line above that may or may not be executed will depend on the outcome of Killed.bIsPlayer. If Killed.bIsPlayer is True then "do this 1" will be executed but if Killed.bIsPlayer is False then "do this 1" will not be executed. However in the above structure "do this 2" and "do this 3" will *always* be executed regardless if the outcome of Killed.bIsPlayer = True or Killed.bIsPlayer = False. To make the program execute or not execute more than one line of code after the if statement you have to use braces "{}" to enclose the list of commands you want to have executed. In other words if I wanted all 3 lines to be executed(or not) depending on the outcome of Killed.bIsPlayer then I would do it like this:
if( Killed.bIsPlayer )
{
do this 1;
do this 2;
do this 3;
}
Now as you can see if Killed.bIsPlayer is True all 3 "do this" lines will be executed and nothing will be executed if Killed.bIsPlayer is False. This is where "else" comes in. The else statement always catches the "False" from an "if" statement. You don't always have to have or use an "else" in your code it just depends on what you want the script to do. For instance like above if I wanted all 3 "do this" lines executed or not depending on the outcome of Killed.bIsPlayer and later on decided that there was a 4th and a 5th "do this" line that should be executed if the outcome of Killed.bIsPlayer is False then I would write it like this:
if( Killed.bIsPlayer )
{
do this 1;
do this 2;
do this 3;
}
else
{
do this 4;
do this 5;
}
What this says now is if Killed.bIsPlayer is True "do this" 1, 2, and 3 will be executed and not "do this" 4 and 5 but if Killed.bIsPlayer was false then "do this" 1, 2, and 3 will not be executed and "do this" 4 and 5 will. So you can see a little bit about how to control program flow and once you know these basic things the rest will be easy!. :)
Well I hope I haven't bored you or wasted your time reading all of this cuz you seem really smart but if not then I hope I've helped and if you need further assistance just ask.
Cheerz
Professor,
1. Thx for the time you took to learn me something.
2. About classes... time for some birth control ;-) Would have saved you a lot of typing.
3. {} in if statements. Didn't know that.
4. Now i understand your previous mail a lot beter
I'm learning.
Plan:
Create a subclass for the cow. Copy the "Killed" function from "ScripedPawn",paste it in new subclass. Rewrite (expand) it with part from ScoreKill function. (Killer.PlayerReplicationInfo.Score -= 1)
The "TakeDamage" Function is defined various times in the ScriptedPawn Class because of the different states the ScripedPawn can be in. I would have to rewrite them all. Besides this script was originaly intended for punishment for killing a cow.
I think this is gonna work. But i'll be back result or no result.
If and idea's pop-up, plz let me know.
Grz,
Jura
Almost there:
I worked out my little plan as in previous mail. And now it works. (Kinda)
If i have 5 cows i get for the 1st cow -4 frags, 2nd cow -3 frags, 3th cow -2 ... last cow 0 frags.
Have completly no idea why this is.
//=============================================================================
// Cow.
//=============================================================================
class FriendlyCow extends Cow;
function Killed(pawn Killer, pawn Other, name damageType)
{
local Pawn aPawn;
local ScriptedPawn ScriptedOther;
local bool bFoundTeam;
// Here is the little thing i added
Killer.PlayerReplicationInfo.Score -= 1;
// That's all fokes
if ( Health <= 0 )
return;
if (Other.bIsPlayer)
bCanBePissed = true;
ScriptedOther = ScriptedPawn(Other);
if ( (TeamTag != '') && (ScriptedOther != None)
&& (ScriptedOther.TeamTag == TeamTag) )
{
if ( ScriptedOther.bTeamLeader )
TeamTag = '';
else if ( ScriptedOther.TeamID < TeamID )
TeamID--;
else if ( bTeamLeader )
{
aPawn = Level.PawnList;
while ( aPawn != None )
{
if ( (ScriptedPawn(aPawn) != None) && (ScriptedPawn(aPawn) != self) &&
(ScriptedPawn(aPawn).TeamTag == TeamTag) )
{
bFoundTeam = true;
break;
}
aPawn = aPawn.nextPawn;
}
if ( !bFoundTeam )
{
bTeamLeader = false;
TeamTag = '';
}
}
}
if ( OldEnemy == Other )
OldEnemy = None;
if ( Enemy == Other )
{
Enemy = None;
if ( (Killer == self) && (OldEnemy == None) )
{
aPawn = Level.PawnList;
while ( aPawn != None )
{
if ( (aPawn.IsA('PlayerPawn') || aPawn.IsA('ScriptedPawn'))
&& (VSize(Location - aPawn.Location) < 500)
&& CanSee(aPawn) )
{
if ( SetEnemy(aPawn) )
{
GotoState('Attacking');
return;
}
}
aPawn = aPawn.nextPawn;
}
Target = Other;
GotoState('VictoryDance');
}
else
GotoState('Attacking');
}
}
i really got no idea what ur talking about
Professor
12-13-2004, 02:18 AM
Professor,
1. Thx for the time you took to learn me something.
2. About classes... time for some birth control ;-) Would have saved you a lot of typing.
3. {} in if statements. Didn't know that.
4. Now i understand your previous mail a lot beter
I'm learning.
Plan:
Create a subclass for the cow. Copy the "Killed" function from "ScripedPawn",paste it in new subclass. Rewrite (expand) it with part from ScoreKill function. (Killer.PlayerReplicationInfo.Score -= 1)
The "TakeDamage" Function is defined various times in the ScriptedPawn Class because of the different states the ScripedPawn can be in. I would have to rewrite them all. Besides this script was originaly intended for punishment for killing a cow.
I think this is gonna work. But i'll be back result or no result.
If and idea's pop-up, plz let me know.
Grz,
Jura
Hehee! No prob. Your new and I have no way of knowing your skill level so I get a bit looooooong winded sometimes. :)
Okay you found the Killed function in the Cow's parent ScriptedPawn now what about the Cow's grandparent Pawn? The Cow also inherits everything out of the Pawn class that hasn't been overriden in the ScriptedPawn class. Ok what I'm ultimately getting at is that the Killed function only gets executed when the Cow kills something. There is a function in the Pawn class called Died. The Died function gets called when the Cow dies. So what's happening with your Killed function is that it's waiting until the Cow "Kills" something to adjust the player's score and the player's score that it's adjusting is what looks to be it's own score and not the player that shot it. Try looking in the Pawn class for "function Died" and copy and paste that into your script and change it to your needs. This is the function that you found the "monitor hook" to prevent suicides. You almost had it right you just didn't add the correct code. Now in the parameters for the Died function you'll see Killer, DamageType, and HitLocation. The Killer is the person that caused the Cow to Die and run it's Died function and this is where you can do something like Killer.Died(Killer, DamageType, HitLocation);
This will run the killer's Died function causing them to die when they kill a cow and it'll be a suicide because they are the "Killer" in the Cow's Died function and that is passed to their Died function and it will detect there if they killed themselves and score it appropriately. Also if you wanted to only punish actual players and no one else for killing a cow you could do this:
function Died(pawn Killer, name damageType, vector HitLocation)
{
if ( Killer.IsA( 'PlayerPawn' ) && Killer.bIsPlayer )
Killer.Died(Killer, DamageType, HitLocation);
//be sure to paste the rest of the Died function from the Pawn class here
because if you don't then the only thing that will get executed are
the lines you see above.
}
And if you want to also add bots to the list of the punished just add Killer.IsA( 'Bot' ) to the if statement and add the boolean or "||" to it like this:
if ( (Killer.IsA( 'PlayerPawn' ) || Killer.IsA( 'Bot' )) && Killer.bIsPlayer )
You can see how I also regrouped the boolean or expression with parenthesis and what this is saying is that Killer either has to be a PlayerPawn OR "||" a Bot AND "&&" the Killer's bIsPlayer variable has to be True.
Cheerz
Thx to all here for introducing me to unrealscripts. Still got a long way to go before being at your level, but here is the final script for friendly cow.
//=============================================================================
// Cow.
//=============================================================================
class FriendlyCow extends Cow;
function Died(pawn Killer, name damageType, vector HitLocation)
{
local pawn OtherPawn;
local actor A;
local string CowKillerText;
if ( (Killer.IsA( 'PlayerPawn' ) || Killer.IsA( 'Bot' )) && Killer.bIsPlayer )
{
CowKillerText = "Sick " $ Killer.PlayerReplicationInfo.PlayerName $ " killed a cow. He lost a frag for this.";
Killer.PlayerReplicationInfo.Score -= 2;
BroadcastMessage(CowKillerText, false);
}
// mutator hook to prevent deaths
// WARNING - don't prevent bot suicides - they suicide when really needed
if ( Level.Game.BaseMutator.PreventDeath(self, Killer, damageType, HitLocation) )
{
Health = max(Health, 1); //mutator should set this higher
return;
}
if ( bDeleteMe )
return; //already destroyed
Health = Min(0, Health);
for ( OtherPawn=Level.PawnList; OtherPawn!=None; OtherPawn=OtherPawn.nextPawn )
OtherPawn.Killed(Killer, self, damageType);
if ( CarriedDecoration != None )
DropDecoration();
level.game.Killed(Killer, self, damageType);
//log(class$" dying");
if( Event != '' )
foreach AllActors( class 'Actor', A, Event )
A.Trigger( Self, Killer );
Level.Game.DiscardInventory(self);
Velocity.Z *= 1.3;
if ( Gibbed(damageType) )
{
SpawnGibbedCarcass();
if ( bIsPlayer )
HidePlayer();
else
Destroy();
}
PlayDying(DamageType, HitLocation);
if ( Level.Game.bGameEnded )
return;
if ( RemoteRole == ROLE_AutonomousProxy )
ClientDying(DamageType, HitLocation);
GotoState('Dying');
}
XepptizZ
12-13-2004, 03:10 PM
So does it work?
King Mango
12-13-2004, 06:57 PM
I love a happy ending. It probably works hence the FINAL part of the description :p
TexasGtar
12-14-2004, 01:30 AM
I love a happy ending.
Me too.
Professor
12-14-2004, 05:20 AM
I don't see why it wouldn't work and his subclassed Cow will work online too because he didn't change any of the already replicated variables!. :D Cow killers won't know what hit 'em! and this will be easier on the engine IMO than attatching triggers to the Cow and such which I actually thought was quite a remarkable idea to get it done without the use of UScript and only use what Epic gave you to work with! I still think that the trigger attaching idea could be made to successfully work though. Maybe not if you had to have like 30 Cows in your map cuz then your fps would be slow but 2 or 3 I think it would work out for! :) Using the script I believe is easier on the mapper and the engine as you just drop a few subclassed Cows in and you're done and the engine doesn't have to keep track of all that attatched stuff every tick of the game. Whenever you attach an actor to another actor the engine has to keep track of it and it sometimes looses it's place and this is why sometimes you'll notice actors that you had attached to another actor will not be attached anymore or will be attached but be in a different location in respect to the parent actor. It's not a perfect science and the game engine "tick" (or the time that the engine updates all actors) is governed by the speed of your CPU not your graphics card!.
Edit: Also don't Cows also have the ability to pick up a weapon and fire it at you? If so then the Cow will be the "Owner" of the weapon and the "Owner" will become the "Instigator" of any projectiles fired from that weapon and if a Cow kills another Cow what would happen? You may need to revise your script just a little to also include Cows so they don't get punished for killing each other. Hmmm.....
If ( Killer.IsA( 'Cow' ) )
return; //and don't do the punishment part.
It would probably be better to do something like this though:
if( !(Killer.IsA( 'Cow' )) )
{
if ( (Killer.IsA( 'PlayerPawn' ) || Killer.IsA( 'Bot' )) && Killer.bIsPlayer )
{
CowKillerText = "Sick " $ Killer.PlayerReplicationInfo.PlayerName $ " killed a cow. He lost a frag for this.";
Killer.PlayerReplicationInfo.Score -= 2;
BroadcastMessage(CowKillerText, false);
}
}
You can see the placement of the "!"(not or inverse operator) and how I grouped the condition using () and then "nested" your if statement inside of another one to check for it being a Cow. Now the "IsA" check function does not have to be specific and what I mean is whatever class you specify that any subclasses of that class will also count as one of the classes you have specified so by just saying IsA( 'Cow' ) will also include your FriendlyCow which is a subclass of Cow. :) This is all only if a Cow is capable at any point of killing themselves or another Cow which I'm not sure of. Also it may work just fine the way you have it already since the IsA ( 'PlayerPawn' ) and IsA( 'Bot' ) *should* filter out any Cows but it's better to be safe than sorry!
I may seem like I know about UScript jura but believe me I learn something new *everytime* I look at a script and you will too!. You're also the smartest *new* person to UnrealPlayground that I've seen to date with the script. I can see by your script that you even know about string concatination which is something I would never suspect someone new to the script to know!!!. :) Since you are pretty adept with the script I'd like to invite you to check out the Actor class thorughly as it has all of the super quick functions that are implemented in C++ and execute a lot faster and are easier in most cases to take advantage of in the script. Any of the functions you see in the Actor class that have the word "native" in the function declaration are functions that have been written in the C++ engine and it's best to try to take advantage of these functions werever you can! Also check out the Object class as it has all of the mathematical functions that you can use. If you have any other questions in the future just ask and someone will be glad to try and help. At least me anyway. :)
Cheerz
XepptizZ
12-14-2004, 06:53 AM
Hmm, I don't think the cow can pickup a weapon, never seen him do it anyways. I do know some skaarj can and that the cow can die with a nice bang, and wouldn't the cow fallover if he'd try to hold the weapon?
Professor
12-14-2004, 11:59 AM
Hmm, I don't think the cow can pickup a weapon, never seen him do it anyways. I do know some skaarj can and that the cow can die with a nice bang, and wouldn't the cow fallover if he'd try to hold the weapon?
Heheeee! That's what I was wondering! Thanks for clearing that up Xman! I guess I was thinking about the Nali War Cow which holds its gun up on some thingy attached to its back. This is what I wasn't sure of was if the regular Cow could use a weapon or not. However thinking about it this does kinda defeat the purpose for having Cows in your map in the first place cuz you put 'em in there to kill and then can't kill 'em and it takes all of the fun out of it. Also if you put Cows in a map and it ever gets played online the players will kill the Cows because the make that moooing noise that drowns out any other noises that the players have to hear to have an advantage over their enemies like the sound of a health vial being picked up. When a player hears that sound they can determine where the enemy is but not if some stupid Cow is Mooooooooooooooooooing!. LOL
Cheerz
Just to be shure to all. Yes it works.
"concatination" I had to look it up in the dictionary. lol Anyway it took me some time to find the right syntax for this, also figuring out the Killer.PlayerReplicationInfo.PlayerName but as i've been doing other scripting / programming languages i knew what to look for.
Besides i prefer to work it out as much as possible by myself before asking around. That's why i liked your appoach in not giving me the answers but just the tools to keep me on track. You can't imagine how much i've learned just by doing it this way. As i said earlier, this way i've worked my way into various syntaxis before.
Thx again to all for your time.
Btw. I set the score for killing a cow to -2. Player still get 1 frag from default scripts. (Score = Score + 1 - 2) FriendlyBabyCow was easy ofcourse after this. (Score = Score + 1 - 3)
XepptizZ
12-15-2004, 04:41 PM
Nice! I'll bookmark this thread since I'd like to keep this script in the back of my head.
I'm one of those persons who always tries to kill pawns if their in the level.
I hope you'll soon be helpin people out with scripten here too, just like prof, cuz he's a busy man considering the demand for scripts and lack of active scripters.
Professor
12-17-2004, 02:44 PM
Hehee! I'm flattered and feel less useless but I'm really no UScript master though. However I'll always try to help wherever I can. :) It's bad in the winter time because I've got to cut fire wood to stay warm and I don't have a lot of time to browse the forums between cutting wood and building fires and chopping kindling and stuff. It's a lot of work just to stay warm here and I don't get paid for it but at least I also don't have to pay as much for heat either. :) There is a price though and that is the time it takes. I have to spend most of my free time doing it. :(
Your welcome jura if I've helped and just remember UP rocks so if you ever need any more help with anything Unreal you know where to turn. :)
Cheerz
XepptizZ
12-17-2004, 02:57 PM
Hmm, try a fundraser. " Help the proffessor out, send him wood, as much as possible"
Well, I hope you make it through the winter. And chopping wood makes you a man, so keep on goin and don't get frostbite!
radio667
12-17-2004, 03:10 PM
Your welcome jura if I've helped and just remember UP rocks so if you ever need any more help with anything Unreal you know where to turn. :)
Cheerz
Professor :D Your a GREAT Reason why UP Rockz Like a Party :rockon: Thank You , BRO PRO !!!
Professor
12-17-2004, 05:14 PM
Professor :D Your a GREAT Reason why UP Rockz Like a Party :rockon: Thank You , BRO PRO !!!
That's partaaaaaaaaay! :) You're welcome too brother Rad! :) Hey you need some Unreal Scripting done? LOL I'm sure you could use something for those 3 boxes in the lava! LOL
Cheerz
radio667
12-17-2004, 07:48 PM
LOl :D - im doing great in the map making dept . i shaved off a couple of ploys from my first ( of three ) Boxes ... Only 200 , 000 ...I Rock .....I Think ;) woot !!
Professor
12-18-2004, 10:01 AM
LOl :D - im doing great in the map making dept . i shaved off a couple of ploys from my first ( of three ) Boxes ... Only 200 , 000 ...I Rock .....I Think ;) woot !!
WoW! Rad! You're gonna have to quit using those tessalated cubes! LOL And yes you do rock!........I think! LOL ;) With three 6 sided boxes you should only have 6x3=18 polys and not 200,000!. w00t!. You could also merge polys on coplanar surfaces to get rid of even more polys! :)
Edit: Seriously though if you should ever need help making a map come to the UT Level Design forum cuz there's lots of nice, smart, helpful, UP rockin peeps there that would be glad to try and help. :)
Cheerz St. Rad :rockon:
radio667
12-18-2004, 10:42 AM
Thank You , Very Much :D PROfesssor - You Are The COOLESt of the Cool :rockon:
As happy as i was, so said i'm now. 2 weeks of map building. My map is ready, i put it online and the server goes crazy.
Why you wander, right??
Server stays up and running but gets terribly slow. (Playable but slower than usual)
two kind of script warings pop up.
- Qannouncer goes totaly crazy. I think because this mutator sees the cows as players.
- The FriendlyBabyCow creates errors like:
ScriptWarning: FriendlyBabyCow DM-HiVoltageMegaCows.FriendlyBabyCow0 (Function UnrealShare.BabyCow.Grazing.PickDestination:0097) Accessed None
Grazing function??? I didn't change that!!! What the *#*% is goin' on here.
So i decided to take out the FriendlyCows and replace them with normal ones. Yes, you guessed right. Same problem!!! 'You like that?'
There goes a good idea.
I don't quit easily but i don't see any solutions now. Case closed!!!
XepptizZ
12-18-2004, 04:47 PM
More scripteditten.
Hmmm, those cows were not intended to be used for UT, cuz it's an Unreal remnant.
Then again, a lot of sp's have cows in it and they can be coop played on internet, and then again I think oldschool probably resurrectes Unreal outta UT and thus do the cows work.
Still, I think you just have to change some parts of the scripts and maybe it's just the thing you tested it on.
Professor
12-18-2004, 05:25 PM
As happy as i was, so said i'm now. 2 weeks of map building. My map is ready, i put it online and the server goes crazy.
Why you wander, right??
Server stays up and running but gets terribly slow. (Playable but slower than usual)
two kind of script warings pop up.
- Qannouncer goes totaly crazy. I think because this mutator sees the cows as players.
- The FriendlyBabyCow creates errors like:
ScriptWarning: FriendlyBabyCow DM-HiVoltageMegaCows.FriendlyBabyCow0 (Function UnrealShare.BabyCow.Grazing.PickDestination:0097) Accessed None
Grazing function??? I didn't change that!!! What the *#*% is goin' on here.
So i decided to take out the FriendlyCows and replace them with normal ones. Yes, you guessed right. Same problem!!! 'You like that?'
There goes a good idea.
I don't quit easily but i don't see any solutions now. Case closed!!!
Well I wouldn't give up so easily if I were you. None of the original script that came from Epic is perfect and it's normal for it to throw some errors sometimes. Did you only get like one or two "Accessed None"'s? If so that's normal and I've seen this with a lot of the monsters and ScriptedPawns with their PickDestination function to Access None. I've even seen bots have this error in the log file. However if you got millions of these error entries in the log file then it might be something like XepptizZ said that the Cows were from Unreal 1 and are not "optimized" for UT. It could also be the place you're putting them in. Are you putting like 500 of them in a 256x256 square area? Okay I know that's exaggerating but I had to make that point clear. The other extreme would be to put only one cow in a 64x64 square area. In other words they gotta be able to move around and sometimes the engine picks a destination that may be in a wall or something and hence the Accessed None.
Cheerz
There are 100's of them. Errors i mean. Funny thing is though it's almost all babycow that generates the errors. But my main problem remains the errors from qannouncer. There are even more errors from that.
I need to supress the qannouncer just for this map. Or rewrite it. (?) Even if i can find the source that sounds impossible at my current level of Unreal scripting.
btw the cows have enough room. Not to much not to little (15 cows in 1024x1024)
Professor
12-18-2004, 06:43 PM
There are 100's of them. Errors i mean. Funny thing is though it's almost all babycow that generates the errors. But my main problem remains the errors from qannouncer. There are even more errors from that.
I need to supress the qannouncer just for this map. Or rewrite it. (?) Even if i can find the source that sounds impossible at my current level of Unreal scripting.
btw the cows have enough room. Not to much not to little (15 cows in 1024x1024)
Okay I tried a little test map myself and got the same Accessed None's that you got so I cracked open the script for the BabyCow and low and behold here is what is says at the very top of the script.
//==============================================
// BabyCow.
// Don't add to world directly. Rather, set bHasBaby of an adult cow.
//=============================================
This is your problem because the baby cows follow their *mom* and if there is no mom then access none! A baby cow has to have a *Cow* to follow. This is kinda the same thing with BiterFish. You don't add BiterFish to your map directly but rather add a BiterFishSchool and the School spawns the fish. So the way it looks you're not going to be able to have *just* BabyCows in your map because they have to have a mother to follow according to their script. So if you have added any BabyCows directly to your map delete them and replace them with regular Cows with bHasBaby under Cow -> bHasBaby=True. This also poses an interesting problem with your subclassed baby cows because the regular adult cow is going to spawn a regular baby cow so what you're going to have to do is to subclass the regular cow and override any script that spawns a regular baby cow and make it spawn your baby cow instead. So what you'll end up with is starting with *your cow* (fixed to spawn *your babycow*) as a subclass of Cow(that Epic gave us) then *your babycow* as a subclass of BabyCow(that Epic gave us) and *your cow* and *your babycow* also have the punishment for killing them code included. Then once you have all the subclasses made, the code in place, and everything compiled successfully, then only add *your cow* class to your map and set it's bHasBaby=True.
Hope this helps
Edit: Yep just tried it and it works. I deleted all of the BabyCows out of the map and replaced them with Cows -> bHasBaby=True and there were big and little Cows in the map but no errors in the log file. :)
Cheerz
Thx Prof, I didn't think of that. Ofcourse i've read that line too, when i started this subclass. Never thought it would cause any problemes. The Wiki pages even warn about placing baby cows.
I looked at the server log files, and see simmular warnings for the brutes that are in MattelFighterJets. (in combination with the Qannouncer). I always thought that map was slow (server wise i mean) , but now i understand why.
Time to give Qannouncer the boot i guess.
As for rewriting friendlycow for a friendlybabycow spawn instead of a regular babycow spawn. Maybe later.... If i do i'll post it here.
Professor
12-19-2004, 01:20 PM
Thx Prof, I didn't think of that. Ofcourse i've read that line too, when i started this subclass. Never thought it would cause any problemes. The Wiki pages even warn about placing baby cows.
I looked at the server log files, and see simmular warnings for the brutes that are in MattelFighterJets. (in combination with the Qannouncer). I always thought that map was slow (server wise i mean) , but now i understand why.
Time to give Qannouncer the boot i guess.
As for rewriting friendlycow for a friendlybabycow spawn instead of a regular babycow spawn. Maybe later.... If i do i'll post it here.
Well that's just the thing. I don't have Qannouncer and I still got the errors in the log file after adding BabyCows to a map by themselves. So I personally don't think there's anything wrong with the Qannouncer but like I said I don't have it or know how it works.
As far as the brutes not working with Zencoder's (aka Ghandi's aka Britton Wesley's) MettelFighterJets that is most likely the script for the MattelFighterJets that didn't take into account that maybe a brute would someday try to pick a jet up. I know not all of Zencoder's script was perfect and I have an example too. If you download his map CTF-Articfighterjets][rEmIx you'll see his "Ghandinator" weapon in the map. Well the bots don't know which end of the weapon is which! LOL All they know is point and shoot and sometimes they shoot it almost straight up into the air instead of shooting it right at something. I rescripted it and you can find it in my map DM-GravityZone. I'm also working on another map that has this weapon in it where I have done even more work on the weapon but it hasn't been released yet.
That's cool if/when you do some more scripting for the cows could you please post it here so I could see it? As far as just giving you a script that immediately works well........I sort of don't have no choice there because there are so many things that can be done with script and I would have to know to the letter exactly how you wanted the cows to act before I could tailor a script for them. That's why I didn't just give you a script that would do what you wanted it to and tell you to be on your way because UScript doesn't work like that. Well it might work but I'm sure the cows would have not worked the way *you* wanted them to but the way that *I* scripted them to work. That's an easy concept but hard to explain and I hope I didn't loose you there by babbling so much! LOL It's just that UScript is so *flexible* it would be like telling me you have a corncob pipe and you wanted me to fashion you a pipe cleaner that would exactly fit inside your corncob pipe without knowing the dimensions of your corncob pipe. LOL Bad analogy but it was the first one I thought of here.
Cheerz
A man of many words, but rarely it makes no sence. ;-) I see what you mean.
I tried to create a new friendlycow as a subclass of scriptedpawn, by taking the whole cow script and modifying it slight.
It doesn't compile. It seems like because i'm refering to a not yet existing subclass of friendlycow (offcourse friendlybabycow) Could that be the reason?
XepptizZ
12-19-2004, 04:39 PM
If I've learned somethin of the Unrealwiki experience is that the script will not be compiled when your referring to something nonexisting.
I'm currently reading the way to get past that, by "casting" it so that the compiler will do as you say anyways, I will gat back to you with that when I get it.
XepptizZ
12-19-2004, 04:48 PM
OKm, This is how far I'm gettin it. A class wich is lower (less subclassed) can still sawn a class wich is placed higher when givin refference, but you can not make that script do domethin that class wich is higher can, unless you "cast" it.
This is what came up first in my head when you posted that, I dunno if I'm close or not (prolly not).
That would mean 1st create the subclass then create the upper class (upper class, that sounds scarry) for that sub class.
I'll try that
XepptizZ
12-20-2004, 04:15 PM
Couldn't you just subclass the normal Babycow with your babycow? And then subclass the "Normal cow" with your cow wich then can reffer to the babycow you made??
I thought i would have been easier to create a subclass for scriptedpawn. But i'll try your way next. I'm kinda busy right now with other stuff so the cows will have to wait a little.
Btw did you get any futher with compiling classes with subclass references? Or could you tell me where you found the earlier mentioned info. Perhaps i can do some digging.
thx
XepptizZ
12-22-2004, 03:14 PM
Here's the link. Somewhere before the middle is a section where the "casting" of objects is mentioned.
EDIT: Oops, me and my scrambled brain, here's the link.
http://wiki.beyondunreal.com/wiki/Using_Objects
Professor
01-07-2005, 12:38 AM
If I've learned somethin of the Unrealwiki experience is that the script will not be compiled when your referring to something nonexisting.
I'm currently reading the way to get past that, by "casting" it so that the compiler will do as you say anyways, I will gat back to you with that when I get it.
I'm not too sure about what you are calling "casting" Xepp. I can explain what casting is. Say I have a function like so:
function touch (actor Other)
{
if ( Other.bIsPlayer )
return;
else
Other.bIsPlayer = True;
}
The above code will not compile! Why: because the compiler will say "unrecognized member 'bIsPlayer' in class actor". What this means is that in the function perameters the variable "Other" was declared as an "actor" and referring to the variable bIsPlayer in the actor class is wrong because there is no bIsPlayer variable in the actor class. The variable bIsPlayer never got declared until the Pawn class was writen. So now we know that for Other to have a bIsPlayer variable in its class it has to be a Pawn. To do this you have to "cast" the "actor" variable "Other" from the function perameter onto the Pawn class. We would rewrite the function like so to make it work:
function touch (actor Other)
{
local pawn P;
P = Pawn(Other); // here is where we are casting Other onto the Pawn class and if Other is not a Pawn the P will = None but if Other is a Pawn then P will = that Pawn. It's almost like we are reaching with our hands down into the Other variable and only pulling out the Pawns. I think of the parenthesis as my hand wrapped around the Other variable and I'm squeezing the Pawns out of it and putting them in the new local copy of the P variable that we added!.
if ( P != None && P.bIsPlayer ) // P will not = None if Other is a Pawn. You have to check for the None condition here to keep from getting the accessed none error in the log file and slowing the game down if Other happens to not be a Pawn.
return;
else if ( P != None ) // Check for None again before we do the next line or it could access none if P is not a Pawn with the bIsPlayer variable.
P.bIsPlayer = True;
}
Written more clearly now is the same workable code without my annotations.
function touch (actor Other)
{
local pawn P;
P = Pawn(Other);
if ( P != None && P.bIsPlayer )
return;
else if ( P != None )
P.bIsPlayer = True;
}
I could have also written it without declaring the extra "local" copy of the pawn variable called "P" which is only temporary because the P variable is destroyed as soon as the function completes but I'm lazy and didn't want to write all those Pawn(Other)'s.
function touch (actor Other)
{
if ( Pawn(Other) != None && Pawn(Other).bIsPlayer )
return;
else if ( Pawn(Other) != None )
Pawn(Other).bIsPlayer = True;
}
This code will work because of class casting.
Cheerz
vBulletin® v3.7.2, Copyright ©2000-2013, Jelsoft Enterprises Ltd.