Making a player lose points when damaged

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
User avatar
giwake
Posts: 24
Joined: Sat Feb 09, 2019 6:44 am

Making a player lose points when damaged

Post by giwake »

Hello.
I'm currently working on a TC with a score system, and I'm trying to make it so that when the player is damaged they lose points.
Here's my code so far.

Decorate code

Code: Select all

ACTOR NewMarine : Doomplayer
{
    Player.StartItem "Clip", 24 //TODO: Replace clip with other ammo for 3d model support.
    Player.StartItem "Revolver"
    Player.StartItem "Kick" 
	States {
	Pain:
		PLAY G 4 A_GiveInventory("owie") //CULPRIT #1: Maybe this isn't actually giving the owie actor?
		PLAY G 4 A_Pain
		Goto Spawn
	
	}
}

ACTOR owie : CustomInventory
{
  Inventory.PickupMessage "owie" //TODO: remove when this shit works
  iNVENTORY.AMOUNT 1
  +AUTOACTIVATE
  States
  {
  Spawn:
    TNT1 A 1
    Loop
  PICKUP:
    TNT1 A 0
    Stop
  }
}
ACS code:

Code: Select all

Script "PAINCHECK" (void) //Player loses points when hit by enemies
{
	If(CheckInventory("owie")) //CULPRIT #2: Maybe this isn't finding the owie actor?
	{
		SetActorProperty(0, APROP_Score, (GetActorProperty(0, APROP_Score)-(Random(8,15))));
		print(s:"OWIE!");
		TakeInventory("owie", 1);

	}

}

The issue is that when the player loses health and enters the pain state, they don't actually lose points for some reason.
I've left some comments where I think some issues might be, but I'm not 100% certain on what could be causing this to not work.
User avatar
ramon.dexter
Posts: 1562
Joined: Tue Oct 20, 2015 12:50 pm
Graphics Processor: nVidia with Vulkan support
Location: Kozolupy, Bohemia

Re: Making a player lose points when damaged

Post by ramon.dexter »

Okay, this could be executed even better in zscript. Try using this for your base marine class (untested, only to give basic idea on how to do it in zscript):

Code: Select all

class NewMarine : DoomPlayer {
	int score;
	Default {
		NewMarine.score 0; //if you want to pre-set some base value of score
	}
	Override int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags, double angle) {
		int newdamage;
		
		let pawn = self.player;
		pawn.score--;
		Return Super.DamageMobj(inflictor,source,damage,mod);
	}
}
Jarewill
 
 
Posts: 1853
Joined: Sun Jul 21, 2019 8:54 am

Re: Making a player lose points when damaged

Post by Jarewill »

As Ramon said, ZScript's DamageMobj will work better, although Score is already a property of Actor, so it will error out if you try to redefine it.
But as for the reason why your code doesn't work, I have two ideas:
First is that you don't call your ACS script from anywhere, it won't automatically run whenever the player takes damage, but I will for now assume you are calling this script from a sort of "master script" that's looping.
Second is seeing how you check for the owie item, it being a CustomInventory with +AUTOACTIVATE and no Use state might be the reason it's messing up, it might be worth to make it a simple Inventory item instead, like so:
ACTOR owie : Inventory { Inventory.MaxAmount 1 }

If the issue persists, it might be worth posting your project here so we can look inside it.

Edit: Looking closer at Ramon's code, I can see an issue.
Putting self.player will interpret the actor as PlayerInfo, which has a completely different set of variables and properties and as such won't read the Score variable.
So instead of using this:

Code: Select all

let pawn = self.player;
pawn.score--;
You can just use this: self.Score--;
And again, Score is already defined in the Actor class, so redefining it can lead to an error.
User avatar
giwake
Posts: 24
Joined: Sat Feb 09, 2019 6:44 am

Re: Making a player lose points when damaged

Post by giwake »

I quickly slapped the ZScript into my mod, unfortunately I'm getting an error message.

Code: Select all

E:/SuperRad/Build/:zscript.zc, line 93: '@property@NewMarine.Score' is an unknown actor property.
My ZScript is this:

Code: Select all

class NewMarine : DoomPlayer {

	int score;
	Default {
		NewMarine.score 50; //if you want to pre-set some base value of score
		Player.StartItem "Clip", 24; //TODO: Replace clip with other ammo for 3d model support.
		Player.StartItem "Revolver";
		Player.StartItem "Kick";
	}
	Override int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags, double angle) {
		int newdamage;
		
		self.Score--;
		Return Super.DamageMobj(inflictor,source,damage,mod);
	}
}
Is it score that might be causing the issue?
User avatar
giwake
Posts: 24
Joined: Sat Feb 09, 2019 6:44 am

Re: Making a player lose points when damaged

Post by giwake »

Scratch that, I figured out an absolutely awful hack to fix it, but it works and at this point I'm just happy that my code works :V

I commented out the definition for newmarine.score and then made a script inside my map that sets the player's score to 50 at the start of the map.
I can only hope and pray that I never have to touch this code ever again.
User avatar
ramon.dexter
Posts: 1562
Joined: Tue Oct 20, 2015 12:50 pm
Graphics Processor: nVidia with Vulkan support
Location: Kozolupy, Bohemia

Re: Making a player lose points when damaged

Post by ramon.dexter »

Jarewill wrote: Thu Mar 02, 2023 5:26 am As Ramon said, ZScript's DamageMobj will work better, although Score is already a property of Actor, so it will error out if you try to redefine it.
But as for the reason why your code doesn't work, I have two ideas:
First is that you don't call your ACS script from anywhere, it won't automatically run whenever the player takes damage, but I will for now assume you are calling this script from a sort of "master script" that's looping.
Second is seeing how you check for the owie item, it being a CustomInventory with +AUTOACTIVATE and no Use state might be the reason it's messing up, it might be worth to make it a simple Inventory item instead, like so:
ACTOR owie : Inventory { Inventory.MaxAmount 1 }

If the issue persists, it might be worth posting your project here so we can look inside it.

Edit: Looking closer at Ramon's code, I can see an issue.
Putting self.player will interpret the actor as PlayerInfo, which has a completely different set of variables and properties and as such won't read the Score variable.
So instead of using this:

Code: Select all

let pawn = self.player;
pawn.score--;
You can just use this: self.Score--;
And again, Score is already defined in the Actor class, so redefining it can lead to an error.
Sorry for the mistake, I didn't checked the actor class ;)
Post Reply

Return to “Scripting”