Jump to content

Photo

compiling Scripting issues

Globals zscript_error

  • Please log in to reply
3 replies to this topic

#1 Max Headroom

Max Headroom

    I'll buy that for a Rupee!

  • Members
  • Real Name:Rion "Axy"
  • Pronouns:He / Him
  • Location:In a low-Def Tv in Chicago

Posted 01 February 2026 - 06:59 PM

I'm having a script compiling issue, 

 

[Info] Compiling the editor script buffer...
[Info] Pass 1: Parsing
[Info] Pass 2: Preprocessing
[Error] syntax error, unexpected SCRIPT, expecting SCOPERES or EMPTYBRACKETS or IDENTIFIER [scripts/globals.zs Line 1831 Column 12 'script']
[Error] ZQ_BUFFER Line 3 @ Columns 1-19 - Error P001: Included file 'scripts/globals.zs' encountered an error.
[Info] Failure!

 

It seems to trigger on a few scripts, Moosh's estus flask, and speedspell script by Alucard648, i am using 2.5.5.x

#option SHORT_CIRCUIT on
#option HEADER_GUARD on

#include "ffcscript.zh"
#include "ghost.zh"
#include "chess.zh"
#include "smartcombos.zh"
#include "Tint.zh"
#include "confusion.zh"
#include "LinkMovement.zh"


//estus flask start
const int ESTUSFLASK_INITIAL_CAPACITY = 6; //How many estus you can carry to start with
const int ESTUSFLASK_MAX_CAPACITY = 30; //The max estus flasks you can ever carry
const int ESTUSFLASK_UPGRADE_TIERS = 5; //How many times the flask can be upgraded (scales healing from ESTUSFLASK_HEALING to ESTUSFLASK_HEALING_MAX)

const int ESTUSFLASK_HEALING = 48; //How much HP the flask heals minimum (16 = one heart)
const int ESTUSFLASK_HEALING_MAX = 80; //How much HP the flask heals maximum
const int ESTUSFLASK_DRINK_TIME = 60; //How many frames it takes to drink a flask and start the healing
const int ESTUSFLASK_HEAL_TIME = 40; //How many frames it takes for the flask to heal

const int ESTUSFLASK_REFILL_ON_F6 = 1; //If 1, the player gets all their flasks back on death/F6
const int ESTUSFLASK_HEALING_IS_PERCENT = 0; //If 1, healing from the estus flask is a percentage of max HP
const int ESTUSFLASK_GETTING_HIT_INTERRUPTS_HEALING = 1; //If 1, getting hit will interrupt the healing even after you finish drinking
const int ESTUSFLASK_CAN_DOUBLE_DRINK = 1; //If 1, using consecutive flasks will make the animation faster
const int ESTUSFLASK_CAN_WASTE = 1; //If 1, getting hit while drinking a flask will waste the flask
const int ESTUSFLASK_BONFIRE_HEALS = 1; //If 1, using a bonfire will fully heal you
const int ESTUSFLASK_BONFIRE_RESETENEMIES = 1; //If 1, using the bonfire will try to reset GuyCount[]
const int ESTUSFLASK_BONFIRE_SETS_CONTINUE = 1; //If 1, using the bonfire will set the continue point
const int ESTUSFLASK_BONFIRE_OVERRIDES_CONTINUE = 0; //If 1, only bonfires will be able to set the continue point

//Tile and CSet for the animation of Link drinking from the estus flask
const int TIL_ESTUSFLASK_DRINK = 1136;
const int CS_ESTUSFLASK_DRINK = 6; 
//How many animation frames the drinking animation lasts for
const int FRAMES_ESTUSFLASK_DRINK = 8; 

//Tile for the estus flask item
const int TIL_ESTUSFLASK_ITEM = 1128;
//Number of tiles following TIL_ESTUSFLASK_ITEM marking how much is left, going from empty to full
const int STATES_ESTUSFLASK_ITEM = 6;

//Layer, combo, and cset for A button prompts
const int LAYER_APROMPT = 4; 
const int CMB_APROMPT = 1135; 
const int CS_APROMPT = 6;

void DrawAPrompt(){
	if(CMB_APROMPT>0)
		Screen->FastCombo(LAYER_APROMPT, Link->X, Link->Y-16, CMB_APROMPT, CS_APROMPT, 128);
}

//Sprite in weapons/misc for particles drawn while healing
const int SPR_ESTUSFLASK_PARTICLES = 118;

//Sound when Link drinks an estus flask
const int SFX_ESTUSFLASK_DRINK = 32; 
//Healing sound after drinking a flask
const int SFX_ESTUSFLASK_HEAL = 56; 
//Sound when refilling estus flasks
const int SFX_ESTUSFLASK_REFILL = 25;

//Counter for the current number of estus flasks (Script 3 by default)
const int CR_ESTUSFLASK_COUNT = 9;
//Counter for the current upgrade level of the estus flask (Script 4 by default)
const int CR_ESTUSFLASK_UPGRADE = 10;

const int _EF_HEALHP = 0;
const int _EF_HEALHP2 = 1;
const int _EF_HEALHPPERFRAME = 2;
const int _EF_DRINKTIMER = 3;
const int _EF_FIRSTLOAD = 4;
const int _EF_MAXREFILL = 5;
const int _EF_UPGRADETIER = 6;
const int _EF_LASTMAP = 7;
const int _EF_CONTINUEDMAP = 8;
const int _EF_CONTINUESCREEN = 9;
const int _EF_MAXDRINKTIME = 10;
const int _EF_DOUBLEDRINKTIMER = 11;
const int _EF_RESETMAP = 20; //First of map enemy spawn reset indices (20-275)
int EstusFlask[512];

void EstusFlask_Init(){
	//On the first load, set the capacity maximum for the flasks
	if(!EstusFlask[_EF_FIRSTLOAD]){
		Game->MCounter[CR_ESTUSFLASK_COUNT] = ESTUSFLASK_MAX_CAPACITY;
		EstusFlask[_EF_MAXREFILL] = ESTUSFLASK_INITIAL_CAPACITY;
		
		EstusFlask[_EF_CONTINUEDMAP] = Game->GetCurMap();
		EstusFlask[_EF_CONTINUESCREEN] = Game->GetCurDMapScreen();
		
		EstusFlask[_EF_FIRSTLOAD] = 1;
	}
	
	if(ESTUSFLASK_REFILL_ON_F6){
		Game->Counter[CR_ESTUSFLASK_COUNT] = EstusFlask[_EF_MAXREFILL];
	}
	
	EstusFlask_RefreshTiles();
}

void EstusFlask_Update(){
	int i; int j;
	//Drinking animation
	if(EstusFlask[_EF_DRINKTIMER]>0){
		i = EstusFlask[_EF_MAXDRINKTIME]-EstusFlask[_EF_DRINKTIMER];
		EstusFlask[_EF_DRINKTIMER]--;
		//If the timer runs out, make Link visible and proceed to the healing
		if(EstusFlask[_EF_DRINKTIMER]==0){
			Link->Invisible = false;
			
			Game->PlaySound(SFX_ESTUSFLASK_HEAL);
			EstusFlask[_EF_DOUBLEDRINKTIMER] = 32;
			//If flasks can be wasted, the counter has been decremented, otherwise do it here
			if(!ESTUSFLASK_CAN_WASTE){
				Game->Counter[CR_ESTUSFLASK_COUNT]--;
			}
		}
		//Otherwise make Link invisible and draw his tiles
		else{
			Link->Invisible = true;
			
			//If Link gets hit, make him visible and interrupt the animation
			if(Link->Action==LA_GOTHURTLAND){
				Link->Invisible = false;
				EstusFlask[_EF_DRINKTIMER] = 0;
				EstusFlask[_EF_HEALHP] = 0;
				EstusFlask[_EF_HEALHPPERFRAME] = 0;
				EstusFlask[_EF_DOUBLEDRINKTIMER] = 0;
			}
			//If he hasn't been hit, draw him
			else{
				int layer = 2;
				if(ScreenFlag(1, 4)) //Layer -2
					layer = 1;
					
				j = Clamp(Floor(i/(EstusFlask[_EF_MAXDRINKTIME]/FRAMES_ESTUSFLASK_DRINK)), 0, EstusFlask[_EF_MAXDRINKTIME]-1);
				Screen->FastTile(layer, Link->X+Link->DrawXOffset, Link->Y+Link->DrawYOffset, TIL_ESTUSFLASK_DRINK+j, CS_ESTUSFLASK_DRINK, 128);
				NoAction();
			}
		}
	}
	else if(EstusFlask[_EF_HEALHP]>0){
		//If Link gets hit or caps out, end the healing
		if(Link->HP>=Link->MaxHP||(ESTUSFLASK_GETTING_HIT_INTERRUPTS_HEALING&&Link->Action==LA_GOTHURTLAND)){
			EstusFlask[_EF_DRINKTIMER] = 0;
			EstusFlask[_EF_HEALHP] = 0;
			EstusFlask[_EF_HEALHPPERFRAME] = 0;
			if(ESTUSFLASK_GETTING_HIT_INTERRUPTS_HEALING&&Link->Action==LA_GOTHURTLAND)
				EstusFlask[_EF_DOUBLEDRINKTIMER] = 0;
		}
		else{
			//Subtract HP each frame being healed from the total frames
			//Get the difference minus decmials to determine how much to heal Link
			j = Floor(EstusFlask[_EF_HEALHP]);
			EstusFlask[_EF_HEALHP] = Max(EstusFlask[_EF_HEALHP]-EstusFlask[_EF_HEALHPPERFRAME], 0);
			int healAmount = j-Floor(EstusFlask[_EF_HEALHP]);
			
			Link->HP += healAmount;
			
			//Draw particles around Link if applicable
			if(SPR_ESTUSFLASK_PARTICLES){
				lweapon particle = CreateLWeaponAt(LW_SCRIPT10, Link->X+Rand(-8, 8), Link->Y+Rand(-8, 8));
				particle->UseSprite(SPR_ESTUSFLASK_PARTICLES);
				particle->DeadState = particle->ASpeed*particle->NumFrames;
				particle->CollDetection = false;
				particle->HitYOffset = -1000;
			}
		}
	}
	
	//Backup heal (Used when double drinking)
	if(EstusFlask[_EF_HEALHP2]>0){
		//If Link gets hit or caps out, end the healing
		if(Link->HP>=Link->MaxHP||(ESTUSFLASK_GETTING_HIT_INTERRUPTS_HEALING&&Link->Action==LA_GOTHURTLAND)){
			EstusFlask[_EF_HEALHP2] = 0;
		}
		else{
			//Subtract HP each frame being healed from the total frames
			//Get the difference minus decmials to determine how much to heal Link
			j = Floor(EstusFlask[_EF_HEALHP2]);
			EstusFlask[_EF_HEALHP2] = Max(EstusFlask[_EF_HEALHP2]-EstusFlask[_EF_HEALHPPERFRAME], 0);
			int healAmount = j-Floor(EstusFlask[_EF_HEALHP2]);
			
			Link->HP += healAmount;
			
			//Draw particles around Link if applicable
			if(SPR_ESTUSFLASK_PARTICLES){
				lweapon particle = CreateLWeaponAt(LW_SCRIPT10, Link->X+Rand(-8, 8), Link->Y+Rand(-8, 8));
				particle->UseSprite(SPR_ESTUSFLASK_PARTICLES);
				particle->DeadState = particle->ASpeed*particle->NumFrames;
				particle->CollDetection = false;
				particle->HitYOffset = -1000;
			}
		}
	}
	
	if(EstusFlask[_EF_DOUBLEDRINKTIMER]>0&&EstusFlask[_EF_DRINKTIMER]<=0)
		EstusFlask[_EF_DOUBLEDRINKTIMER]--;
	
	//Reset all guycounts if a bonfire has been used
	j = Game->GetCurMap();
	if(EstusFlask[_EF_LASTMAP]!=j){
		if(EstusFlask[_EF_RESETMAP+j]){
			for(i=0; i<=0x7F; i++){
				Game->GuyCount[i] = 10;
			}
			EstusFlask[_EF_RESETMAP+j] = 0;
		}
	}
	EstusFlask[_EF_LASTMAP] = j;
	
	//If bonfires overwrite continue points, set them every frame
	if(ESTUSFLASK_BONFIRE_OVERRIDES_CONTINUE){
		Game->LastEntranceDMap = EstusFlask[_EF_CONTINUEDMAP];
		Game->LastEntranceScreen = EstusFlask[_EF_CONTINUESCREEN];
		Game->ContinueDMap = EstusFlask[_EF_CONTINUEDMAP];
		Game->ContinueScreen = EstusFlask[_EF_CONTINUESCREEN];
	}
	
	//Update the estus flask tile to suit how many you have
	EstusFlask_RefreshTiles();
}

