[ACS] Problem making a regenerative shield work

Discuss all aspects related to modding Zandronum here.
Post Reply
User avatar
FranckyFox2468
Forum Regular
Posts: 180
Joined: Sat May 07, 2016 8:30 pm

[ACS] Problem making a regenerative shield work

#1

Post by FranckyFox2468 » Sat Sep 09, 2017 9:18 pm

Please i do not want the "doom shouldn't have this sort of thing" talk/debate going. If you are only here for that reason and not to help please simply ignore this thread. Thank you.

So i was starting to work on a regenerative shield for certain player classes dedicated to taking enemies more upfront with melee weapons or mean't to gain mobility out of explosion/self damage without over relying on medics and such. So me and a friend tried to get something to work aaaaaaand for some fucking reason it doesn't when we couldn't find anything wrong with the script.

I figured some people here might have better eyes than us so here's the items (the "ShieldWielder" is mean't to be an inventory exclusive to characters with regenerative shields, and characters without it does not get regenerative shields)

Code: Select all

ACTOR Shield : BasicArmorPickup
{
  Inventory.Icon "ARM1A0"
  Armor.SavePercent 100.0
  Armor.SaveAmount 100
  States
  {
  Spawn:
    TNT1 A 0
    stop
  }
}

ACTOR ShieldBit : Shield
{
  Inventory.Icon "ARM1A0"
  Armor.SavePercent 100.0
  Armor.SaveAmount 1
}

Actor ShieldWielder : CustomInventory
{
inventory.maxamount 1
}
the player class i made to test:

Code: Select all

ACTOR ShieldPlayer : DoomPlayer
{
  Speed 1
  Health 100
  Radius 16
  Height 56
  Mass 100
  PainChance 255
  Player.StartItem "Shield"
  Player.StartItem "ShieldWielder", 1
  Player.DisplayName "ShieldMarine"
  Player.StartItem "Chainsaw"
  Player.ColorRange 112, 127
  
}
the calling code used in enter/respawn codes:

Code: Select all

ACS_NamedExecuteAlways("ShieldRegen", 0);
and the code itself that seems to not want to work at all for some fucking reason:

Code: Select all

script "ShieldRegen" (void)
{
    int ArmorChecki = Checkinventory("Armor");
    int OldArmor;

    delay (1);
    if (Checkinventory("ShieldWielder") >= 1)
    {
        if (OldArmor == ArmorChecki)
        {
            giveinventory("ShieldBit", 1);
            delay (15);
        }
        else
        {
            delay (3*35);
            OldArmor = ArmorChecki;
        }
        restart;
    }
    else
    Terminate; 
}
Basically it checks every 15 ticks if the player has the same armor ammount and gives an armor point, if not, it gives a 3 second delay before it recharges. Help would be greatly appreciated.

Konda
Forum Regular
Posts: 487
Joined: Thu Jun 07, 2012 5:22 pm

[ACS] Re: Problem making a regenerative shield work

#2

Post by Konda » Sat Sep 09, 2017 10:02 pm

Can't check right now but I think the "restart" instruction resets local variables so if that's true then OldArmor is always having the value of 0 before the nested if check (OldArmor == ArmorChecki)

If that's not the case then check if the script is being executed at all by adding a print command at the beginning. Zan used to have a problem where enter scripts wouldn't be executed offline.

User avatar
FranckyFox2468
Forum Regular
Posts: 180
Joined: Sat May 07, 2016 8:30 pm

[ACS] Re: Problem making a regenerative shield work

#3

Post by FranckyFox2468 » Sat Sep 09, 2017 10:09 pm

Konda wrote:Can't check right now but I think the "restart" instruction resets local variables so if that's true then OldArmor is always having the value of 0 before the nested if check (OldArmor == ArmorChecki)

If that's not the case then check if the script is being executed at all by adding a print command at the beginning. Zan used to have a problem where enter scripts wouldn't be executed offline.
I added a print. It does show up but only once and it does not loop.

