Aller au contenu

Photo

Issue with a script


  • Veuillez vous connecter pour répondre
10 réponses à ce sujet

#1
AaronH

AaronH
  • Members
  • 115 messages

A developer in our team worked on some of the skills, one being Smithing. He's no longer in the team, and we're having an issue with the skill.


What's happening is, when you try and smith, you use an anvil to create a sword or armour once or more, then you completely stop.

 

The script lets you smith 1, 5 or All (All being every bar in your invent, and stopping once you run out).

But when you smith 1-10 items, you completely stop, even if you have metal bars remaining to be smelted, so when you try and click the anvil again, your character just won't do anything and just stand there, even after re-selecting what you want to smelt.

After you keep trying to use the anvil, you will randomly be able to smith again, the then the bug loops, and will only let you smith 1-10 more items before locking you out completely.

 

 

Could someone please look over the script and see if you can find anything?

We have other scripts like this and they work completely the same and perfectly fine. For example, cooking.

 

 

 

 

// tb_smithing
/*-
    This script checks to see if the PC has an item in their inventory
        _bar = tag of the smithing material
        _item = tag of item we're making
        _barsused = quantity of material used per item
        _quantity = quantity of items we're smithing
        _nXP = xp per smith
*/

#include "tb_loops"
#include "tb_skillsandxp"
#include "nw_i0_plot"


const string ANIM_SMITH = "FORGE01";
const string SMITH_SOUND = "as_cv_smithhamr1";

object oPC;
string item;
string bar;
int xp;
int barspersmith;
int quantity;
location loc;
float nSmithTime = 6.0;

void StartSmithing();
void EndSmithing(); //you either moved on or finished all the items
void WaitForSmith(float time, float curtime = 1000.0);
void Smith();
void GiveSmithed();
void DestroyItems(object oTarget, string sItem, int nNumItems);

void main(string _bartag, string _itemtag, int _barsused, int _quantity, int _nXp)
{
    oPC = GetPCSpeaker();
    if (GetLocalInt(oPC, "issmithing") == 1) //a smithing loop is already firing
    { //closing all smithing scripts and starting this one
        return;
    }
    SetLocalString(oPC, "activity", "smithing"); //activity switch aborts loops in all other activities
    item = _itemtag;
    bar = _bartag;
    xp = _nXp;
    barspersmith = _barsused;
    quantity = _quantity;
    loc = GetLocation(oPC);
    StartSmithing();
}

void ReallyPlayCustomAnimation(object oObject, string sAnimationName, int nsmithing, float fSpeed = 1.0f)
{
    PlayAnimation(0, 1.0f, 0.01f);
     PlayCustomAnimation(oObject, sAnimationName, nsmithing, fSpeed);
}

void StartSmithing()
{
    string hammertag = GetTag(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC));
    if (hammertag != "hammer")
    {
        object oHammer = GetItemPossessedBy(oPC, "hammer");
        AssignCommand(oPC, ActionEquipItem(oHammer, INVENTORY_SLOT_RIGHTHAND));
        if (oHammer == OBJECT_INVALID)
        {
            EndSmithing();
            SendMessageToPC(oPC, "<color=white>" + "You don't seem to have a hammer ready.");
            return;
        }
        //test carrying pickaxe in left hand and another item in right
        else if (GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC) != oHammer)
        {
            AssignCommand(oPC, ActionUnequipItem(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC)));
            AssignCommand(oPC, ActionEquipItem(oHammer, INVENTORY_SLOT_RIGHTHAND));
        }
    }
    DelayCommand(0.01, WaitForSmith(nSmithTime, nSmithTime));
    AssignCommand(oPC, PlaySound(SMITH_SOUND));
}

void WaitForSmith(float time, float curtime)
{
    float step = 0.5f;
    float curdist = GetDistanceBetweenLocations(GetLocation(oPC), loc);
    //abort if we're done or don't have enough bars
    
    if (curdist <= 0.01)
    {
        SetLocalInt(oPC, "issmithing", 1);
        if (quantity <= 0)
        {
            EndSmithing();
            return;
        }
        if (GetNumItems(oPC, bar) < barspersmith)
        {
            EndSmithing();
            SendMessageToPC(oPC, "<color=white>" + "You've run short on materials to smith with.");
            return;
        }
        else if (curtime <= 0.0f)
        {
            quantity--;
            Smith();
        }
        else if (GetLocalString(oPC, "activity") == "smithing")
        {
            DelayCommand(0.2f, AssignCommand(oPC, ReallyPlayCustomAnimation(oPC, ANIM_SMITH, 0)));
            DelayCommand(step, AssignCommand(oPC, WaitForSmith(time, curtime-step)));
            EndSmithing();
        }
    }
    else
    {
        //SendMessageToPC(oPC, "<color=white>" + "Current Activity: " + GetLocalString(oPC, "activity"));
        EndSmithing();
    }
}