void EstusFlask_RefreshTiles(){
	if(TIL_ESTUSFLASK_ITEM>0&&STATES_ESTUSFLASK_ITEM>=2){
		int st = 0;
		if(Game->Counter[CR_ESTUSFLASK_COUNT]>0){
			st = Clamp(Round((Game->Counter[CR_ESTUSFLASK_COUNT]/EstusFlask[_EF_MAXREFILL])*(STATES_ESTUSFLASK_ITEM-1)), 1, STATES_ESTUSFLASK_ITEM-1);
		}
		
		CopyTile(TIL_ESTUSFLASK_ITEM+1+st, TIL_ESTUSFLASK_ITEM);
	}
}

//Put this script as the action script on the estus flask item
item script EstusFlask_Use{
	void run(){
		if(Game->Counter[CR_ESTUSFLASK_COUNT]>0){
			//Calculate how much to heal
			int baseHeal = ESTUSFLASK_HEALING;
			if(ESTUSFLASK_UPGRADE_TIERS>0){
				if(Game->Counter[CR_ESTUSFLASK_UPGRADE]>0){
					int addedHealth = Floor((ESTUSFLASK_HEALING_MAX-ESTUSFLASK_HEALING)*(Game->Counter[CR_ESTUSFLASK_UPGRADE]/ESTUSFLASK_UPGRADE_TIERS));
					baseHeal += addedHealth;
				}
			}
			
			//Get percentage of Link's max HP if applicable
			int healAmount = baseHeal;
			if(ESTUSFLASK_HEALING_IS_PERCENT){
				healAmount = Clamp(Round(Link->HP*(baseHeal*0.01)), 0, Link->MaxHP);
			}
			
			if(EstusFlask[_EF_DRINKTIMER]<=0&&EstusFlask[_EF_HEALHP]<=0&&EstusFlask[_EF_DOUBLEDRINKTIMER]<=0){
				Game->PlaySound(SFX_ESTUSFLASK_DRINK);
				//Set how much to heal and start drinking animation
				EstusFlask[_EF_HEALHP] = healAmount;
				EstusFlask[_EF_HEALHPPERFRAME] = healAmount/ESTUSFLASK_HEAL_TIME;
				EstusFlask[_EF_MAXDRINKTIME] = ESTUSFLASK_DRINK_TIME;
				EstusFlask[_EF_DRINKTIMER] = EstusFlask[_EF_MAXDRINKTIME];
				
				//If flasks can be wasted, decrement the counter here, otherwise do it in the global
				if(ESTUSFLASK_CAN_WASTE){
					Game->Counter[CR_ESTUSFLASK_COUNT]--;
				}
			}
			//If already drunk an estus flask, make drinking a second one immediately after go faster
			else if(ESTUSFLASK_CAN_DOUBLE_DRINK&&EstusFlask[_EF_DRINKTIMER]<=0){
				Game->PlaySound(SFX_ESTUSFLASK_DRINK);
				//Set how much to heal and start drinking animation
				EstusFlask[_EF_HEALHP2] += EstusFlask[_EF_HEALHP];
				EstusFlask[_EF_HEALHP] = healAmount;
				EstusFlask[_EF_HEALHPPERFRAME] = healAmount/ESTUSFLASK_HEAL_TIME;
				EstusFlask[_EF_MAXDRINKTIME] = Floor(ESTUSFLASK_DRINK_TIME/2);
				EstusFlask[_EF_DRINKTIMER] = EstusFlask[_EF_MAXDRINKTIME];
				
				//If flasks can be wasted, decrement the counter here, otherwise do it in the global
				if(ESTUSFLASK_CAN_WASTE){
					Game->Counter[CR_ESTUSFLASK_COUNT]--;
				}
			}
		}
	}
}

//Put this script as the pickup script on items that raise your estus flask capacity
//D0: String to play on pickup
//D1: How much to increase capacity by
item script EstusFlask_CapacityUpgrade{
	void run(int str, int amount){
		if(amount==0)
			amount = 1;
		if(str>0)
			Screen->Message(str);
		EstusFlask[_EF_MAXREFILL] = Min(EstusFlask[_EF_MAXREFILL]+amount, ESTUSFLASK_MAX_CAPACITY);
		Game->Counter[CR_ESTUSFLASK_COUNT] = Min(Game->Counter[CR_ESTUSFLASK_COUNT]+amount, ESTUSFLASK_MAX_CAPACITY);
	}
}
//estus flask end

//speed modifier script
const int SPEED_SPELL_DISPEL_ON_UNEQUIP = 1;//If>0 - turn off spell on item unequip.

int Speed_Spell_Drain_Rate = 30;//Delay between drains .
int Speed_Spell_Drain_Cost = 4;//Counter 1 cost at drain times.
int Speed_Spell_Drain_Counter = 7;//Counter 1 used for cost at drain times.
int Speed_Spell_Counter = 0;//Timer used for counter draining and SFX playback. Resets every 15600 frames.
int Speed_Spell_SFX = 4;//Sound to play when spell is active.
int Speed_Spell_SFX_Rate = 192;//Delay between sound playbacks when spell is active.
int Speed_Spell_Modifier = 100;//Default spell speed modifier. Must be set to positive value, if Link starts with speed spell. 
int Speed_Spell_Status = 0;//On/Off status for spell.
int Speed_Spell_Drain_Cost2 = 1;//Counter 2 cost at drain times.
int Speed_Spell_Drain_Counter2 = 1;//Counter 2 used for cost at drain times.

//Speed modifier spell

//Select item in subscreen and set it to turn on or off. If turned on, drains counter and makes Link move faster.

//Requires LinkMovement.zh

//1. Global script combining: 
//	  Put SpeedSpellInit() before LinkMovement_Init() prior to main loop of Active global script.
//    Put UpdateSpeedSpellStatus() before LinkMovement_Update1() prior to Waitdraw() inside main loop of Active global script.
//    Put LinkMovement_Update2() after to Waitdraw() inside main loop of Active global script.
//2. Set up Speed Spell item.
//   Power - additive speed modifier bestowed by spell, when it`s active.
//   UseSound - Sound to play when spell is active.
//   D0 - Delay between magic drain rate
//   D1 - counter cost at drain times.
//   D2 - Delay between sound playbacks when spell is active.
//   D3 - ID of counter of used as fuel.
//   D4 - ID of 2nd counter of used as fuel.
//   D5 - 2nd counter cost at drain times.
//3. Assign SpeedSpellAction to OnAction item script slot and SpeedSpellPickup to OnPickup script slot.

//speedmodifier script end


//day night system by emily start
namespace DayNight
{
	using namespace TintZH;
	typedef const int CONFIG;
	typedef const bool CONFIGB;
	CONFIG DAY_LENGTH = 1; //In minutes, decimal not allowed
	CONFIGB ONLY_OUTDOORS = true; //Should this only apply when outdoors? (i.e. overworld screens)?
	//These are the RGB values for the tint:
	CONFIG NIGHT_R = -21;
	CONFIG NIGHT_G = -23;
	CONFIG NIGHT_B = -10;
	
	int NightTint = NULL; //Needs to be initialized by Tint.zh
	bool nightActive = false; //Start at daytime
	
	void initializeNightTint()
	{
		unless(NightTint)
			NightTint = createTintPalette(NIGHT_R, NIGHT_G, NIGHT_B);
	}
	
	void toggleNight()
	{
		nightActive = !nightActive;
	}
	
	void handleTint()
	{
		if(!ONLY_OUTDOORS || isOverworldScreen())
		{
			setTint(NightTint, nightActive);
		}
		else
		{
			setTint(NightTint,false);
		}
	}
	
	bool isOverworldScreen()
	{
		if(IsDungeonFlag() || IsInteriorFlag())return false;
		dmapdata dm = Game->LoadDMapData(Game->GetCurDMap());
		switch(dm->Type)
		{
			case DMAP_OVERWORLD:
			case DMAP_BSOVERWORLD:
				return true;
		}
		return false;
	}
}
//end daynight system by emily


// Soulslike Death penalty start
const int DEATHPENALTY_RUPEE_LOSS_PERCENT = 25; //Percent of Link's current rupees (0-100) lost on death
const int DEATHPENALTY_NUM_RUPEEBAGS = 4; //How many rupee bags to create
const int DEATHPENALTY_HP_REDUCTION_PERCENT = 0; //If >0 Link's max HP will be reduced by up to this percent (0-100) on death.
const int DEATHPENALTY_HP_REDUCTION_TIERS = 5; //How many tiers of max HP reductions there are

