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

