// TMW2 Script
// Author:
// Jesusalva
// Description:
// Item Option System
// Notes:
// Awarded for crafters and their own base skill tree system
// Player knowledge structure
// CRAFTSYS[ SKILL_SCOPE ] = SKILL_LV
// Player craft skills selection:
// CRAFTSYS_CURRENT
// Generate() takes the scope and finds out the skills on the group
// It'll fill the following variables:
// @csys_attr → Available attributes
// @csys_penalty → Penalty attribute array
//
// use getarraysize(@csys_attr) to know how many are there.
// Players can active the bonus groups they want to use (in future, TODO)
// Max Level for base: 10
// Max Level for first tier: 5
// Max Level for second tier:
// Max Level for third tier:
// Max Level for ultimate tier: 1
// csys_Generate( cr_id{, preserve} )
// Return average level
function script csys_Generate {
.@gid=getarg(0);
if (!getarg(1, false)) {
deletearray(@csys_attr);
deletearray(@csys_penalty);
}
//.@lvl=getd("CRAFTSYS["+.@gid+"]");
.@avg=0;
.@stk=0;
if (.@gid & CRGROUP_BASE) {
.@lvl=CRAFTSYS[CRGROUP_BASE];
if (.@lvl >= 1)
array_push(@csys_attr, VAR_STRAMOUNT);
if (.@lvl >= 2)
array_push(@csys_attr, VAR_AGIAMOUNT);
if (.@lvl >= 3)
array_push(@csys_attr, VAR_VITAMOUNT);
if (.@lvl >= 4)
array_push(@csys_attr, VAR_INTAMOUNT);
if (.@lvl >= 5)
array_push(@csys_attr, VAR_DEXAMOUNT);
if (.@lvl >= 6)
array_push(@csys_attr, VAR_LUKAMOUNT);
if (.@lvl >= 8)
array_push(@csys_attr, VAR_MAXHPAMOUNT);
if (.@lvl >= 10)
array_push(@csys_attr, VAR_MAXSPAMOUNT);
// Update averages
.@avg+=.@lvl;
.@stk+=1;
}
// First tier
if (.@gid & CRGROUP_ATK) {
.@lvl=CRAFTSYS[CRGROUP_ATK];
if (.@lvl >= 1) {
array_push(@csys_attr, VAR_ATTPOWER);
array_push(@csys_attr, VAR_ATTMPOWER);
}
if (.@lvl >= 5) {
array_push(@csys_attr, VAR_MAGICATKPERCENT);
array_push(@csys_attr, VAR_ATKPERCENT);
}
array_push(@csys_penalty, VAR_ITEMDEFPOWER);
array_push(@csys_penalty, VAR_MDEFPOWER);
// Update averages
.@avg+=.@lvl;
.@stk+=1;
}
if (.@gid & CRGROUP_DEF) {
.@lvl=CRAFTSYS[CRGROUP_DEF];
if (.@lvl >= 1) {
array_push(@csys_attr, VAR_ITEMDEFPOWER);
array_push(@csys_attr, VAR_MDEFPOWER);
}
if (.@lvl >= 5) {
array_push(@csys_attr, DAMAGE_CRI_USER);
array_push(@csys_attr, RANGE_ATTACK_DAMAGE_USER);
}
array_push(@csys_penalty, VAR_ATTPOWER);
array_push(@csys_penalty, VAR_ATTMPOWER);
// Update averages
.@avg+=.@lvl;
.@stk+=1;
}
if (.@gid & CRGROUP_ACC) {
.@lvl=CRAFTSYS[CRGROUP_ACC];
if (.@lvl >= 1) {
array_push(@csys_attr, VAR_HITSUCCESSVALUE);
}
if (.@lvl >= 5) {
array_push(@csys_attr, VAR_CRITICALSUCCESSVALUE);
}
array_push(@csys_penalty, VAR_ATTPOWER);
array_push(@csys_penalty, VAR_ATTMPOWER);
// Update averages
.@avg+=.@lvl;
.@stk+=1;
}
if (.@gid & CRGROUP_EVD) {
.@lvl=CRAFTSYS[CRGROUP_EVD];
if (.@lvl >= 1) {
array_push(@csys_attr, VAR_AVOIDSUCCESSVALUE);
}
if (.@lvl >= 5) {
array_push(@csys_attr, VAR_PLUSAVOIDSUCCESSVALUE);
}
array_push(@csys_penalty, VAR_ATTPOWER);
array_push(@csys_penalty, VAR_ATTMPOWER);
// Update averages
.@avg+=.@lvl;
.@stk+=1;
}
// Second tier
if (.@gid & CRGROUP_REGEN) {
.@lvl=CRAFTSYS[CRGROUP_REGEN];
if (.@lvl >= 1) {
array_push(@csys_attr, VAR_HPACCELERATION);
}
if (.@lvl >= 5) {
array_push(@csys_attr, VAR_SPACCELERATION);
}
array_push(@csys_penalty, VAR_ATTPOWER);
array_push(@csys_penalty, VAR_ATTMPOWER);
// Update averages
.@avg+=.@lvl;
.@stk+=1;
}
// Clear the dummies
array_remove(@csys_attr, DeathPenalty);
array_remove(@csys_penalty, DeathPenalty);
// Return the average level
if (!.@stk)
return 0;
return (.@avg/.@stk);
}
// Confirms if player really wants to tweak a craft.
// Do not cast after new crafts. Returns false to stop script.
// csys_Confirm( invindex )
function script csys_Confirm {
.@id=getarg(0);
// Sanitize input
if (.@id < 0)
return false;
// *getequipisenableopt(<equipment slot>) → cannot use here
// Not an equipment
if (!getiteminfo(.@id, ITEMINFO_LOC))
return false;
mesc l("Really try to tweak this item? All current options will be deleted.");
next;
if (askyesno() == ASK_NO)
return false;
return true;
}
// Check if you'll have success in applying options or not
// Returns true if you was successful, and also cleans previous options
// If you only want cleaning, just disregard the output.
// csys_Check( invindex )
function script csys_Check {
.@id=getarg(0);
// Clear all five options
setitemoptionbyindex(.@id, 0, 0, 0);
setitemoptionbyindex(.@id, 1, 0, 0);
setitemoptionbyindex(.@id, 2, 0, 0);
setitemoptionbyindex(.@id, 3, 0, 0);
setitemoptionbyindex(.@id, 4, 0, 0);
// Base Success Rate is: 40% + 5% each craft skill level
.@base=4000+(getskilllv(TMW2_CRAFT)*500);
if (rand(10000) < .@base)
return true;
return false;
}
// csys_Multiplier( cr_id )
// Returns a multiplier for bonus (it can be zero)
function script csys_Multiplier {
.@sk=getarg(0);
switch (.@sk) {
case IOPT_SPLASHDAMAGE:
return 0;
case IOPT_SCRESIST_POISON:
case IOPT_SCRESIST_SILENCE:
case IOPT_SCRESIST_CURSE:
case IOPT_SCRESIST_BLIND:
return 2;
case VAR_MAXHPAMOUNT:
case VAR_MAXSPAMOUNT:
case VAR_ITEMDEFPOWER:
case VAR_MDEFPOWER:
return 3;
default:
return 1;
}
return 0;
}
// Attribute item options
// Does NOT performs success chance check, and can be used by NPC
// csys_Apply( invindex{, lvl, scope} )
function script csys_Apply {
.@id=getarg(0);
.@lv=getarg(1, getskilllv(TMW2_CRAFT));
.@sc=getarg(1, CRAFTSYS_CURRENT);
.@lv2=csys_Generate(.@sc);
// @csys_attr → Available attributes
// @csys_penalty → Penalty attribute array
// Shuffle the arrays
array_shuffle(@csys_attr);
array_shuffle(@csys_penalty);
// How many bonuses we'll have? Never more than 3 bonus and 2 onus.
.@max_attr=getarraysize(@csys_attr);
.@max_pena=getarraysize(@csys_penalty);
//debugmes "We have %d attributes and %d penalties", .@max_attr, .@max_pena;
.@slot=0;
while (.@slot < min(3, .@max_attr)) {
// You have 100% for first bonus/onus, -30% each, depending on skill lv
.@base=3000-(.@lv*75);
if (rand(10000) > 10000-(.@base*.@slot))
break;
// Apply a bonus using array_pop (it was shuffled so we're fine)
// A pity 1 str and 1 hp is so different.
.@vartp=array_pop(@csys_attr);
.@bonus=rand(1, .@lv+.@lv2)*csys_Multiplier(.@vartp)+1;
setitemoptionbyindex(.@id, .@slot, .@vartp, .@bonus);
//debugmes "Bonus applied: %d at %d (slot: %d)", .@vartp, .@bonus, .@slot;
.@slot+=1;
}
// We need a new temp var
.@slt=0;
while (.@slt < min(2, .@max_pena)) {
// You have 100% for first bonus/onus, -30% each, depending on skill lv
.@base=3000+(.@lv*75);
if (rand(10000) > 10000-(.@base*.@slt))
break;
// Apply a bonus using array_pop (it was shuffled so we're fine)
// A pity 1 str and 1 hp is so different.
.@vartp=array_pop(@csys_penalty);
.@bonus=rand(1, .@lv+.@lv2)*csys_Multiplier(.@vartp)+1;
setitemoptionbyindex(.@id, .@slot, .@vartp, .@bonus);
.@slot+=1;
.@slt+=1;
}
// The options have been attributed
return;
}