const int DEATHPENALTY_RUPEE_LOSS_IS_FIXED = 0; //If 1, the amount of rupees lost on death is a fixed value instead of a percentage
const int DEATHPENALTY_ACTIVE_ON_F6 = 0; //If 1, the death penalty will happen even if you F6
const int DEATHPENALTY_RESET_F6_HP = 0; //If 1, Link's HP won't be reset on death
const int DEATHPENALTY_MAGNETIZE_RUPEEBAGS = 1; //If 1, rupee bags will move towards Link when he gets close
const int DEATHPENALTY_RUPEEBAGS_USE_DCOUNTER = 1; //If 1, rupee bags will refill rupees gradually, else it's instant
const int DEATHPENALTY_FAST_RUPEE_FILL = 1; //If 1, Link's rupees will fill faster when gaining large amounts at once
const int DEATHPENALTY_HP_REDUCTION_ONLY_FULL_HEARTS = 0; //If 1, HP reduction will only work in full heart increments
const int DEATHPENALTY_RUPEEBAG_REVERSES_HP_REDUCTION = 1; //If 1, picking up a rupee bag from a death that reduced HP will undo the reduction
const int DEATHPENALTY_EXTRA_COUNTER_PENALTY_BASED_ON_MAX = 0; //If 1, counter penalties (see DeathPenalty_GiveTakeCounters() function) take based on the max value of the counter instead of the current
const int DEATHPENALTY_SPECIAL_DEATH_OVERRIDES_OLD_RUPEEBAGS = 1; //If 1, dying to a scripted object that doesn't allow rupee bags will still remove old rupee bags

//Sound when Link picks up a rupee bag
const int SFX_DEATHPENALTY_RUPEEBAG = 25;
//Sound when Link uses a cure curing consumable
const int SFX_DEATHPENALTY_UNCURSE_CONSUMABLE = 25;

//Combo and CSet for the rupee bag
const int CMB_DEATHPENALTY_RUPEEBAG = 5899;
const int CS_DEATHPENALTY_RUPEEBAG = 9;

//Counter for the current level of HP reduction curse. 0 for none.
const int CR_DEATHPENALTY_HP_REDUCTION = 7; //Script 1 by default
//Counter for the number of held HP reduction curing items
const int CR_DEATHPENALTY_HP_REDUCTION_CURES = 8; //Script 2 by default

const int _DP_HASDIED = 0;
const int _DP_ANIM = 1;
const int _DP_FIRSTLOAD = 2;
const int _DP_RUPEEBAG_MAP = 3;
const int _DP_RUPEEBAG_SCREEN = 4;
const int _DP_HPREDUCTION_TIER = 5;
const int _DP_LASTX = 6;
const int _DP_LASTY = 7;
const int _DP_LASTHP = 8;
const int _DP_LASTMAP = 9;
const int _DP_LASTSCREEN = 10;
const int _DP_LOADEDSAVE = 11;
const int _DP_RUPEEBAG_HASCURSE = 12;
const int _DP_RUPEEBAG_HASITEMS = 13;
const int _DP_DONTSPAWNBAGS = 14;
const int _DP_RUPEEBAG_X = 20;
const int _DP_RUPEEBAG_Y = 21;
const int _DP_RUPEEBAG_AMOUNT = 22;

const int _DP_TAKENITEMS = 100; //First of taken item indices (100-355)

const int _DP_TAKENCOUNTERS = 400; //First of taken counter indices (400-431)
int DeathPenalty[432];

void DeathPenalty_Init(){
	int i; int j; int k;
	int x; int y;
	
	int numRupeeBags = Clamp(DEATHPENALTY_NUM_RUPEEBAGS, 1, 20);
	int rupeeLossPercent = Clamp(DEATHPENALTY_RUPEE_LOSS_PERCENT, 0, 100)*0.01;

	if(DeathPenalty[_DP_LOADEDSAVE]){
		DeathPenalty[_DP_LOADEDSAVE] = 0;
	}
	else if(!DeathPenalty[_DP_FIRSTLOAD]){
		DeathPenalty[_DP_FIRSTLOAD] = 1;
	}
	//If penalties should activate and it isn't the first load
	else if(DeathPenalty[_DP_HASDIED]||DEATHPENALTY_ACTIVE_ON_F6){
		//Add draining rupees to the main counter
		Game->Counter[CR_RUPEES] += Game->DCounter[CR_RUPEES];
	
		int rupeeVals[20];
		int lostRupees = Ceiling(Game->Counter[CR_RUPEES]*rupeeLossPercent);
		if(DEATHPENALTY_RUPEE_LOSS_IS_FIXED)
			lostRupees = DEATHPENALTY_RUPEE_LOSS_PERCENT;
		
		int lastRupees = Game->Counter[CR_RUPEES];
		Game->Counter[CR_RUPEES] = Max(Game->Counter[CR_RUPEES]-lostRupees, 0);
		lostRupees = Abs(lastRupees-Game->Counter[CR_RUPEES]);
		
		int rupeesPerBag = lostRupees/numRupeeBags;
		
		//Set rupee values to a fraction of the whole
		for(i=0; i<numRupeeBags; i++){
			rupeeVals[i] = Floor(rupeesPerBag);
		}
		//If it doesn't divide evenly, add 1 rupee to the first bag
		if(rupeesPerBag-Floor(rupeesPerBag)>0)
			rupeeVals[0] += lostRupees-Floor(rupeesPerBag)*numRupeeBags;
			
		//Move some rupees between bags at random
		for(i=0; i<numRupeeBags-1; i++){
			k = Floor(rupeesPerBag*(Rand(5, 20)*0.01));
			if(Rand(2)){
				rupeeVals[i] -= k;
				rupeeVals[i+1] += k;
			}
			else{
				rupeeVals[i] += k;
				rupeeVals[i+1] -= k;
			}
		}
		if(numRupeeBags>1){
			k = Floor(rupeesPerBag*(Rand(5, 20)*0.01));
			if(Rand(2)){
				rupeeVals[0] -= k;
				rupeeVals[numRupeeBags-1] += k;
			}
			else{
				rupeeVals[0] += k;
				rupeeVals[numRupeeBags-1] -= k;
			}
		}
	
		if(DEATHPENALTY_NUM_RUPEEBAGS>0){
			if(!DeathPenalty[_DP_DONTSPAWNBAGS]){
				//Create the rupee bags
				for(i=0; i<numRupeeBags; i++){
					if(numRupeeBags>1){
						j = Rand(360);
						k = Rand(8, 40);
						
						x = DeathPenalty[_DP_LASTX] + VectorX(k, j);
						y = DeathPenalty[_DP_LASTY] + VectorY(k, j);
					}
					else{
						x = DeathPenalty[_DP_LASTX];
						y = DeathPenalty[_DP_LASTY];
					}
					DeathPenalty[_DP_RUPEEBAG_X+i*3] = x;
					DeathPenalty[_DP_RUPEEBAG_Y+i*3] = y;
					if(DEATHPENALTY_RUPEE_LOSS_PERCENT)
						DeathPenalty[_DP_RUPEEBAG_AMOUNT+i*3] = rupeeVals[i];
					else
						DeathPenalty[_DP_RUPEEBAG_AMOUNT+i*3] = 1;
				}
			}
		}
		//Script related event where bags are prevented from spawning
		if(DeathPenalty[_DP_DONTSPAWNBAGS]){
			if(DEATHPENALTY_SPECIAL_DEATH_OVERRIDES_OLD_RUPEEBAGS){
				//Remove old rupee bags
				for(i=0; i<numRupeeBags; i++){
					DeathPenalty[_DP_RUPEEBAG_AMOUNT+i*3] = 0;
				}
			}
			DeathPenalty[_DP_DONTSPAWNBAGS] = 0;
		}
		
		DeathPenalty[_DP_RUPEEBAG_MAP] = DeathPenalty[_DP_LASTMAP];
		DeathPenalty[_DP_RUPEEBAG_SCREEN] = DeathPenalty[_DP_LASTSCREEN];
		
		//Handle the HP curse
		DeathPenalty[_DP_RUPEEBAG_HASCURSE] = 0;
		if(DEATHPENALTY_HP_REDUCTION_PERCENT>0){
			//Mark if rupee bag is able to undo the curse
			if(DEATHPENALTY_RUPEEBAG_REVERSES_HP_REDUCTION&&DeathPenalty[_DP_HPREDUCTION_TIER]<DEATHPENALTY_HP_REDUCTION_TIERS)
				DeathPenalty[_DP_RUPEEBAG_HASCURSE] = 1;
			
			//Increase HP reduction penalty
			DeathPenalty[_DP_HPREDUCTION_TIER] = Clamp(DeathPenalty[_DP_HPREDUCTION_TIER]+1, 0, DEATHPENALTY_HP_REDUCTION_TIERS);
		}
		
		//Take items on death
		DeathPenalty_GiveTakeItems(true);
		
		//Take counters on death
		DeathPenalty_GiveTakeCounters(true);
		
		//Keep HP on F6
		if(DEATHPENALTY_RESET_F6_HP){
			if(!DeathPenalty[_DP_HASDIED]&&DeathPenalty[_DP_LASTHP]>0)
				Link->HP = DeathPenalty[_DP_LASTHP];
		}
		
	}
	
	DeathPenalty[_DP_LASTX] = Link->X;
	DeathPenalty[_DP_LASTY] = Link->Y;
}