EDIT:

okay so, this does not work:

Code: Select all

script "ShieldRegen" (void)
{
    int ArmorChecki = Checkinventory("Armor");
    int OldArmor;

    delay (1);
    if (Checkinventory("ShieldWielder") >= 1)
    {   Print(s:"Fuck");
        if (OldArmor == ArmorChecki)
        {
            giveinventory("ShieldBit", 1);
            delay (15);
        }
        else
        {
            delay (3*35);
            OldArmor = ArmorChecki;
        }
        restart;
    }
    else
    Terminate; 
}
but this does:

Code: Select all

script "ShieldRegen" (void)
{
    int ArmorChecki = Checkinventory("Armor");
    int OldArmor;
	Print(s:"Fuck");

    delay (1);
    if (Checkinventory("ShieldWielder") >= 1)
    { 
        if (OldArmor == ArmorChecki)
        {
            giveinventory("ShieldBit", 1);
            delay (15);
        }
        else
        {
            delay (3*35);
            OldArmor = ArmorChecki;
        }
        restart;
    }
    else
    Terminate; 
}
Couldn't exactly tell why

Konda
Forum Regular
Posts: 487
Joined: Thu Jun 07, 2012 5:22 pm

[ACS] Re: Problem making a regenerative shield work

#4

Post by Konda » Sat Sep 09, 2017 10:20 pm

Are you saying that the first script outputs "Fuck" only once while the second one does it always?

User avatar
FranckyFox2468
Forum Regular
Posts: 180
Joined: Sat May 07, 2016 8:30 pm

[ACS] Re: Problem making a regenerative shield work

#5

Post by FranckyFox2468 » Sat Sep 09, 2017 10:34 pm

Konda wrote:Are you saying that the first script outputs "Fuck" only once while the second one does it always?
No, the second one only does it once, the first does not do it at all.

Konda
Forum Regular
Posts: 487
Joined: Thu Jun 07, 2012 5:22 pm

[ACS] Re: Problem making a regenerative shield work

#6

Post by Konda » Sat Sep 09, 2017 10:39 pm

FranckyFox2468 wrote:
Konda wrote:Are you saying that the first script outputs "Fuck" only once while the second one does it always?
No, the second one only does it once, the first does not do it at all.
Ok, this means that the restart instruction is never reached which is only possible if the first if check fails, so there's something up wirh ShieldWielder.
First, make sure you're actually playing as the ShieldPlayer and not as DoomPlayer since ShieldPlayer doesn't replace DoomPlayer. Can you select the class and have you defined it in keyconf?
If yes, then try adding "inventory.amount 1" to the definition of the ShieldWielder actor.

User avatar
FranckyFox2468
Forum Regular
Posts: 180
Joined: Sat May 07, 2016 8:30 pm

[ACS] Re: Problem making a regenerative shield work

#7

Post by FranckyFox2468 » Sat Sep 09, 2017 10:47 pm

It didn't work but then i tried changing it from a custominventory to just inventory but the script started acting really fucking weirdly. With this script, it just shows "fuck" continuously and does not give armor back at all.

Code: Select all

#library "command"
#include "zcommon.acs"

script "ShieldRegen" (void)
{
    int ArmorChecki = Checkinventory("Armor");
    int OldArmor;

    delay (1);
    if (Checkinventory("ShieldWielder") >= 1)
    {   
        if (OldArmor == ArmorChecki)
        {
		    Print(s:"Fuck");
            giveinventory("ShieldBit", 1);
            delay (15);
        }
        else
        {
            delay (3*35);
            OldArmor = ArmorChecki;
        }
        restart;
    }
    else
    Terminate; 
}
here's the modified decorate:

Code: Select all