void Smith()
{
    SendMessageToPC(oPC, "<color=white>" + "You smith successfully.");
    DestroyItems(oPC, bar, barspersmith);
    DelayCommand(0.1f, AssignCommand(oPC, GiveSmithed()));
    GiveXP(oPC, "smithing", xp);
    EndSmithing();
    StartSmithing();
}

void GiveSmithed()
{
    CreateItemOnObject(item, oPC, 1);
}

void EndSmithing()
{
    CloseLoops(oPC);
}

void DestroyItems(object oTarget,string sItem,int nNumItems)
{
    int nCount = 0;
    object oItem = GetFirstItemInInventory(oTarget);
    
    while (GetIsObjectValid(oItem) == TRUE && nCount < nNumItems)
    {
        if (GetTag(oItem) == sItem)
        {
            int nRemainingToDestroy = nNumItems - nCount;
            int nStackSize = GetItemStackSize(oItem);
            
            if(nStackSize <= nRemainingToDestroy)
            {
                DestroyObject(oItem,0.1f);
                nCount += nStackSize;
            }
            else
            {
                int nNewStackSize = nStackSize - nRemainingToDestroy;
                SetItemStackSize(oItem, nNewStackSize);
                break;
            }
        }
        oItem = GetNextItemInInventory(oTarget);
    }
   return;
}

 



#2
kevL

kevL
  • Members
  • 4 052 messages
I suspect it's in the way that WaitForSmith() interacts with EndSmithing() -> CloseLoops()

examine the Wait functions in other scripts with particular attention to how End gets called in them.


i also notice that the "issmithing" int_var gets turned on but isn't turned off in the script. Same with string_var "activity" though I imagine it's less important (within the context of the script). If "issmithing" is left true it could result in a lockout.

#3
AaronH

AaronH
  • Members
  • 115 messages

I suspect it's in the way that WaitForSmith() interacts with EndSmithing() -> CloseLoops()

examine the Wait functions in other scripts with particular attention to how End gets called in them.


i also notice that the "issmithing" int_var gets turned on but isn't turned off in the script. Same with string_var "activity" though I imagine it's less important (within the context of the script). If "issmithing" is left true it could result in a lockout.

I appreciate the response, but I honestly have no idea what I'm looking at regarding scripts. It's a massive shame because the developer worked on his own and never got anyone involved on what he worked on, so we were left out in the dark.

Would you be able to see what's wrong by comparing it to this script?

It's our cooking script which works the same as the smithing one.


// tb_cooking
/*
    This script checks to see if the PC has an item in their inventory
        rawTag = tag of raw food
        sCookedTemplate = templateResRef of cooked food
        quantity = how many to cook
        foodlevel = min level to cook
        burnFire = level stops burning on fires (-1 for range only)
        burnRange = level stops burning on ranges
        burnLumRange = level stops burning on lumbridge castle range
        burnGuantlet = level stops burning with cooking guantlets
        xp = xp gain
*/

#include "tb_loops"
#include "tb_spawndespawn"
#include "tb_skillsandxp"

const string COOK_SOUND = "al_cv_firepit1";
const string ANIM_COOKFIRE = "fishnet";
const string ANIM_COOKRANGE = "cookrange";
//Tags
const string FIRE_TAG = "bonfire";
const string RANGE_TAG = "oven";
const string LUMMYRANGE_TAG = "lumoven";
const string COOKING_GUANTLETS_TAG = "cookingguantlets";
const string BURNTMEAT_TAG = "burntmeat";

const float BASEBURNCHANCE = 55.0;

object oPC;
int quantity;
string rawItem;
string cookedTemplate;
string anim;
string rangetag;
location loc;
int xp;
int foodlevel;
int stopsburning;
int level;

void WaitForCook(float delay, float curtime);
void StartCooking();
void EndCooking(); //you either moved on or finished all the items
void Cook();
void GiveCooked();
void DestroyItems(object oTarget, string sItem, int nNumItems);
float nCookTime = 3.2f;