void DeathPenalty_Update(){
	if(Link->Action==LA_SCROLLING)
		return;
	
	int i; int j; int k;
	int x; int y;
	
	int numRupeeBags = Clamp(DEATHPENALTY_NUM_RUPEEBAGS, 1, 20);
	int rupeeLossPercent = Clamp(DEATHPENALTY_RUPEE_LOSS_PERCENT, 0, 100)*0.01;
	int hpReductionPercent = Clamp(DEATHPENALTY_HP_REDUCTION_PERCENT, 0, 99)*0.01;
	
	//If Link is on the same screen as the rupee bags
	if(Game->GetCurMap()==DeathPenalty[_DP_RUPEEBAG_MAP]&&Game->GetCurScreen()==DeathPenalty[_DP_RUPEEBAG_SCREEN]&&Link->HP>0){
		for(i=0; i<numRupeeBags; i++){
			//Only draw bags with rupees in them
			if(DeathPenalty[_DP_RUPEEBAG_AMOUNT+i*3]>0){
				x = DeathPenalty[_DP_RUPEEBAG_X+i*3];
				y = DeathPenalty[_DP_RUPEEBAG_Y+i*3];
				
				//Detect Link collisions
				if(RectCollision(Link->X+Link->HitXOffset+4, Link->Y+Link->HitYOffset+4, Link->X+Link->HitXOffset+11, Link->Y+Link->HitYOffset+11, x+4, y+4, x+11, y+11)){
					if(Link->Z==0&&!Link->Invisible){
						Game->PlaySound(SFX_DEATHPENALTY_RUPEEBAG);
						if(DEATHPENALTY_RUPEE_LOSS_PERCENT){
							if(DEATHPENALTY_RUPEEBAGS_USE_DCOUNTER){
								Game->DCounter[CR_RUPEES] += DeathPenalty[_DP_RUPEEBAG_AMOUNT+i*3];
							}
							else{
								Game->Counter[CR_RUPEES] += DeathPenalty[_DP_RUPEEBAG_AMOUNT+i*3];
							}
						}
						
						DeathPenalty[_DP_RUPEEBAG_AMOUNT+i*3] = 0;
						
						if(DeathPenalty[_DP_RUPEEBAG_HASCURSE]){
							DeathPenalty[_DP_HPREDUCTION_TIER] = Clamp(DeathPenalty[_DP_HPREDUCTION_TIER]-1, 0, DEATHPENALTY_HP_REDUCTION_TIERS);
							DeathPenalty[_DP_RUPEEBAG_HASCURSE] = 0;
						}
						
						if(DeathPenalty[_DP_RUPEEBAG_HASITEMS]){
							DeathPenalty_GiveTakeItems(false);
							DeathPenalty_GiveTakeCounters(false);
							DeathPenalty[_DP_RUPEEBAG_HASITEMS] = 0;
						}
					}
				}
				
				//Magnetize effect
				if(DEATHPENALTY_MAGNETIZE_RUPEEBAGS){
					if(Distance(Link->X, Link->Y, x, y)<48){
						j = Angle(x, y, Link->X, Link->Y);
						k = 24/Max(1, Distance(Link->X, Link->Y, x, y));
						
						DeathPenalty[_DP_RUPEEBAG_X+i*3] += VectorX(k, j);
						DeathPenalty[_DP_RUPEEBAG_Y+i*3] += VectorY(k, j);
					}
				}
				
				Screen->FastCombo(4, x, y, CMB_DEATHPENALTY_RUPEEBAG, CS_DEATHPENALTY_RUPEEBAG, 128);
			}
		}
	}

	//Max HP penalty
	if(DEATHPENALTY_HP_REDUCTION_PERCENT){
		i = Floor((DeathPenalty[_DP_HPREDUCTION_TIER]/DEATHPENALTY_HP_REDUCTION_TIERS)*hpReductionPercent*Link->HP);
		if(DEATHPENALTY_HP_REDUCTION_ONLY_FULL_HEARTS)
			i = Round(i/16)*16;
		Link->HP = Min(Link->HP, Link->MaxHP-i);
		
		if(CR_DEATHPENALTY_HP_REDUCTION>0){
			Game->Counter[CR_DEATHPENALTY_HP_REDUCTION] = DeathPenalty[_DP_HPREDUCTION_TIER];
		}
	}
	
	//Track HP to undo on F6
	DeathPenalty[_DP_LASTHP] = Link->HP;
	
	//Keep track of if Link died
	if(Link->HP<=0){
		DeathPenalty[_DP_HASDIED] = 1;
	}
	else if(DeathPenalty[_DP_HASDIED]){
		DeathPenalty[_DP_HASDIED] = 0;
	}
	
	//Fast draining rupees
	if(DEATHPENALTY_FAST_RUPEE_FILL){
		int dc = Abs(Game->DCounter[CR_RUPEES]);
		int sign = Sign(Game->DCounter[CR_RUPEES]);
		if(dc>=1000){
			Game->Counter[CR_RUPEES] += 100*sign;
			Game->DCounter[CR_RUPEES] -= 100*sign;
		}
		else if(dc>=500){
			Game->Counter[CR_RUPEES] += 50*sign;
			Game->DCounter[CR_RUPEES] -= 50*sign;
		}
		else if(dc>=200){
			Game->Counter[CR_RUPEES] += 20*sign;
			Game->DCounter[CR_RUPEES] -= 20*sign;
		}
		else if(dc>=100){
			Game->Counter[CR_RUPEES] += 10*sign;
			Game->DCounter[CR_RUPEES] -= 10*sign;
		}
		else if(dc>=50){
			Game->Counter[CR_RUPEES] += 5*sign;
			Game->DCounter[CR_RUPEES] -= 5*sign;
		}
		else if(dc>=20){
			Game->Counter[CR_RUPEES] += 2*sign;
			Game->DCounter[CR_RUPEES] -= 2*sign;
		}
	}
	
	DeathPenalty[_DP_LASTX] = Link->X;
	DeathPenalty[_DP_LASTY] = Link->Y;
	DeathPenalty[_DP_LASTMAP] = Game->GetCurMap();
	DeathPenalty[_DP_LASTSCREEN] = Game->GetCurScreen();
	
	//If the script is set to not spawn bags and Link isn't actually dead that frame, undo that
	if(DeathPenalty[_DP_DONTSPAWNBAGS]&&Link->HP>0)
		DeathPenalty[_DP_DONTSPAWNBAGS] = 0;
}

void DeathPenalty_GiveTakeItems(bool take){
	int i;
	int ItemsToTake[256];
	
	//Examples
	//ItemsToTake[17] = 2; //EXAMPLE: Blue ring - Taken forever
	//ItemsToTake[6] = 1; //EXAMPLE: Sword 2 - Can be regained
	
	if(take){
		for(i=0; i<256; i++){
			DeathPenalty[_DP_TAKENITEMS+i] = 0;
			if(ItemsToTake[i]){
				if(Link->Item[i]&&ItemsToTake[i]==1){
					DeathPenalty[_DP_TAKENITEMS+i] = 1;
					DeathPenalty[_DP_RUPEEBAG_HASITEMS] = 1;
				}
				Link->Item[i] = false;
			}
		}
	}
	else{
		for(i=0; i<256; i++){
			if(DeathPenalty[_DP_TAKENITEMS+i]){
				Link->Item[i] = true;
				DeathPenalty[_DP_TAKENITEMS+i] = 0;
			}
		}
	}
}

void DeathPenalty_GiveTakeCounters(bool take){
	int i;
	if(take){
		int counterBehavior[32];
		int counterPercent[32];
		int tc[2] = {counterBehavior, counterPercent};
		
		//Examples
		//DeathPenalty_TakeCounter_Percent(tc, CR_ARROWS, false, 50); //EXAMPLE: Takes 50% of arrows, can be regained
		//DeathPenalty_TakeCounter_Exact(tc, CR_BOMBS, true, 5); //EXAMPLE: Takes 5 bombs, can't be regained
		
		for(i=0; i<32; i++){
			if(counterBehavior[i]){
				int amountTaken = Abs(counterPercent[i]);
				//If counter percent is positive, take a percentage of the counter. Otherwise takea fixed value
				if(counterPercent[i]>0){
					if(DEATHPENALTY_EXTRA_COUNTER_PENALTY_BASED_ON_MAX)
						amountTaken = Ceiling(Game->MCounter[i]*(counterPercent[i]*0.01));
					else
						amountTaken = Ceiling(Game->Counter[i]*(counterPercent[i]*0.01));
				}
				int oldAmount = Game->Counter[i];
				Game->Counter[i] = Max(Game->Counter[i]-amountTaken, 0);
				//If the taken counter items can be regained
				if(counterBehavior[i]==1){
					//Store how much was taken from the counter
					DeathPenalty[_DP_TAKENCOUNTERS+i] = Abs(oldAmount-Game->Counter[i]);
					DeathPenalty[_DP_RUPEEBAG_HASITEMS] = 1;
				}
			}
		}
	}
	else{
		for(i=0; i<32; i++){
			if(DeathPenalty[_DP_TAKENCOUNTERS+i]){
				Game->Counter[i] += DeathPenalty[_DP_TAKENCOUNTERS+i];
				DeathPenalty[_DP_TAKENCOUNTERS+i] = 0;
			}
		}
	}
}

void DeathPenalty_TakeCounter_Percent(int tc, int whichCounter, bool permanent, int percent){
	int counterBehavior = tc[0];
	int counterPercent = tc[1];
	
	counterBehavior[whichCounter] = 1;
	if(permanent)
		counterBehavior[whichCounter] = 2;
	counterPercent[whichCounter] = Abs(percent);
}

void DeathPenalty_TakeCounter_Exact(int tc, int whichCounter, bool permanent, int amount){
	int counterBehavior = tc[0];
	int counterPercent = tc[1];
	
	counterBehavior[whichCounter] = 1;
	if(permanent)
		counterBehavior[whichCounter] = 2;
	counterPercent[whichCounter] = -Abs(amount);
}

//Disables rupee bags for one frame
void DeathPenalty_DisableRupeeBags(){
	if(Link->HP<=0)
		DeathPenalty[_DP_DONTSPAWNBAGS] = 1;
}

//This script is for items that when picked up remove the HP curse
item script DeathPenalty_UncursePickup{
	void run(int msg){
		if(msg>0)
			Screen->Message(msg);
		DeathPenalty[_DP_HPREDUCTION_TIER] = 0;
	}
}

//This script is for items that when used remove the HP curse
item script DeathPenalty_UncurseConsumable{
	void run(){
		if(Game->Counter[CR_DEATHPENALTY_HP_REDUCTION_CURES]>0&&DeathPenalty[_DP_HPREDUCTION_TIER]>0){
			Game->PlaySound(SFX_DEATHPENALTY_UNCURSE_CONSUMABLE);
			DeathPenalty[_DP_HPREDUCTION_TIER] = 0;
			Game->Counter[CR_DEATHPENALTY_HP_REDUCTION_CURES]--;
		}
	}
}

///soulslike death penalty end

/// dark souls status

namespace DarkSoulsStatus{

	void UpdateDeathPenalty(){
		//If you're using my death penalty script, uncomment this line
	DeathPenalty[_DP_HASDIED] = 1;
	}
	
	//Status bar drawn position
	const int STATUSBARS_ON_LINK = 0; //0 - Top of screen, 1 - Above Link
	//Status warning drawn positio
	const int STATUSWARNINGS_ON_LINK = 0; //0 - Center Screen, 1 - Above Link, 2 - Invisible
	
	const int FONT_STATUSWARNINGS = FONT_SHERWOOD;

	//Misc colors
	const int C_STATUSBAR_BG = 0x0F; //Meter background
	const int C_STATUSBAR_FG = 0x01; //Meter outline
	const int C_STATUSBAR_TEXTSHADOW = 0x0F; //Text outline and other black things

	//Stats for modifying status. Damage values are percentage based if negative. Decay is a percentage lost every frame.

	//Stats for poison status
	const int POISON_TILE = 4737;
	const int POISON_DAMAGE = 1;
	const int POISON_TICKFREQ = 60;
	const int POISON_DURATION = 2400;
	const int POISON_DECAY = 0.05;
	const int POISON_COLOR1 = 0x51;
	const int POISON_COLOR2 = 0x52;

	//Stats for toxic status
	const int TOXIC_TILE = 4736;
	const int TOXIC_DAMAGE = -5;
	const int TOXIC_TICKFREQ = 60;
	const int TOXIC_DURATION = 1200;
	const int TOXIC_DECAY = 0.01;
	const int TOXIC_COLOR1 = 0xA1;
	const int TOXIC_COLOR2 = 0xA2;

	//Stats for bleed status
	const int BLEED_TILE = 4738;
	const int BLEED_DAMAGE = -40;
	const int BLEED_DECAY = 0.01;
	const int BLEED_COLOR1 = 0x85;
	const int BLEED_COLOR2 = 0x81;

