summaryrefslogtreecommitdiff
path: root/npc/functions
diff options
context:
space:
mode:
Diffstat (limited to 'npc/functions')
-rw-r--r--npc/functions/array.txt22
-rw-r--r--npc/functions/clientversion.txt7
-rw-r--r--npc/functions/lockpicks.txt8
-rw-r--r--npc/functions/main.txt7
-rw-r--r--npc/functions/politics.txt143
-rw-r--r--npc/functions/refine.txt22
-rw-r--r--npc/functions/resetstatus.txt46
-rw-r--r--npc/functions/siege.txt8
-rw-r--r--npc/functions/soul_menhir.txt1
-rw-r--r--npc/functions/util.txt19
10 files changed, 261 insertions, 22 deletions
diff --git a/npc/functions/array.txt b/npc/functions/array.txt
index 1a106175e..161cedd0b 100644
--- a/npc/functions/array.txt
+++ b/npc/functions/array.txt
@@ -411,3 +411,25 @@ function script array_filter {
freeloop(false);
return .@count;
}
+
+// array_highest(<array>)
+// Returns the index of the highest value in <array>
+// NOTE: Array must be an INT array!
+
+function script array_highest {
+ .@size = getarraysize(getarg(0));
+ .@win=0;
+ .@idx=0;
+ freeloop(true);
+
+ for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) {
+ if (getelementofarray(getarg(0), .@i) > .@win) {
+ .@win=getelementofarray(getarg(0), .@i);
+ .@idx=.@i;
+ }
+ }
+
+ freeloop(false);
+ return .@idx;
+}
+
diff --git a/npc/functions/clientversion.txt b/npc/functions/clientversion.txt
index 51e5eab84..94b37582f 100644
--- a/npc/functions/clientversion.txt
+++ b/npc/functions/clientversion.txt
@@ -579,6 +579,13 @@ function script clientupdater {
getitem GoldenGift, 1;
if (BaseLevel >= 75 && getq(TulimsharQuest_Eistein) >= 3)
getitem GraduationRobe, 1;
+ // Grant you Thief Skill Tier 4
+ if (THIEF_RANK >= 4) {
+ skill(MC_OVERCHARGE,1,0);
+ dispbottom l("You have learnt \"Barter\" in Thief Skills.");
+ }
+ // Update Crafting Score
+ CRAFTING_SCORE_COMPLETE=CRAFTING_SCORE*39;
}
// Test Server Updates
diff --git a/npc/functions/lockpicks.txt b/npc/functions/lockpicks.txt
index 88171c3dd..c8271ba3a 100644
--- a/npc/functions/lockpicks.txt
+++ b/npc/functions/lockpicks.txt
@@ -71,8 +71,8 @@ function script LockPicking {
l("Give up!"), 0;
if (!@menuret) {
- // 10% chance to save the lockpick
- if (rand(1,10) == 7)
+ // 25% chance to save the lockpick
+ if (rand2(1,4) == 2)
getitem Lockpicks, 1;
else
dispbottom l("The lockpick broke.");
@@ -92,8 +92,8 @@ function script LockPicking {
}
if (@pos >= .@d) {
- // 10% chance to save the lockpick
- if (rand(1,10) == 7)
+ // 20% chance to save the lockpick
+ if (rand2(1,5) == 3)
getitem Lockpicks, 1;
else
dispbottom l("The lockpick broke.");
diff --git a/npc/functions/main.txt b/npc/functions/main.txt
index e1b93fa46..b54401e02 100644
--- a/npc/functions/main.txt
+++ b/npc/functions/main.txt
@@ -330,6 +330,13 @@ function script gf_accid {
return .@value[0];
}
+// Get some char id, even if offline
+// ( Name )
+function script gf_charnameid {
+ .@nb = query_sql("SELECT char_id FROM `char` WHERE name='"+escape_sql(getarg(0))+"' LIMIT 2", .@value);
+ return .@value[0];
+}
+
// Get some char name from char ID, even if offline
// ( Name )
function script gf_charname {
diff --git a/npc/functions/politics.txt b/npc/functions/politics.txt
new file mode 100644
index 000000000..b4ddde37d
--- /dev/null
+++ b/npc/functions/politics.txt
@@ -0,0 +1,143 @@
+// TMW2 Script
+// Author:
+// Jesusalva
+// Description:
+// Central Town Political System Controller
+// Note: The office is NOT Mayor, we have from kings to mayors here and you're
+// not a citzen (yet). It'll be... I'll think in a name better than Minister.
+// Perhaps, Town Administrator.
+// NPCs:
+// Tulim -
+// Halin -
+// Hurns - Airlia
+// LoF -
+// Nival -
+// Frostia -
+// Variables:
+// $LOC_MAYOR$ - Stores the name of current Hurnscald Mayor
+// $LOC_MONEY - Total money reserves of Hurnscald
+// $LOC_TAX - How much in % is charged as taxes. (OnBuy income)
+// $LOC_EXPORT - Defines how much Hurnscald exports (weekly income)
+// $LOC_REPUTATION - Town reputation. Affects Max Tax and Weekly Income;
+// Note: Tax cannot exceed 10% ie 1000. Reputation must be between 0 and 100.
+//
+// "Temporary Arrays":
+// $LOC_CANDIDATE$ - Candidate for Office
+// $LOC_VOTES - Number of votes of Candidate
+
+// Proccess Taxes from purchases
+// PurchaseTaxes( Location )
+function script PurchaseTaxes {
+ .@tax=0;
+ for (.@i=0; .@i < getarraysize(@bought_nameid); .@i++) {
+ // Note: Some NPC might not
+ .@price=getiteminfo(@bought_nameid[.@i], ITEMINFO_BUYPRICE);
+ .@tax+=.@price*@bought_quantity[.@i];
+ }
+ .@loc$=strtoupper(getarg(0, LOCATION$));
+ .@vat=getd("$"+.@loc$+"_TAX");
+ .@tax=.@tax*.@vat/10000;
+ if (.@tax) {
+ debugmes "%s paid %d in taxes to %s prefecture!", strcharinfo(0), .@tax, .@loc$;
+ setd("$"+.@loc$+"_TAX", .@vat+.@tax);
+ }
+ return;
+}
+
+- script Politics NPC_HIDDEN,{
+
+OnSun0000:
+ // Weekly income
+ $TULIM_MONEY+=$TULIM_EXPORT*limit(0, $TULIM_REPUTATION, 100)/100;
+ $HALIN_MONEY+=$HALIN_EXPORT*limit(0, $HALIN_REPUTATION, 100)/100;
+ $HURNS_MONEY+=$HURNS_EXPORT*limit(0, $HURNS_REPUTATION, 100)/100;
+ $LOF_MONEY+=$LOF_EXPORT*limit(0, $LOF_REPUTATION, 100)/100;
+ $NIVAL_MONEY+=$NIVAL_EXPORT*limit(0, $NIVAL_REPUTATION, 100)/100;
+ $FROSTIA_MONEY+=$FROSTIA_EXPORT*limit(0, $FROSTIA_REPUTATION, 100)/100;
+
+ // Send salary to Town Administrators (20% from exports and 5GP/reputation)
+ .@tax=$TULIM_EXPORT*limit(0, $TULIM_REPUTATION, 100)/500;
+ .@tax+=$TULIM_REPUTATION*5;
+ .@tax=min($TULIM_MONEY, .@tax);
+ $TULIM_MONEY-=.@tax;
+ rodex_sendmail(gf_charnameid($TULIM_MAYOR$), "Tulimshar Townhall", "Term Income", "You've received the money for the term.", .@tax);
+
+ .@tax=$HALIN_EXPORT*limit(0, $HALIN_REPUTATION, 100)/500;
+ .@tax+=$HALIN_REPUTATION*5;
+ .@tax=min($HALIN_MONEY, .@tax);
+ $HALIN_MONEY-=.@tax;
+ rodex_sendmail(gf_charnameid($HALIN_MAYOR$), "Halinarzo Townhall", "Term Income", "You've received the money for the term.", .@tax);
+
+ .@tax=$HURNS_EXPORT*limit(0, $HURNS_REPUTATION, 100)/500;
+ .@tax+=$HURNS_REPUTATION*5;
+ .@tax=min($HURNS_MONEY, .@tax);
+ $HURNS_MONEY-=.@tax;
+ rodex_sendmail(gf_charnameid($HURNS_MAYOR$), "Hurnscald Townhall", "Term Income", "You've received the money for the term.", .@tax);
+
+ .@tax=$LOF_EXPORT*limit(0, $LOF_REPUTATION, 100)/500;
+ .@tax+=$LOF_REPUTATION*5;
+ .@tax=min($LOF_MONEY, .@tax);
+ $LOF_MONEY-=.@tax;
+ rodex_sendmail(gf_charnameid($LOF_MAYOR$), "LoF Townhall", "Term Income", "You've received the money for the term.", .@tax);
+
+ .@tax=$NIVAL_EXPORT*limit(0, $NIVAL_REPUTATION, 100)/500;
+ .@tax+=$NIVAL_REPUTATION*5;
+ .@tax=min($NIVAL_MONEY, .@tax);
+ $NIVAL_MONEY-=.@tax;
+ rodex_sendmail(gf_charnameid($NIVAL_MAYOR$), "Nivalis Townhall", "Term Income", "You've received the money for the term.", .@tax);
+
+ .@tax=$FROSTIA_EXPORT*limit(0, $FROSTIA_REPUTATION, 100)/500;
+ .@tax+=$FROSTIA_REPUTATION*5;
+ .@tax=min($FROSTIA_MONEY, .@tax);
+ $FROSTIA_MONEY-=.@tax;
+ rodex_sendmail(gf_charnameid($FROSTIA_MAYOR$), "Frostia Townhall", "Term Income", "You've received the money for the term.", .@tax);
+
+ // Conduct elections
+ .@w=array_highest($TULIM_VOTES);
+ if ($TULIM_CANDIDATE$[.@w] != "")
+ $TULIM_MAYOR$=$TULIM_CANDIDATE$[.@w];
+ deletearray($TULIM_CANDIDATE$);
+ deletearray($TULIM_VOTES);
+
+ .@w=array_highest($HALIN_VOTES);
+ if ($HALIN_CANDIDATE$[.@w] != "")
+ $HALIN_MAYOR$=$HALIN_CANDIDATE$[.@w];
+ deletearray($HALIN_CANDIDATE$);
+ deletearray($HALIN_VOTES);
+
+ .@w=array_highest($HURNS_VOTES);
+ if ($HURNS_CANDIDATE$[.@w] != "")
+ $HURNS_MAYOR$=$HURNS_CANDIDATE$[.@w];
+ deletearray($HURNS_CANDIDATE$);
+ deletearray($HURNS_VOTES);
+
+ .@w=array_highest($LOF_VOTES);
+ if ($LOF_CANDIDATE$[.@w] != "")
+ $LOF_MAYOR$=$LOF_CANDIDATE$[.@w];
+ deletearray($LOF_CANDIDATE$);
+ deletearray($LOF_VOTES);
+
+ .@w=array_highest($NIVAL_VOTES);
+ if ($NIVAL_CANDIDATE$[.@w] != "")
+ $NIVAL_MAYOR$=$NIVAL_CANDIDATE$[.@w];
+ deletearray($NIVAL_CANDIDATE$);
+ deletearray($NIVAL_VOTES);
+
+ .@w=array_highest($FROSTIA_VOTES);
+ if ($FROSTIA_CANDIDATE$[.@w] != "")
+ $FROSTIA_MAYOR$=$FROSTIA_CANDIDATE$[.@w];
+ deletearray($FROSTIA_CANDIDATE$);
+ deletearray($FROSTIA_VOTES);
+
+ // Notify new mayors of their victory
+ rodex_sendmail(gf_charnameid($TULIM_MAYOR$), "Tulimshar Townhall", "Election Victory", "You've been elected to the office!");
+ rodex_sendmail(gf_charnameid($HALIN_MAYOR$), "Halinarzo Townhall", "Election Victory", "You've been elected to the office!");
+ rodex_sendmail(gf_charnameid($HURNS_MAYOR$), "Hurnscald Townhall", "Election Victory", "You've been elected to the office!");
+ rodex_sendmail(gf_charnameid($LOF_MAYOR$), "LoF Townhall", "Election Victory", "You've been elected to the office!");
+ rodex_sendmail(gf_charnameid($NIVAL_MAYOR$), "Nivalis Townhall", "Election Victory", "You've been elected to the office!");
+ rodex_sendmail(gf_charnameid($FROSTIA_MAYOR$), "Frostia Townhall", "Election Victory", "You've been elected to the office!");
+
+ end;
+
+}
+
diff --git a/npc/functions/refine.txt b/npc/functions/refine.txt
index 1936b5542..48535f91d 100644
--- a/npc/functions/refine.txt
+++ b/npc/functions/refine.txt
@@ -24,6 +24,7 @@ function script refineMaster {
l("Nothing, thanks"), 0,
rif(getequipisequiped(EQI_HEAD_MID), l("My chestplate, @@", getequipname(EQI_HEAD_MID))), EQI_HEAD_MID,
rif(getequipisequiped(EQI_HAND_R), l("My weapon, @@", getequipname(EQI_HAND_R))), EQI_HAND_R,
+ rif(getequipisequiped(EQI_HAND_L), l("My shield, @@", getequipname(EQI_HAND_L))), EQI_HAND_L,
rif(getequipisequiped(EQI_HEAD_TOP), l("My helmet, @@", getequipname(EQI_HEAD_TOP))), EQI_HEAD_TOP,
l("Item break? Too dangerous! I don't want it!!"), 0;
@@ -53,7 +54,7 @@ function script refineMaster {
// Not all items are refinable
if (!getequipisenableref(.@it)) {
mesn;
- mesq l("Well, sorry, but only weapons and body armor can be refined.");
+ mesq l("Well, sorry, but only some items can be refined.");
mesq l("There may be some exceptions. Anyway, this item clearly cannot be refined.");
next;
return;
@@ -73,20 +74,21 @@ function script refineMaster {
switch (.@rlv) {
case 0:
case 1:
- .@rg=CopperIngot; break;
case 2:
case 3:
- .@rg=IronIngot; break;
+ .@rg=Wurtizite; break;
case 4:
case 5:
- .@rg=TitaniumIngot; break;
case 6:
case 7:
- .@rg=LeadIngot; break;
+ .@amount=((.@rlv-4)/2)+1;
+ .@rg=Graphene; break;
case 8:
- .@rg=Bloodstone; break;
+ case 9:
+ case 10:
default:
- .@rg=BlueManaPearl; break;
+ .@amount=((.@rlv-8)/2)+1;
+ .@rg=Arcanum; break;
}
mesn;
mesq l("This @@ is a nice stuff. I can refine it for @@ GP and @@ @@.", getitemlink(.@item), .@price, .@amount, getitemlink(.@rg));
@@ -151,8 +153,8 @@ function script refineMaster {
mesc l("Weapons: +8 attack, +8 magic attack");
mesc l("Armors: +3~5 defense");
next;
- // Perhaps the item has broken?
- } else if (rand2(100) < .@rlv) {
+ // Perhaps the item has broken? (~0.01% chance)
+ } else if (rand2(10000) <= 1) {
failedrefitem .@it;
mesc l("*CRASH*");
next;
@@ -162,7 +164,7 @@ function script refineMaster {
mesn;
mesq l("Well, you were warned. Do you have any other stuff for me?");
next;
- // Item is weakened.
+ // Item is weakened. (1% per refine level)
} else if (rand2(100) < .@rlv) {
downrefitem .@it, 1;
mesn;
diff --git a/npc/functions/resetstatus.txt b/npc/functions/resetstatus.txt
index c9744d901..e1d290499 100644
--- a/npc/functions/resetstatus.txt
+++ b/npc/functions/resetstatus.txt
@@ -5,6 +5,41 @@
// Description:
// Status Reset NPC utils
+// Reset status and return permanent bonuses
+// StatusResetReinvest( - )
+function script StatusResetReinvest {
+ // Compulsory check
+ inventoryplace NPCEyes, 6;
+
+ // Permanent boosts were now lost, return the fruits
+ if (STATUSUP_STR) {
+ getitem StrengthFruit, STATUSUP_STR;
+ STATUSUP_STR=0;
+ }
+ if (STATUSUP_AGI) {
+ getitem AgilityFruit, STATUSUP_AGI;
+ STATUSUP_AGI=0;
+ }
+ if (STATUSUP_VIT) {
+ getitem VitalityFruit, STATUSUP_VIT;
+ STATUSUP_VIT=0;
+ }
+ if (STATUSUP_INT) {
+ getitem IntelligenceFruit, STATUSUP_INT;
+ STATUSUP_INT=0;
+ }
+ if (STATUSUP_DEX) {
+ getitem DexterityFruit, STATUSUP_DEX;
+ STATUSUP_DEX=0;
+ }
+ if (STATUSUP_LUK) {
+ getitem LuckFruit, STATUSUP_LUK;
+ STATUSUP_LUK=0;
+ }
+ resetstatus();
+ return true;
+}
+
// Return wasSP on success, 0 on failure
// ConfirmReset( {price} )
function script ConfirmStatusReset {
@@ -16,6 +51,8 @@ function script ConfirmStatusReset {
if (getarg(0,-1) >= 0)
.@plush_count=getarg(0,-1);
+ mesc l("WARNING: Permanent boosts will return to their fruit form."), 1;
+
switch (select(lg("Yes, I am sure."),
lg("I need to think about it..."),
lg("I won't need it, thank you.")))
@@ -38,16 +75,17 @@ function script ConfirmStatusReset {
l("Thank you."),
l("Now stand still... It should not take much time...");
- // Delete the GP and THEN reset the status
- Zeny-=.@plush_count;
+ // Reset status have an inventorycheck, so we charge later.
.@wasSP = StatusPoint;
- resetstatus();
+ StatusResetReinvest();
+
+ // Nothing to do: Do not charge (eg. you just got the fruits back)
if (StatusPoint == .@wasSP) {
speech S_LAST_NEXT,
l("It seems that you have no status points to reset!"),
- l("But the money you brought was really awesome you know."),
l("Come back when you will really need me.");
} else {
+ Zeny-=.@plush_count;
speech S_LAST_NEXT,
l("Let's see... @@ of your status points have just been reset!", StatusPoint - .@wasSP),
l("Spend it wisely this time."),
diff --git a/npc/functions/siege.txt b/npc/functions/siege.txt
index e8f40b229..9be7a9e23 100644
--- a/npc/functions/siege.txt
+++ b/npc/functions/siege.txt
@@ -191,14 +191,18 @@ function script siege_check {
.@mb+=mobcount(.@m$, "#SiegeCtrl::OnColonelDeath");
.@mb+=mobcount(.@m$, "#SiegeCtrl::OnGeneralDeath");
- // Players failed, so reduce score in 1~10 (like Sergeant~General).
+ // Players failed, so reduce score in 1~5 (like Sergeant~General).
// In future, it could be inverse proportion (-9 for sergeant, -1 for general)
if (.@mb) {
if ($GAME_STORYLINE == 2)
- $MK_TEMPVAR-=rand2(1, 10);
+ $MK_TEMPVAR-=rand2(1, 5);
+
kamibroadcast("Players failed to defend the city!!");
debugmes "Number of boss grade monsters found: %d", .@mb;
$SIEGE_DIFFICULTY=max(1, ($SIEGE_DIFFICULTY/2));
+ // Lower the town reputation in 10%
+ .@var$="$"+MapToLoc(.@m$)+"_REPUTATION";
+ setd(.@var$, getd(.@var$)*9/10);
} else {
kamibroadcast("The city was defended with success! GG, everyone!");
$SIEGE_DIFFICULTY+=1;
diff --git a/npc/functions/soul_menhir.txt b/npc/functions/soul_menhir.txt
index 437e6d1e8..f44cc7b3b 100644
--- a/npc/functions/soul_menhir.txt
+++ b/npc/functions/soul_menhir.txt
@@ -102,6 +102,7 @@ L_Do_Save:
savepoint @map$, @x, @y;
specialeffect(4, SELF, getcharid(3));
} else {
+ EnterTown(MapToLoc(@map$));
dispbottom col(l("Your position is auto-saved when entering a town - use @ucp to change this behavior."), 1);
}
diff --git a/npc/functions/util.txt b/npc/functions/util.txt
index 21abcd1f2..c32a831e1 100644
--- a/npc/functions/util.txt
+++ b/npc/functions/util.txt
@@ -743,10 +743,9 @@ function script anyloot {
return Exception("Faulty anyloot skill command invoked - error");
// Get Items
- for (.@i=0;.@i < getargcount(); .@i++) {
+ for (.@i=0;.@i < getargcount(); .@i+=3) {
if (rand2(10000) < getarg(.@i+2))
getitem getarg(.@i), rand2(1, getarg(.@i+1));
- .@i++;
}
return true;
}
@@ -826,3 +825,19 @@ function script EnterTown {
return;
}
+// Convert map name to location id
+// MapToLoc( MapName )
+function script MapToLoc {
+ // Fill variable
+ .@v$=getarg(0);
+
+ // Validade variable, see npc/000-1/exit.txt first
+ setarray .@mapx$, "005-1", "003-1", "009-1", "012-1", "017-1", "018-5", "020-1", "024-1";
+ setarray .@locs$, "Candor", "Tulim", "Halin", "Hurns", "LoF", "Lilit", "Nival", "Frostia";
+ .@lx=array_find(.@locs$, .@v$);
+ if (.@lx < 0)
+ return Exception("Invalid map passed to MapToLoc: "+.@v$, RB_DEBUGMES);
+
+ return .@locs$[.@lx];
+}
+