Actor ShieldWielder : Inventory
{
inventory.amount 1
inventory.maxamount 1
Inventory.InterHubAmount 1
 -Invbar 
 +Inventory.Undroppable 
 +Inventory.HubPower
}

User avatar
Ivan
Addicted to Zandronum
Posts: 2219
Joined: Mon Jun 04, 2012 5:38 pm
Location: Omnipresent

[ACS] Re: Problem making a regenerative shield work

#8

Post by Ivan » Sat Sep 09, 2017 11:03 pm

Use this to obtain information about the armor of the player instead of checking armor specifically like an inventory item: GetArmorType

That might help. Other than that I don't know what could be wrong besides the "ShieldWielder" not being properly given.

EDIT: Edited because I linked the wrong ACS function.
Last edited by Ivan on Sun Sep 10, 2017 9:31 am, edited 1 time in total.
=== RAGNAROK DM ON ... uh... dead forever? ===
=== ALWAYS BET ON ... uh... dead forever? ===
=== Who wanta sum wang? ===
=== Death and Decay - A new Monster/Weapon replacer ===

User avatar
FranckyFox2468
Forum Regular
Posts: 180
Joined: Sat May 07, 2016 8:30 pm

[ACS] Re: Problem making a regenerative shield work

#9

Post by FranckyFox2468 » Sat Sep 09, 2017 11:16 pm

Ended up having another friend helping on the matter. Valerie Valen of the Serious Sam community. Thanks you guys for trying to help regardless, ima post the code and the item decorate with her permission:

Script:

Code: Select all

bool ShieldsGiven[32];

script "ShieldRegen" (void)
{	
    int OldArmor;
	int NewArmor;
	int OldHealth;
	int NewHealth;
	int GiveShield;
	int FracArmor;
	int DelayTimer;
	
    if (!!Checkinventory("ShieldWielder")) {
		if (!ShieldsGiven[PlayerNumber()]) {
			GiveInventory("Shield",100);
			ShieldsGiven[PlayerNumber()] = 1;
		}
		
		NewHealth = GetActorProperty(0,APROP_Health);
		NewArmor = CheckInventory("Armor");
        if (NewArmor < OldArmor || NewHealth < OldHealth) {
            DelayTimer = 0;
            FracArmor = 0;
        } else if (DelayTimer >= 105) {
            FracArmor++;
			GiveShield = FracArmor/15;
			GiveInventory("Shield",GiveShield);
			FracArmor = FracArmor % 15;
        } else {
			DelayTimer++;
        }
		OldHealth = NewHealth;
		OldArmor = CheckInventory("Armor");
    }
    Delay(1);
    Restart; 
}
Decorate item(thanks to konda):

Code: Select all

ACTOR Shield : BasicArmorBonus
{
  +INVENTORY.ALWAYSPICKUP
  Armor.SavePercent 100.0
  Armor.SaveAmount 3
   Armor.MaxSaveAmount 100
  States
  {
  Spawn:
    TNT1 A 0
    stop
  }
}
(gives 3 shields per second once the regeneration works)

User avatar
Ivan
Addicted to Zandronum
Posts: 2219
Joined: Mon Jun 04, 2012 5:38 pm
Location: Omnipresent

[ACS] Re: Problem making a regenerative shield work

#10

Post by Ivan » Sat Sep 09, 2017 11:46 pm

Excuse me, all of this for a regenerating shield? Seriously...

I have a regenerating health and armor script from DND that works way simpler than that, and doesn't require you to fiddle with arrays. In fact, your array size should have been 64 not 32. (MAXPLAYERS is 64)

Code: Select all