	//Stats for frost status
	const int FROST_TILE = 4739;
	const int FROST_DAMAGE = -10;
	const int FROST_HPPENALTY = 1.5; //Multiplier for damage while inflicted
	const int FROST_MPPENALTY = 1.5; //Multiplier for MP used while inflicted
	const int FROST_DURATION = 1200;
	const int FROST_DECAY = 0.05;
	const int FROST_COLOR1 = 0x72;
	const int FROST_COLOR2 = 0x73;

	//Stats for curse status
	const int CURSE_TILE = 4740;
	const int CURSE_HPREDUCE = 0.5; //Percentage of HP reduced while cursed
	const int CURSE_KILLS = 0; //Whether or not curse is instant death when inflicted
	const int CURSE_DURATION = -1; //Duration of curse, -1 for infinite
	const int CURSE_DECAY = 0.05;
	const int CURSE_COLOR1 = 0xB1;
	const int CURSE_COLOR2 = 0xB2;
	
	//Sounds when inflicted with each status
	const int SFX_POISON = 68;
	const int SFX_TOXIC = 66;
	const int SFX_BLEED = 67;
	const int SFX_FROST = 65;
	const int SFX_CURSE = 69;
	
	//Sounds for damage ticks from statuses
	const int SFX_POISON_TICK = 71;
	const int SFX_TOXIC_TICK = 70;
	
	int DSStatus[512];

	//INTERNAL CONSTANTS, DON'T MESS WITH THESE
	enum StatusType {POISON, TOXIC, BLEED, FROST, CURSE, NUMSTATUS};

	const int _ANIM = 0;
	const int _CURSEFRAME = 1;
	const int _SWAMPCOUNTER = 2;
	const int _STATUSDATASTART = 16;

	enum StatusData {BUILDUP, TIME, MAXTIME, DECAYDELAY, NUMSTATUSDATA};
	//END OF INTERNAL CONSTANTS
	
	//Functions for accessing array indices
	int GetData(int status, int which){
		return DSStatus[_STATUSDATASTART+NUMSTATUSDATA*status+which];
	}
	void SetData(int status, int which, int val){
		DSStatus[_STATUSDATASTART+NUMSTATUSDATA*status+which] = val;
	}
	void AddData(int status, int which, int val){
		DSStatus[_STATUSDATASTART+NUMSTATUSDATA*status+which] += val;
	}
	void ClampData(int status, int which, int min, int max){
		DSStatus[_STATUSDATASTART+NUMSTATUSDATA*status+which] = Clamp(DSStatus[_STATUSDATASTART+NUMSTATUSDATA*status+which], min, max);
	}
	
	//Functions for getting status settings
	float StatusTile(int status){
		switch(status){
			case POISON:
				return POISON_TILE;
			case TOXIC:
				return TOXIC_TILE;
			case BLEED:
				return BLEED_TILE;
			case FROST:
				return FROST_TILE;
			case CURSE:
				return CURSE_TILE;
		}
	}
	float StatusDuration(int status){
		switch(status){
			case POISON:
				return POISON_DURATION;
			case TOXIC:
				return TOXIC_DURATION;
			case BLEED:
				return 0;
			case FROST:
				return FROST_DURATION;
			case CURSE:
				return CURSE_DURATION;
		}
	}
	float StatusDecay(int status){
		switch(status){
			case POISON:
				return POISON_DECAY;
			case TOXIC:
				return TOXIC_DECAY;
			case BLEED:
				return BLEED_DECAY;
			case FROST:
				return FROST_DECAY;
			case CURSE:
				return CURSE_DECAY;
		}
	}
	float StatusColor1(int status){
		switch(status){
			case POISON:
				return POISON_COLOR1;
			case TOXIC:
				return TOXIC_COLOR1;
			case BLEED:
				return BLEED_COLOR1;
			case FROST:
				return FROST_COLOR1;
			case CURSE:
				return CURSE_COLOR1;
		}
	}
	float StatusColor2(int status){
		switch(status){
			case POISON:
				return POISON_COLOR2;
			case TOXIC:
				return TOXIC_COLOR2;
			case BLEED:
				return BLEED_COLOR2;
			case FROST:
				return FROST_COLOR2;
			case CURSE:
				return CURSE_COLOR2;
		}
	}
	
	//Returns true if the status bars can be drawn
	bool CanDrawStatus(){
		switch(Link->Action){
			case LA_SCROLLING:
			case LA_HOLD1LAND:
			case LA_HOLD2LAND:
			case LA_HOLD1WATER:
			case LA_HOLD2WATER:
				return false;
		}
		return true;
	}
	
	//Draws a status meter to the screen
	void DrawStatusMeter(int x, int y, int til, int c1, int c2, int percent, bool flash){
		Screen->Rectangle(6, x+8, y+2, x+8+17, y+6, C_STATUSBAR_BG, 1, 0, 0, 0, true, 128);
		Screen->Rectangle(6, x+8, y+2, x+8+17, y+6, C_STATUSBAR_FG, 1, 0, 0, 0, false, 128);
		int c = c1;
		if(flash&&DSStatus[_ANIM]%4<2)
			c = c2;
		Screen->Rectangle(6, x+9, y+3, x+Lerp(8+1, 8+16, percent), y+5, c, 1, 0, 0, 0, true, 128);
		Screen->FastTile(6, x, y, til, 0, 128);
	}		

	//These items will reduce the effect of status buildup. If 0, no item has that effect
	const int I_RING_POISONBITE = 145;
	const int MULTIPLIER_POISONBITE = 0.5;
	
	const int I_RING_TOXINBITE = 148;
	const int MULTIPLIER_TOXINBITE = 0.5;
	
	const int I_RING_BLOODBITE = 150;
	const int MULTIPLIER_BLOODBITE = 0.5;
	
	const int I_RING_FROSTBITE = 149;
	const int MULTIPLIER_FROSTBITE = 0.5;
	
	const int I_RING_CURSEBITE = 147;
	const int MULTIPLIER_CURSEBITE = 0.5;

	//Fills a status by a certain amount
	void FillStatus(int status, int amount, int maxTime){
		switch(status){
			case POISON:
				if(I_RING_POISONBITE){
					if(Link->Item[I_RING_POISONBITE])
						amount = Ceiling(amount*MULTIPLIER_POISONBITE);
				}
				break;
			case TOXIC:
				if(I_RING_TOXINBITE){
					if(Link->Item[I_RING_TOXINBITE])
						amount = Ceiling(amount*MULTIPLIER_TOXINBITE);
				}
				break;
			case BLEED:
				if(I_RING_BLOODBITE){
					if(Link->Item[I_RING_BLOODBITE])
						amount = Ceiling(amount*MULTIPLIER_BLOODBITE);
				}
				break;
			case FROST:
				if(I_RING_FROSTBITE){
					if(Link->Item[I_RING_FROSTBITE])
						amount = Ceiling(amount*MULTIPLIER_FROSTBITE);
				}
				break;
			case CURSE:
				if(I_RING_CURSEBITE){
					if(Link->Item[I_RING_CURSEBITE])
						amount = Ceiling(amount*MULTIPLIER_CURSEBITE);
				}
				break;
		}
		AddData(status, BUILDUP, amount);
		SetData(status, MAXTIME, maxTime);
		SetData(status, DECAYDELAY, 48);
		ClampData(status, BUILDUP, 0, 100);
	}
	
	//Damages Link with status
	void DamageLinkStatus(int damage){
		if(damage<0){
			damage = Ceiling(Link->MaxHP*(Abs(damage)/100));
		}
		Link->HP -= damage;
	}

	void Init(){
		DSStatus[_CURSEFRAME] = 0;
		for(int i=0; i<NUMSTATUS; ++i){
			SetData(i, BUILDUP, 0);
			if(i!=CURSE)
				SetData(i, TIME, 0);
			SetData(i, MAXTIME, 0);
			SetData(i, DECAYDELAY, 0);
		}
		if(GetData(CURSE, TIME)!=0){
			genericdata gd = Game->LoadGenericData(Game->GetGenericScript("CurseEffect"));
			gd->Running = true;
		}
	}
	
	void Update(){
		DSStatus[_ANIM] = (DSStatus[_ANIM]+1)%360;
		int numMeters;
		for(int i=0; i<NUMSTATUS; ++i){
			int drawMeterFill;
			bool flashMeter;
			//Status is active
			if(GetData(i, TIME)!=0){
				switch(i){
					case POISON:
						break;
				}
				
				if(GetData(i, TIME)>0){
					drawMeterFill = Clamp(GetData(i, TIME)/GetData(i, MAXTIME), 0, 1);
					flashMeter = true;
					AddData(i, TIME, -1);
				}
				else if(GetData(i, TIME)==-1){
					drawMeterFill = 1;
				}
				SetData(i, BUILDUP, 0);
			}
			//Status is being filled
			else if(GetData(i, BUILDUP)){
				//Status is fully filled
				if(GetData(i, BUILDUP)>=100){
					SetData(i, BUILDUP, 0);
					SetData(i, TIME, GetData(i, MAXTIME));
					switch(i){
						case POISON:
							genericdata gd = Game->LoadGenericData(Game->GetGenericScript("PoisonEffect"));
							gd->Running = true;
							break;
						case TOXIC:
							genericdata gd = Game->LoadGenericData(Game->GetGenericScript("ToxicEffect"));
							gd->Running = true;
							break;
						case BLEED:
							genericdata gd = Game->LoadGenericData(Game->GetGenericScript("BleedEffect"));
							gd->Running = true;
							break;
						case FROST:
							genericdata gd = Game->LoadGenericData(Game->GetGenericScript("FrostEffect"));
							gd->Running = true;
							break;
						case CURSE:
							DSStatus[_CURSEFRAME] = 1;
							genericdata gd = Game->LoadGenericData(Game->GetGenericScript("CurseEffect"));
							gd->Running = true;
							break;
					}
				}
				//Status is filling/decaying
				else{
					if(GetData(i, DECAYDELAY)>0)
						AddData(i, DECAYDELAY, -1);
					else{
						AddData(i, BUILDUP, -StatusDecay(i));
						ClampData(i, BUILDUP, 0, 100);
					}
					
					drawMeterFill = Clamp(GetData(i, BUILDUP)/100, 0, 1);
				}
			}
		
			if(drawMeterFill>0){
				if(CanDrawStatus()){
					if(STATUSBARS_ON_LINK)
						DrawStatusMeter(Link->X-6, Link->Y-10-numMeters*10, StatusTile(i), StatusColor1(i), StatusColor2(i), drawMeterFill, flashMeter);
					else
						DrawStatusMeter(8+32*numMeters, 8, StatusTile(i), StatusColor1(i), StatusColor2(i), drawMeterFill, flashMeter);
				}
				++numMeters;
			}
		}
	}
	