void main(string rawTag, string sCookedTemplate, int _quantity, int foodLevel, int nXp, int burnFire = 0, int burnRange = 0, int burnLumRange = 0, int burnGuantlet = 0)
{
    oPC = GetPCSpeaker();
    rangetag = GetTag(OBJECT_SELF);
    //SendMessageToPC(oPC, "<color=white>" + "Triston: Cooking v1");
    if (GetLocalInt(oPC, "iscooking") == 1) //a cooking loop is already firing
    {
        return;
    }
    SetLocalString(oPC, "activity", "cooking"); //activity switch aborts loops in all other activities
    level = GetSkillRank(SKILL_COOKING, oPC);
    if (burnFire == -1)
    {
        SendMessageToPC(oPC, "<color=white>" + "You can't cook that on a fire.");
    }
    stopsburning = burnFire;
    anim = (rangetag == FIRE_TAG) ? ANIM_COOKFIRE : ANIM_COOKRANGE;
    stopsburning = (rangetag == RANGE_TAG) ? burnRange : stopsburning;
    stopsburning = (rangetag == LUMMYRANGE_TAG) ? burnLumRange : stopsburning;
    stopsburning = (GetTag(GetItemInSlot(INVENTORY_SLOT_ARMS, oPC)) == COOKING_GUANTLETS_TAG) ? burnGuantlet : stopsburning;
    rawItem = rawTag;
    cookedTemplate = sCookedTemplate;
    xp = nXp;
    quantity = _quantity;
    loc = GetLocation(oPC);
    foodlevel = foodLevel;
    StartCooking();
}

void ReallyPlayCustomAnimation(object oObject, string sAnimationName, int nLooping, float fSpeed = 1.0f)
{
    PlayAnimation(0, 1.0f, 0.01f);
     PlayCustomAnimation(oObject, sAnimationName, nLooping, fSpeed);
}

void StartCooking()
{
    AssignCommand(oPC, PlaySound(COOK_SOUND, TRUE));
    WaitForCook(nCookTime, nCookTime);
}

void WaitForCook(float time, float curtime)
{
    float step = 0.5f;
    object nearestfire = GetNearestObjectByTag(FIRE_TAG,oPC);
    int isfire = (rangetag == FIRE_TAG) ? GetIsObjectValid(nearestfire) : FALSE;
    //abort if we're done, lose our fire, or run out of items
    if ((rangetag == FIRE_TAG && !isfire) ||
        !GetIsObjectValid(GetItemPossessedBy(oPC,rawItem)))
    {
        EndCooking();
        return;
    }
    else if (curtime <= 0.0f)
    {
        quantity--;
        
        /**** ****/
        float result = BASEBURNCHANCE - ((IntToFloat(level) - IntToFloat(foodlevel)) *
                        (BASEBURNCHANCE / (IntToFloat(stopsburning) - IntToFloat(foodlevel))));
        float random = IntToFloat(Random(100));                
        
        SendMessageToPC(oPC, "<color=white>" + "DEBUG:" + " Random: " + FloatToString(random) +
                                                        " Result: " + FloatToString(result));
        
        if (result <= random)
        {
            SendMessageToPC(oPC, "<color=white>" + "You cook successfully.");
            Cook();
        }
        else //burn
        {
            SendMessageToPC(oPC, "<color=white>" + "You burned your food.");
            CreateItemOnObject(BURNTMEAT_TAG, oPC, 1);
            DestroyItems(oPC, rawItem, 1);
        }
        StartCooking();
    }
    else if (GetDistanceBetweenLocations(GetLocation(oPC), loc) < 0.3f && GetLocalString(oPC, "activity") == "cooking")
    {
        SetLocalInt(oPC, "iscooking", 1);
        if (quantity <= 0)
        {
            EndCooking();
            return;
        }
        DelayCommand(0.2f, AssignCommand(oPC, ReallyPlayCustomAnimation(oPC, anim, 0)));
        DelayCommand(step, AssignCommand(oPC, WaitForCook(time, curtime-step)));
    }
    else
    {
        EndCooking();
        //SendMessageToPC(oPC, "<color=white>" + "Current Activity: " + GetLocalString(oPC, "activity"));
    }
}

void Cook()
{
    DestroyItems(oPC, rawItem, 1);
    DelayCommand(0.1f, AssignCommand(oPC, GiveCooked()));
    GiveXP(oPC, "cooking", xp);
}

void GiveCooked()
{
    CreateItemOnObject(cookedTemplate, oPC, 1);
}

void EndCooking()
{
    CloseLoops(oPC);
}