// Regeneration
Script 999 ENTER {
	while(1) {
		int armor = GetArmorType("CyberneticArmor", PlayerNumber());
		if(isAlive()) {
			if(armor && armor < DND_CYBERNETICARMOR_AMOUNT && !CheckInventory("P_Damaged")) {
				if(armor < DND_CYBERNETICARMOR_AMOUNT - 5)
					GiveInventory("NewArmorBonus", 5);
				else
					GiveInventory("NewArmorBonus", DND_CYBERNETICARMOR_AMOUNT - armor);
				GiveInventory("CyberneticEffect", 1);
				LocalAmbientSound("items/armorbonus", 127);
			}
		Delay(35);
	}
}
I took the healing part but essentially the same... I don't know why you even went this far for something so trivial. The "isAlive" function just checks if the player's health is not 0 basically. Other than that it's all your typical ACS. (Things in full capital are #defines that are just constant values)
=== RAGNAROK DM ON ... uh... dead forever? ===
=== ALWAYS BET ON ... uh... dead forever? ===
=== Who wanta sum wang? ===
=== Death and Decay - A new Monster/Weapon replacer ===

User avatar
ArcheKruz
 
Posts: 63
Joined: Wed Oct 31, 2012 8:17 am
Location: Hong Kong

[ACS] Re: Problem making a regenerative shield work

#11

Post by ArcheKruz » Sun Sep 10, 2017 6:32 am

Well yes, Ivan, because within the span of a second, you could lose health, and then recover the same amount, which will confuse the script. The intent is to check every tic if the player has sustained any health or armor damage, and if so, reset the delay timer to restart the countdown timer to start regenerating armor. The key here is temporal resolution.

So, considering that armor can only be 1 or 0, and DND_CyberneticArmor_Amount is a fixed number that I'd assume to be greater than 1, what would be the point of "armor < DND_CYBERNETICARMOR_AMOUNT" in the second IF validation chunk? Moreover, what is the script that controls the giving and taking of the inventory item "P_Damaged"? What scripts would the item "CyberneticEffect" affect?

Also, this, what I contributed, is what I would consider simple scripting.

User avatar
Ivan
Addicted to Zandronum
Posts: 2219
Joined: Mon Jun 04, 2012 5:38 pm
Location: Omnipresent

[ACS] Re: Problem making a regenerative shield work

#12

Post by Ivan » Sun Sep 10, 2017 9:34 am

ArcheKruz wrote:Well yes, Ivan, because within the span of a second, you could lose health, and then recover the same amount, which will confuse the script. The intent is to check every tic if the player has sustained any health or armor damage, and if so, reset the delay timer to restart the countdown timer to start regenerating armor. The key here is temporal resolution.
That is why there's a "P_Damaged" item. When player is damaged, this powerup is given (in the pain state of the player) which lasts for some seconds. The resolution is kept to a second, because I don't want to keep the script checking in short time intervals. (There are many scripts in the mod that do which are quite costly, so I sacrificed some on this and a couple less crucial ones)
ArcheKruz wrote: So, considering that armor can only be 1 or 0, and DND_CyberneticArmor_Amount is a fixed number that I'd assume to be greater than 1, what would be the point of "armor < DND_CYBERNETICARMOR_AMOUNT" in the second IF validation chunk? Moreover, what is the script that controls the giving and taking of the inventory item "P_Damaged"? What scripts would the item "CyberneticEffect" affect?
Quoting the wiki:
The return value is the number of armor points if the player wears the designated armor, 0 otherwise.
I edited my post above to reflect this, I realized I linked the wrong ACS function "GetArmorInfo" whereas it should have been "GetArmorType". The point of the conditional checks is my mod lets you go over the limit of a cybernetic armor, so you could have twice as much armor than that and the regeneration script won't consider that valid. The P_Damaged part is explained above. For the "CyberneticEffect", that is just a custom inventory that spawns effects around you for regeneration.
ArcheKruz wrote: Also, this, what I contributed, is what I would consider simple scripting.
What did you contribute?
=== RAGNAROK DM ON ... uh... dead forever? ===
=== ALWAYS BET ON ... uh... dead forever? ===
=== Who wanta sum wang? ===
=== Death and Decay - A new Monster/Weapon replacer ===

Post Reply