	void DrawEffectLabel(int statusType, int str, int labelFrames, int drawTime){
		if(STATUSWARNINGS_ON_LINK==2)
			return;
		int x = 128;
		int y = 88;
		if(STATUSWARNINGS_ON_LINK){
			x = Link->X;
			y = Link->Y-8;
			int stringW = Text->StringWidth(str, FONT_STATUSWARNINGS);
			if(x-stringW/2<8)
				x += Abs((x-stringW/2)-8);
			if(x+stringW/2>248)
				x -= Abs((x+stringW/2)-248);
		}
		if(labelFrames[0]<drawTime){
			int op = 128;
			if(labelFrames[0]>=drawTime-8)
				op = 64;
			int c = StatusColor1(statusType);
			if(labelFrames[0]%4<2)
				c = StatusColor2(statusType);
			Screen->DrawString(6, x, y-labelFrames[0]/2-Text->FontHeight(FONT_STATUSWARNINGS)/2, FONT_STATUSWARNINGS, c, -1, TF_CENTERED, str, op, SHD_OUTLINED8, C_STATUSBAR_TEXTSHADOW);
			++labelFrames[0];
		}
	}
	
	generic script PoisonEffect{
		void run(){
			this->ExitState[GENSCR_ST_RELOAD] = true;
			this->ExitState[GENSCR_ST_CONTINUE] = true;
			int labelFrames[1];
			int damageTimer;
			if(SFX_POISON)
				Game->PlaySound(SFX_POISON);
			while(GetData(POISON, TIME)>0){
				WaitTo(SCR_TIMING_POST_GLOBAL_ACTIVE, false);
				DrawEffectLabel(POISON, "POISONED", labelFrames, 64);
				++damageTimer;
				if(damageTimer>=POISON_TICKFREQ){
					if(SFX_POISON_TICK)
						Game->PlaySound(SFX_POISON_TICK);
					DamageLinkStatus(POISON_DAMAGE);
					damageTimer = 0;
				}
				Waitframe();
			}
		}
	}
	
	generic script ToxicEffect{
		void run(){
			this->ExitState[GENSCR_ST_RELOAD] = true;
			this->ExitState[GENSCR_ST_CONTINUE] = true;
			int labelFrames[1];
			int damageTimer;
			if(SFX_TOXIC)
				Game->PlaySound(SFX_TOXIC);
			while(GetData(TOXIC, TIME)>0){
				WaitTo(SCR_TIMING_POST_GLOBAL_ACTIVE, false);
				DrawEffectLabel(TOXIC, "TOXIC", labelFrames, 64);
				++damageTimer;
				if(damageTimer>=TOXIC_TICKFREQ){
					if(SFX_TOXIC_TICK)
						Game->PlaySound(SFX_TOXIC_TICK);
					DamageLinkStatus(TOXIC_DAMAGE);
					damageTimer = 0;
				}
				Waitframe();
			}
		}
	}
	
	const int SPR_BLEEDPARTICLES = 119; //2x2 sprite animation used for bleed
	
	generic script BleedEffect{
		void run(){
			this->ExitState[GENSCR_ST_RELOAD] = true;
			this->ExitState[GENSCR_ST_CONTINUE] = true;
			int labelFrames[1];
			int damageTimer;
			if(SFX_BLEED)
				Game->PlaySound(SFX_BLEED);
			if(SPR_BLEEDPARTICLES){
				lweapon bleed = CreateLWeaponAt(LW_SPARKLE, Link->X, Link->Y);
				bleed->DrawXOffset = -8;
				bleed->DrawYOffset = -8;
				bleed->Extend = 3;
				bleed->TileWidth = 2;
				bleed->TileHeight = 2;
				bleed->UseSprite(SPR_BLEEDPARTICLES);
			}
			int totalDamage = BLEED_DAMAGE;
			if(BLEED_DAMAGE<0)
				totalDamage = Ceiling(Link->MaxHP*(Abs(BLEED_DAMAGE)/100));
			int remainingDamage = totalDamage;
			for(int i=0; i<64; ++i){
				WaitTo(SCR_TIMING_POST_GLOBAL_ACTIVE, false);
				DrawEffectLabel(BLEED, "BLOOD LOSS", labelFrames, 64);
				
				int tickDamage = Clamp(Ceiling(totalDamage/32), 0, remainingDamage);
				Link->HP -= tickDamage;
				remainingDamage -= tickDamage;
				
				Waitframe();
			}
		}
	}
	
	generic script FrostEffect{
		void run(){
			this->ExitState[GENSCR_ST_RELOAD] = true;
			this->ExitState[GENSCR_ST_CONTINUE] = true;
			int labelFrames[1];
			int damageTimer;
			if(SFX_FROST)
				Game->PlaySound(SFX_FROST);
			
			int totalDamage = FROST_DAMAGE;
			if(FROST_DAMAGE<0)
				totalDamage = Ceiling(Link->MaxHP*(Abs(FROST_DAMAGE)/100));
			int remainingDamage = totalDamage;
			
			int lastLinkHP = Link->HP;
			int lastLinkMP = Link->MP;
			while(GetData(FROST, TIME)>0){
				WaitTo(SCR_TIMING_POST_GLOBAL_ACTIVE, false);
				DrawEffectLabel(FROST, "FROSTBITTEN", labelFrames, 64);
				
				//Deal initial ticks of damage
				if(remainingDamage>0){
					int tickDamage = Clamp(Ceiling(totalDamage/32), 0, remainingDamage);
					Link->HP -= tickDamage;
					remainingDamage -= tickDamage;
				}
				//Extra damage when Link gets hit
				else{
					if(Link->HP<lastLinkHP){
						int damage = lastLinkHP-Link->HP;
						Link->HP -= Ceiling(damage*(FROST_HPPENALTY-1));
					}
				}
				
				//Increase MP costs
				if(Link->MP<lastLinkMP){
					int cost = lastLinkMP-Link->MP;
					Link->MP = Max(Link->MP-Ceiling(cost*(FROST_MPPENALTY-1)), 0);
				}
				
				lastLinkHP = Link->HP;
				lastLinkMP = Link->MP;
				
				Waitframe();
			}
		}
	}
	
	generic script CurseEffect{
		void run(){
			this->ExitState[GENSCR_ST_RELOAD] = true;
			this->ExitState[GENSCR_ST_CONTINUE] = true;
			int labelFrames[1];
			int damageTimer;
			if(DSStatus[_CURSEFRAME]){
				if(SFX_CURSE)
					Game->PlaySound(SFX_CURSE);
				if(CURSE_KILLS){
					genericdata gd = Game->LoadGenericData(Game->GetGenericScript("CurseDeathAnim"));
					Link->Invisible = true;
					Waitframe();
					gd->RunFrozen();
				}
			}
			DSStatus[_CURSEFRAME] = 0;
			
			while(GetData(CURSE, TIME)!=0){
				if(!CURSE_KILLS)
					DrawEffectLabel(CURSE, "CURSED", labelFrames, 64);
				
				if(Link->HP>Ceiling(Link->MaxHP*CURSE_HPREDUCE))
					--Link->HP;
				
				Waitframe();
			}
		}
	}
	
	//Data for the tile animation that plays when Link is cursed
	const int CURSE_ANIM_TILE = 1138;
	const int CURSE_ANIM_W = 1;
	const int CURSE_ANIM_H = 1;
	const int CURSE_ANIM_FRAMES = 20;
	const int CURSE_ANIM_ASPEED = 10;
	
	generic script CurseDeathAnim{
		void run(){
			Game->PlayMIDI(0);
			DSStatus[_CURSEFRAME] = 0;
			int labelFrames[1];
			int animTime = CURSE_ANIM_FRAMES*CURSE_ANIM_ASPEED;
			int fadeSpeed = animTime/4;
			if(animTime<16)
				fadeSpeed = 0;
			int xOff = (CURSE_ANIM_W-1)*-8;
			int yOff = (CURSE_ANIM_H-1)*-8;
			for(int i=0; i<animTime; ++i){
				if(fadeSpeed){
					if(i>fadeSpeed)
						Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 128);
					if(i>fadeSpeed/3*2)
						Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 64);
					if(i>fadeSpeed/3)
						Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 64);
				}
				else{
					Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 128);
				}
				Screen->DrawTile(6, Link->X+Link->DrawXOffset+xOff, Link->Y+Link->DrawYOffset+yOff, CURSE_ANIM_TILE+Floor(i/CURSE_ANIM_ASPEED), CURSE_ANIM_W, CURSE_ANIM_H, 6, -1, -1, 0, 0, 0, 0, true, 128);
				if(fadeSpeed){
					if(i>animTime-fadeSpeed/3)
						Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 128);
					if(i>animTime-fadeSpeed/3*2)
						Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 64);
					if(i>animTime-fadeSpeed)
						Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 64);
				}
				Waitframe();
			}
			if(STATUSWARNINGS_ON_LINK<2){
				for(int i=0; i<80; ++i){
					Screen->Rectangle(6, 0, -56, 255, 175, C_STATUSBAR_TEXTSHADOW, 1, 0, 0, 0, true, 128);
					DrawEffectLabel(CURSE, "CURSED", labelFrames, 64);
					Waitframe();
				}
			}
			UpdateDeathPenalty();
			Game->Continue();
		}
	}
	
	//NPC script to be put on enemies to apply status
	npc script EnemyStatusContact{
		void run(int statusType, int amount, int duration){
			if(duration==0)
				duration = StatusDuration(statusType);
			while(true){
				untyped hitby = Link->HitBy[0]; //HIT_BY_NPC
				if(hitby>0){
					npc hitNPC = Screen->LoadNPC(hitby);
					if(hitNPC->isValid()){
						if(hitNPC==this){
							FillStatus(statusType, amount, duration);
						}
					}
				}
				Waitframe();
			}
		}
	}
	
	//Weapon script to be put on enemies to apply status
	eweapon script EWeaponStatusContact{
		void run(int statusType, int amount, int duration){
			if(duration==0)
				duration = StatusDuration(statusType);
			while(true){
				untyped hitby = Link->HitBy[1]; //HIT_BY_EWEAPON
				if(hitby>0){
					eweapon hitEW = Screen->LoadEWeapon(hitby);
					if(hitEW->isValid()){
						if(hitEW==this){
							FillStatus(statusType, amount, duration);
						}
					}
				}
				Waitframe();
			}
		}
	}


	const int SFX_CURSE_CURE = 25;
	
	//Simple item script to remove curse when used
	itemdata script CurseCure{
		void run(){
			if(GetData(CURSE, TIME)!=0){
				Game->PlaySound(25);
				SetData(CURSE, TIME, 0);
				Link->Item[this->ID] = false;
			}
		}
	}
	
	//This item makes it so swamp combos don't slow you down
	const int I_RUSTEDIRONRING = 151;
	
	//Poison swamps that inflict status. Miyazaki would be proud
	combodata script PoisonSwamp{
		void run(){
			int statusType = this->Attribytes[0];
			int amount = this->Attribytes[1];
			int freq = this->Attribytes[2];
			int onlyWalk = this->Attribytes[3];
			int walkSFX = this->Attribytes[4];
			int duration = this->Attrishorts[0];
			int stepMod = this->Attributes[0];
			int walkCMB = this->Attributes[1];
			if(duration==0)
				duration = StatusDuration(statusType);
			while(true){
				int pos = ComboAt(Link->X+8, Link->Y+12);
				if(pos==this->Pos){
					if(walkCMB){
						Screen->FastCombo(4, Link->X+Link->DrawXOffset, Link->Y+Link->DrawYOffset+2, walkCMB, Screen->ComboC[this->Pos], 128);
					}
					if(!(I_RUSTEDIRONRING&&Link->Item[I_RUSTEDIRONRING]))
						LinkMovement_AddLinkSpeedBoost(stepMod);
					if(onlyWalk==0||Link->Action==LA_WALKING)
						++DSStatus[_SWAMPCOUNTER];
					if(DSStatus[_SWAMPCOUNTER]>=freq){
						if(statusType>=0)
							FillStatus(statusType, amount, duration);
						if(walkSFX&&Link->Action==LA_WALKING)
							Game->PlaySound(walkSFX);
						DSStatus[_SWAMPCOUNTER] = 0;
					}
				}
				Waitframe();
			}
		}
	}
}
// dark souls status end