void DestroyItems(object oTarget,string sItem,int nNumItems)
{
    int nCount = 0;
    object oItem = GetFirstItemInInventory(oTarget);
    
    while (GetIsObjectValid(oItem) == TRUE && nCount < nNumItems)
    {
        if (GetTag(oItem) == sItem)
        {
            int nRemainingToDestroy = nNumItems - nCount;
            int nStackSize = GetItemStackSize(oItem);
            
            if(nStackSize <= nRemainingToDestroy)
            {
                DestroyObject(oItem,0.1f);
                nCount += nStackSize;
            }
            else
            {
                int nNewStackSize = nStackSize - nRemainingToDestroy;
                SetItemStackSize(oItem, nNewStackSize);
                break;
            }
        }
        oItem = GetNextItemInInventory(oTarget);
    }
   return;
}



#4
kevL

kevL
  • Members
  • 4 052 messages
backup. replace these two functions
void WaitForSmith(float time, float curtime)
{
	float step = 0.5f;
	//abort if we're done or don't have enough bars

	if (curtime <= 0.0f)
	{
		quantity--;
		Smith();
		StartSmithing();
	}
	else if (GetDistanceBetweenLocations(GetLocation(oPC), loc) <= 0.01 && GetLocalString(oPC, "activity") == "smithing")
	{
		SetLocalInt(oPC, "issmithing", 1);
		if (quantity <= 0)
		{
			EndSmithing();
			return;
		}
		else if (GetNumItems(oPC, bar) < barspersmith)
		{
			EndSmithing();
			SendMessageToPC(oPC, "<color=white>" + "You've run short on materials to smith with.");
			return;
		}
		DelayCommand(0.2f, AssignCommand(oPC, ReallyPlayCustomAnimation(oPC, ANIM_SMITH, 0)));
		DelayCommand(step, AssignCommand(oPC, WaitForSmith(time, curtime-step)));
	}
	else
	{
		//SendMessageToPC(oPC, "<color=white>" + "Current Activity: " + GetLocalString(oPC, "activity"));
		EndSmithing();
	}
}

void Smith()
{
	SendMessageToPC(oPC, "<color=white>" + "You smith successfully.");
	DestroyItems(oPC, bar, barspersmith);
	DelayCommand(0.1f, AssignCommand(oPC, GiveSmithed()));
	GiveXP(oPC, "smithing", xp);
}
Recompile. I just replicated the behavior from Cooking, removing a couple of seemingly misplaced EndSmithing()s, and tightened the scope of setting "issmithing".
  • olnorton aime ceci

#5
AaronH

AaronH
  • Members
  • 115 messages

Will test it now



#6
AaronH

AaronH
  • Members
  • 115 messages

The first attempt, it stopped after 1 (after choosing to smith all bars in my inventory), but then i clicked it again and it worked for the full amount.

I'll have to test more, but I really appreciate it, you've done me a massive favour :)



#7
kevL

kevL
  • Members
  • 4 052 messages
Did it sort itself out? I'd need to see 'tb_loops' to sort any further

( specifically where & how "issmithing" turns FALSE -- might be in 'tb_skillsandxp' also )

#8
AaronH

AaronH
  • Members
  • 115 messages

Did it sort itself out? I'd need to see 'tb_loops' to sort any further

( specifically where & how "issmithing" turns FALSE -- might be in 'tb_skillsandxp' also )

 

The first time you go to smith, you smith 1 item and then stop. When you go again, it's fine and smiths forever (well until you run out of bars).

If you leave an area or log off, and log back in (or rejoin the area), and go to smith again, you'll stop after the first item, but then continue once you go to use the anvil again and choosing what to smith.



#9
kevL

kevL
  • Members
  • 4 052 messages
are you saying that if

PC clicks to smith all once
- 1 item is crafted

PC clicks 2nd time to smith all
- all remaining bars are crafted

PC STAYS IN THE AREA AND YOU CONSOLE IN MORE BARS FOR PC TO SMITH
and PC clicks 3rd time to smith all
- all bars are crafted


But if PC leaves the area and returns (or reloads)
- the entire procedure repeats.


that indicates a mix-up in the area's OnEnter script. I'd need access to a bunch of other stuff and a test-case, but that's up to you.

#10
AaronH

AaronH
  • Members
  • 115 messages

The exact step is;

(Starts off with 30 bars in inventory)

1) click anvil
2) Smith daggers

3) Quanity = 'All'
4) Player smiths 1 dagger then stops
5) click anvil again

6) Smith daggers

7) Quantity = 'All'
8) Player smiths all bars available.


I went to a shop to sell the equipment (I did spawn in the bars), but honestly, I'm grateful enough and it's fine as it is :P

I'll just say that it's an anti-afking mechanic xD But it's not a game breaking bug, not even an annoying bug, unlike what it was before.



#11
kevL

kevL
  • Members
  • 4 052 messages
ok
  • GCoyote et AaronH aiment ceci