//Bombsshakescreen
const int BombsScreenShakeFrames = 10; //how many frames a bomb shakes the screen
const int BombsScreenShakeSFrames = 30; //how many frames a superbomb shakes the screen
const int BombsScreenShakeWeaponMisc = 0; //what weapon misc to use for explosion eweapons and lweapons (leave at 0 if no other script uses them)


////////////////////////////////////////////////////////////////
// Overhead
// by grayswandir
////////////////////////////////////////////////////////////////
// Makes certain overhead layers transparent/invisible while link is
// underneath them.
////////////////////////////////////////////////////////////////
// Setup:
// Put Overhead_Update() in your active loop.
// Mess with the Configuration section if you want.
////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////
// Configuration

// Set to 1 to make the tiles disappear completely, instead of being drawn
// transparently.
const int OVERHEAD_INVISIBLE = 0;

// These are the layers that are used. Set to 1 to enable, and 0 to disable.
const int OVERHEAD_USE_L3 = 1;
const int OVERHEAD_USE_L4 = 1;
const int OVERHEAD_USE_L5 = 1;
const int OVERHEAD_USE_L6 = 1;

// Change this to 16 if you have very fast scrolling turned on.
const int OVERHEAD_SCROLL_SPEED = 4;

////////////////////////////////////////////////////////////////
// Code

int Overhead_Data[1416];
const int OVERHEAD_STATE = 0;
const int OVERHEAD_LAST_SCREEN = 1;
const int OVERHEAD_SCROLL_DIR = 2;
const int OVERHEAD_TIMER = 3;
const int OVERHEAD_SCREENS = 4;
const int OVERHEAD_COMBOS = 8;
const int OVERHEAD_CSETS = 712;

const int OVERHEAD_STATE_UNINIT = 0;
const int OVERHEAD_STATE_SCROLLING = 1;
const int OVERHEAD_STATE_WORKING = 2;

void Overhead_Update() {
  int map; int screen; int location; int layer; bool under; int offset;

  // If this is the first time this function has been called, do some setup.
  if (OVERHEAD_STATE_UNINIT == Overhead_Data[OVERHEAD_STATE]) {
    Overhead_Data[OVERHEAD_STATE] = OVERHEAD_STATE_SCROLLING;
    Overhead_Data[OVERHEAD_LAST_SCREEN] = -1;
    for (layer = 3; layer <= 6; ++layer) {
      Overhead_Data[OVERHEAD_SCREENS + layer - 3] = -1;
    }
  }

  // If we've left our current screen, reset the layers we killed.
  screen = (Game->GetCurMap() << 8) + Game->GetCurScreen();
  if (screen != Overhead_Data[OVERHEAD_LAST_SCREEN]) {
    for (layer = 3; layer <= 6; ++layer) {
      // Skip if this layer wasn't recorded.
      if (-1 == Overhead_Data[OVERHEAD_SCREENS + layer - 3]) {continue;}

      // Replace the lost data.
      map = Overhead_Data[OVERHEAD_SCREENS + layer - 3] >> 8;
      screen = Overhead_Data[OVERHEAD_SCREENS + layer - 3] % 256;
      offset = 176 * (layer - 3);
      for (location = 0; location < 176; ++location) {
        Game->SetComboData(map, screen, location, Overhead_Data[OVERHEAD_COMBOS + offset + location]);
      }
    }

    // Remember what screen we're on, so we can tell if we've moved.
    Overhead_Data[OVERHEAD_LAST_SCREEN] = (Game->GetCurMap() << 8) + Game->GetCurScreen();
    Overhead_Data[OVERHEAD_STATE] = OVERHEAD_STATE_SCROLLING;

    // If we've just started scrolling, figure out what direction it's in so
    // we can draw the deleted combos properly. Also reset the timer.
    if (LA_SCROLLING == Link->Action) {
      if (-16 == Link->X) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_RIGHT;}
      if (256 == Link->X) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_LEFT;}
      if (-16 == Link->Y) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_DOWN;}
      if (176 == Link->Y) {Overhead_Data[OVERHEAD_SCROLL_DIR] = DIR_UP;}
      Overhead_Data[OVERHEAD_TIMER] = 0;
    }
  }

  // If we've finished scrolling, copy over the layers and delete them.
  if (LA_SCROLLING != Link->Action && OVERHEAD_STATE_SCROLLING == Overhead_Data[OVERHEAD_STATE]) {
    for (layer = 3; layer <= 6; ++layer) {
      // Skip this layer if we're not configured to use it.
      if (3 == layer && !OVERHEAD_USE_L3) {continue;}
      if (4 == layer && !OVERHEAD_USE_L4) {continue;}
      if (5 == layer && !OVERHEAD_USE_L5) {continue;}
      if (6 == layer && !OVERHEAD_USE_L6) {continue;}

      // If this screen doesn't use this layer, mark as not in use and skip.
      map = Screen->LayerMap(layer);
      screen = Screen->LayerScreen(layer);
      if (-1 == map || -1 == screen) {
        Overhead_Data[OVERHEAD_SCREENS + layer - 3] = -1;
        continue;
      }

      // Save this layer's screen location.
      Overhead_Data[OVERHEAD_SCREENS + layer - 3] = (map << 8) + screen;

      // Grab every combo and cset, and delete the original.
      offset = (layer - 3) * 176;
      for (location = 0; location < 176; ++location) {
        // Grab the data.
        Overhead_Data[OVERHEAD_COMBOS + offset + location] = Game->GetComboData(map, screen, location);
        Overhead_Data[OVERHEAD_CSETS + offset + location] = Game->GetComboCSet(map, screen, location);
        // Delete the original.
        Game->SetComboData(map, screen, location, 0);
      }
    }

    // Update the state so we know we've copied the data.
    Overhead_Data[OVERHEAD_STATE] = OVERHEAD_STATE_WORKING;
  }

  // See if link is standing under a combo in one of the specified layers.
  under = false;
  location = ComboAt(Link->X + 8, Link->Y + 8);
  for (layer = 3; layer <= 6; ++layer) {
    // Skip this layer if it's not in use.
    if (-1 == Overhead_Data[OVERHEAD_SCREENS + layer - 3]) {continue;}
    // Check for there being a non-0 combo at the specified position.
    if (Overhead_Data[OVERHEAD_COMBOS + (layer - 3) * 176 + location]) {
      under = true;
      break;
    }
  }

  // Offsets for scrolling.
  int x = 0;
  int y = 0;
  if (OVERHEAD_STATE_SCROLLING == Overhead_Data[OVERHEAD_STATE]) {
    if (DIR_LEFT == Overhead_Data[OVERHEAD_SCROLL_DIR]) {x = Overhead_Data[OVERHEAD_TIMER];}
    if (DIR_RIGHT == Overhead_Data[OVERHEAD_SCROLL_DIR]) {x = -Overhead_Data[OVERHEAD_TIMER];}
    if (DIR_UP == Overhead_Data[OVERHEAD_SCROLL_DIR]) {y = Overhead_Data[OVERHEAD_TIMER];}
    if (DIR_DOWN == Overhead_Data[OVERHEAD_SCROLL_DIR]) {y = -Overhead_Data[OVERHEAD_TIMER];}
    Overhead_Data[OVERHEAD_TIMER] += OVERHEAD_SCROLL_SPEED;
  }

  // Don't draw if we're under and have it set to be invisible then.
  if (under && OVERHEAD_INVISIBLE) {return;}

  // Draw the overhead layers.
  int opaque = Cond(under, OP_TRANS, OP_OPAQUE);
  for (layer = 3; layer <= 6; ++layer) {
    // Make sure the layer exists.
    if (-1 == Overhead_Data[OVERHEAD_SCREENS + layer - 3]) {continue;}

    // Draw the layer.
    offset = (layer - 3) * 176;
    for (location = 0; location < 176; ++location) {
      int combo = Overhead_Data[OVERHEAD_COMBOS + offset + location];
      if (combo) {
        Screen->FastCombo(layer, ComboX(location) + x, ComboY(location) + y,
                          combo, Overhead_Data[OVERHEAD_CSETS + offset + location],
                          opaque);
      }
    }
  }
}

//Randomized hurt sfx

void LinkHurtSounds_Update(int hurtSFX){
	if(hurtSFX[0]==0){ //Link isn't in hurt frames
		if(Link->Action==LA_GOTHURTLAND||Link->Action==LA_GOTHURTWATER){
			int size = SizeOfArray(hurtSFX)-1;
			Game->PlaySound(hurtSFX[Rand(size)+1]); //Play a random sound from the array
			hurtSFX[0] = 1; //Mark Link as in hurt frames
		}
	}
	else{ //Link is in hurt frames
		if(Link->Action!=LA_GOTHURTLAND&&Link->Action!=LA_GOTHURTWATER){
			hurtSFX[0] = 0; //Mark Link as not in hurt frames
		}
	}
}

//SFX for Link getting hurt. You can add more of these and add them to the hurtSFX[] array for more options
const int SFX_LINKHURT1 = 113;
const int SFX_LINKHURT2 = 114;
const int SFX_LINKHURT3 = 115;
const int SFX_LINKHURT4=  116;
const int SFX_LINKHURT5=  117;

//randomized hurt sf end

//global script
global script Active{
	void run(){
		InitConfusion();
		DarkSoulsStatus::Init();
		DeathPenalty[_DP_LOADEDSAVE] = 1;
		SpeedSpellInit();
		LinkMovement_Init();
		TintZH::tintOnContinue();
		EstusFlask_Init();
		TintZH::tintInit(); //Required by Tint.zh
        DayNight::initializeNightTint();
		{
		int frame = 0;
		int min = 0;
		while(true)
		Overhead_Update();
			{
			if(++frame >= 3600)
				{
				frame = 0;
				if(++min >= DayNight::DAY_LENGTH)
					{
					DayNight::toggleNight();
					min = 0;
					}
				}
			DayNight::handleTint();
			TintZH::runTints();
			//The first number in this array should be 0. The rest are the SFX options.
		int hurtSFX[] = {0, SFX_LINKHURT1, SFX_LINKHURT2, SFX_LINKHURT3, SFX_LINKHURT4, SFX_LINKHURT5};
		while(true){
			LinkHurtSounds_Update(hurtSFX);
			Waitdraw();
			Waitframe();
			}
		}
            DayNight::handleTint();
            TintZH::runTints();	
			while(true){
			shutterControl();
			updatePrev();
			BombsScreenShake(); //put this line into your global loop (to combine this script with your global script)
			DarkSoulsStatus::Update();
			LinkMovement_Update1();
			Confuse();
			EstusFlask_Update();
			Waitdraw();
			UpdateConfusion();
			LinkMovement_Update2();
			UpdateGhostZH1();
			UpdateSpeedSpellStatus();
			LinkMovement_Update1();
			UpdateConfusion();
            LinkMovement_Update2();
			UpdateGhostZH2();
            LinkMovement_Update2();
			Waitframe();
			}
		}
	}


// bombshakesscreen script

void BombsScreenShake() {
    for (int i = 1; i <= Screen->NumLWeapons(); i++) { //lweapons
        lweapon lweap = Screen->LoadLWeapon(i);
        if ( lweap->ID == LW_BOMBBLAST && lweap->Misc[BombsScreenShakeWeaponMisc] == 0 ) { //if there is a normal explosion on screen and the misc value is 0
            Screen->Quake = BombsScreenShakeFrames; //shake the screen
            lweap->Misc[BombsScreenShakeWeaponMisc] = 1; //change the misc value to 1
        }
        else if ( lweap->ID == LW_SBOMBBLAST && lweap->Misc[BombsScreenShakeWeaponMisc] == 0 ) { //if there is a super explosion on screen and the misc value is 0
            Screen->Quake = BombsScreenShakeSFrames; //shake the screen
            lweap->Misc[BombsScreenShakeWeaponMisc] = 1; //change the misc value to 1
        }
    }
    for (int i = 1; i <= Screen->NumEWeapons(); i++) { //eweapons
        eweapon eweap = Screen->LoadEWeapon(i);
        if ( eweap->ID == EW_BOMBBLAST && eweap->Misc[BombsScreenShakeWeaponMisc] == 0 ) { //if there is a normal explosion on screen and the misc value is 0
            Screen->Quake = BombsScreenShakeFrames; //shake the screen
            eweap->Misc[BombsScreenShakeWeaponMisc] = 1; //change the misc value to 1
        }
        else if ( eweap->ID == EW_BOMBBLAST && eweap->Misc[BombsScreenShakeWeaponMisc] == 0 ) { //if there is a super explosion on screen and the misc value is 0
            Screen->Quake = BombsScreenShakeSFrames; //shake the screen
            eweap->Misc[BombsScreenShakeWeaponMisc] = 1; //change the misc value to 1
        }
    }
}

// Bombshakescreen script end

//speed modifier script start
void SpeedSpellInit(){
	Speed_Spell_Status=0;
}

void UpdateSpeedSpellStatus(){
	if (Speed_Spell_Status>0){
		Speed_Spell_Counter++;
		if ((Speed_Spell_Counter%Speed_Spell_SFX_Rate)==0)Game->PlaySound(Speed_Spell_SFX);
		if ((Speed_Spell_Counter%Speed_Spell_Drain_Rate)==0 && Link->Action==LA_WALKING){
			if (Game->Counter[Speed_Spell_Drain_Counter]>=Speed_Spell_Drain_Cost)Game->Counter[Speed_Spell_Drain_Counter]-=Speed_Spell_Drain_Cost;
			else Speed_Spell_Status=0;
			if (Game->Counter[Speed_Spell_Drain_Counter2]>=Speed_Spell_Drain_Cost2 && Speed_Spell_Status>0)Game->Counter[Speed_Spell_Drain_Counter2]-=Speed_Spell_Drain_Cost2;
			else Speed_Spell_Status=0;
		}
		if (Speed_Spell_Counter>=15600)Speed_Spell_Counter=0;
		LinkMovement_AddLinkSpeedBoost(Speed_Spell_Modifier/100);
	}
	if (GetEquipmentB()!=Speed_Spell_Status && GetEquipmentA()!=Speed_Spell_Status) Speed_Spell_Status=0;
}

item script SpeedSpellAction{
	void run(){
		int itm = GetHighestLevelItemOwned(this->Family);
		if (Speed_Spell_Status>0)Speed_Spell_Status=0;
		else if (Game->Counter[Speed_Spell_Drain_Counter]>=Speed_Spell_Drain_Cost && 
		Game->Counter[Speed_Spell_Drain_Counter2]>=Speed_Spell_Drain_Cost2)Speed_Spell_Status=itm;
	}
}

item script SpeedSpellPickup{
	void run(int drainrate, int draincost, int soundrate, int counterused, int counter2used, int counter2cost){
		int itm = GetHighestLevelItemOwned(this->Family);
		if (itm>=0){
			itemdata it = Game->LoadItemData(itm);
			int lvl = it->Level;
			if (this->Level<=lvl) Quit();
		}
		Speed_Spell_Drain_Rate = drainrate;
		Speed_Spell_Drain_Cost = draincost;
		Speed_Spell_SFX = this->UseSound;
		Speed_Spell_SFX_Rate = soundrate;
		Speed_Spell_Modifier = this->Power;
		Speed_Spell_Drain_Counter = counterused;
		Speed_Spell_Drain_Cost2 = counter2cost;
		Speed_Spell_Drain_Counter2 = counter2used;
	}
}

//Sandstorm. Reduces Link`s movement speed, if Link does not have specific item. 
//Requires LinkMovement.zh
//D0 - item ID
//D1 - speed penalty
ffc script Sandstorm{
	void run (int itemid, int slow){
		while(true){
			if (! Link->Item[itemid])LinkMovement_AddLinkSpeedBoost(-slow);
			Waitframe();
		}
	}
}

//Same as Sandstorm, but restricted to specific combo.
//Requires LinkMovement.zh
//D0 - item ID
//D1 - speed penalty, negative to speed boost
//D2 - ID of specific combo in table
ffc script SpeedModifierCombo{
	void run (int itemid, int slow, int modcmb){
		int cmb=0;
		while(true){
			cmb = ComboAt(CenterLinkX(), CenterLinkY());
			if ((!Link->Item[itemid]) && (Screen->ComboD[cmb]==modcmb))LinkMovement_AddLinkSpeedBoost(-slow);
			Waitframe();
		}
	}
}

//speedmodifer script end

//estus flask campfire 
ffc script EstusFlask_Bonfire{
	void run(){
		int i;
		while(true){
			bool canUse;
			if(Link->X>=this->X-8&&Link->X<=this->X+8&&Link->Y>=this->Y-16&&Link->Y<=this->Y&&Link->Dir==DIR_DOWN)
				canUse = true;
			if(Link->X>=this->X-8&&Link->X<=this->X+8&&Link->Y>=this->Y&&Link->Y<=this->Y+8&&Link->Dir==DIR_UP)
				canUse = true;
			if(Link->X>=this->X-16&&Link->X<=this->X&&Link->Y>=this->Y-12&&Link->Y<=this->Y+4&&Link->Dir==DIR_RIGHT)
				canUse = true;
			if(Link->X>=this->X&&Link->X<=this->X+16&&Link->Y>=this->Y-12&&Link->Y<=this->Y+4&&Link->Dir==DIR_LEFT)
				canUse = true;
			if(canUse){
				DrawAPrompt();
				if(Link->PressA){
					Link->PressA = false;
					Link->InputA = false;
					NoAction();
					Game->PlaySound(SFX_ESTUSFLASK_REFILL);
					
					if(ESTUSFLASK_BONFIRE_HEALS){
						int healAmount = Link->MaxHP-Link->HP;
						EstusFlask[_EF_HEALHP] = healAmount;
						EstusFlask[_EF_HEALHPPERFRAME] = healAmount/30;
						EstusFlask[_EF_DRINKTIMER] = 0;
					}
					
					if(ESTUSFLASK_BONFIRE_RESETENEMIES){
						EstusFlask[_EF_LASTMAP] = -1;
						for(i=0; i<=255; i++){
							EstusFlask[_EF_RESETMAP+i] = 1;
						}
					}
					
					if(ESTUSFLASK_BONFIRE_SETS_CONTINUE||ESTUSFLASK_BONFIRE_OVERRIDES_CONTINUE){
						EstusFlask[_EF_CONTINUEDMAP] = Game->GetCurDMap();
						EstusFlask[_EF_CONTINUESCREEN]= Game->GetCurDMapScreen();
						
						Game->LastEntranceDMap = Game->GetCurDMap();
						Game->LastEntranceScreen = Game->GetCurDMapScreen();
						Game->ContinueDMap = Game->GetCurDMap();
						Game->ContinueScreen = Game->GetCurDMapScreen();
					}
					
					if(Game->Counter[CR_ESTUSFLASK_COUNT]<EstusFlask[_EF_MAXREFILL]){
						for(i=0; Game->Counter[CR_ESTUSFLASK_COUNT]<EstusFlask[_EF_MAXREFILL]; i++){
							Game->Counter[CR_ESTUSFLASK_COUNT] = Min(Game->Counter[CR_ESTUSFLASK_COUNT]+1, EstusFlask[_EF_MAXREFILL]);
							WaitNoAction(4);
						}
						WaitNoAction(20);
					}
					else{
						WaitNoAction(20);
					}
					while(EstusFlask[_EF_HEALHP]>0){
						WaitNoAction();
					}
				}
			}
			Waitframe();
		}
	}
}
//estusflaskcampfire end

 

 



#2 Emily

Emily

    Scripter / Dev

  • ZC Developers
  • Pronouns:She / Her

Posted 01 February 2026 - 09:01 PM

try changing `item script` to `itemdata script`?


  • Max Headroom likes this

#3 Max Headroom

Max Headroom

    I'll buy that for a Rupee!

  • Members
  • Real Name:Rion "Axy"
  • Pronouns:He / Him
  • Location:In a low-Def Tv in Chicago

Posted 01 February 2026 - 10:14 PM

update, i tried that, it didn't work, its weird it worked yesterday fine. I'm gonna try to rebuild the list.



#4 connor.clark

connor.clark

    Junior

  • ZC Developers

Posted 17 June 2026 - 03:11 PM

Your "global script Active{" is missing a close "}", which breaks the parser.

 

EDIT:

It's actually more severe than that:
 

DayNight::initializeNightTint();
{ // ??? stray {
int frame = 0;
int min = 0;
while(true)
Overhead_Update(); // ??? can't call a function between a while loop and its { ...
{

The entire active global script should be deleted and done again from scratch.




6 user(s) are reading this topic

0 members, 6 guests, 0 anonymous users