From ce7cbf358967493350caccc61124395f44ad040e Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:06:08 -0300 Subject: areasc() - never target caster. areasc2() [NEW] - For NPC usage --- npc/items/grenade.txt | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/npc/items/grenade.txt b/npc/items/grenade.txt index 0fdd5ea05..59e0e4ae5 100644 --- a/npc/items/grenade.txt +++ b/npc/items/grenade.txt @@ -27,7 +27,7 @@ function script grenade { } // areasc(range, time, sc, bl) - defaults to 3x3 square, sleep mob for 500ms. -// before was: smoke_grenade(). Valid BL: BL_MOB | BL_PC | BL_HOM | BL_MER +// Need a player caster. Valid BL: BL_MOB | BL_PC | BL_HOM | BL_MER function script areasc { .@r=getarg(0, 3); .@d=getarg(1, 500); @@ -35,6 +35,28 @@ function script areasc { .@b=getarg(3, BL_MOB); getmapxy(.@m$, .@x, .@y, 0); + .@c=getunits(.@b, .@mbs, false, .@m$, .@x-.@r, .@y-.@r, .@x+.@r, .@y+.@r); + for (.@i = 0; .@i < .@c; .@i++) { + // Never target the caster + if (.@mbs[.@i] == getcharid(3)) + continue; + sc_start .@s, .@d, 1, 10000, SCFLAG_NONE, .@mbs[.@i]; + specialeffect(FX_BUFF, AREA, .@mbs[.@i]); + } + return; +} + +// areasc2(map, x, y, {range, time, sc, bl}) - can be used by NPC +// Valid BL: BL_MOB | BL_PC | BL_HOM | BL_MER +function script areasc { + .@m$=getarg(0); + .@x=getarg(1); + .@y=getarg(2); + .@r=getarg(3, 3); + .@d=getarg(4, 500); + .@s=getarg(5, SC_SLEEP); + .@b=getarg(6, BL_MOB); + .@c=getunits(.@b, .@mbs, false, .@m$, .@x-.@r, .@y-.@r, .@x+.@r, .@y+.@r); for (.@i = 0; .@i < .@c; .@i++) { sc_start .@s, .@d, 1, 10000, SCFLAG_NONE, .@mbs[.@i]; -- cgit v1.2.3-70-g09d2 From 2347ce5b6c84a62be386643aa9b4773a1c3bb9d0 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:06:41 -0300 Subject: New logic for siege difficulty calculator - it now use flags. Previous implementation was bad. --- npc/functions/siege.txt | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/npc/functions/siege.txt b/npc/functions/siege.txt index 95d16ebc2..baca59a63 100644 --- a/npc/functions/siege.txt +++ b/npc/functions/siege.txt @@ -18,22 +18,31 @@ function script siege_spawn { } // Calculate player average level -// if highest is set, it will return highest player level, with minimum the value -// passed. (A level "0" is clearly not valid, of course) -// siege_calcdiff ( map{, highest_lvl} ) +// flag 1 - Don't count dead players +// flag 2 - Return highest player level, instead of average. +// flag 4 - Return the total sum of levels instead. +// siege_calcdiff ( map{, flags} ) function script siege_calcdiff { .@bsum=0; - .@highest=getarg(1, false); + if (getarg(1,0) & 1) + .@deadcount=true; + if (getarg(1,0) & 2) + .@onlyhighest=true; + if (getarg(1,0) & 4) + .@onlytotal=true; .@c = getunits(BL_PC, .@players, false, getarg(0)); .@skip=0; // There is at least one player, do things properly for (.@i = 0; .@i < .@c; .@i++) { - /* // Dead players are not counted - if (ispcdead(strcharinfo(0, "", .@players[.@i]))) - continue; - */ + if (.@deadcount) { + if (ispcdead(strcharinfo(0, "", .@players[.@i]))) { + .@skip+=1; + continue; + } + } + .@b=readparam(BaseLevel, .@players[.@i]); // GMs are not counted @@ -53,8 +62,10 @@ function script siege_calcdiff { //debugmes "calcdiff: Total %d Average %d Highest %d", .@bsum, (.@bsum/.@c), .@highest; - if (getarg(1,false)) + if (.@onlyhighest) return .@highest; + else if (.@onlytotal) + return .@bsum; else return (.@bsum/.@c); } -- cgit v1.2.3-70-g09d2 From 8a6628c11c04179a7738c3d60b606d38bf567ab2 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:10:13 -0300 Subject: Monster King Challenge - minimal logic --- npc/boss/throne.txt | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/npc/boss/throne.txt b/npc/boss/throne.txt index e8f375bff..d44a63c99 100644 --- a/npc/boss/throne.txt +++ b/npc/boss/throne.txt @@ -14,4 +14,51 @@ OnTouch: dispbottom "The throne is cursed, only the Monster King may seat on it."; end; +// Controls the Event +OnBegin: + .MK=monster("boss", 45, 45, "The Monster King", MonsterKing, 1, .name$+"::OnVictory"); + .@bhp=getunitdata(.MK, UDT_MAXHP); + setunitdata(.MK, UDT_MAXHP, .@bhp+50000+2000*.FAILS); + setunitdata(.MK, UDT_HP, .@bhp+50000+2000*.FAILS); + + initnpctimer; + end; + +function CheckFinalAssault { + if (!siege_calcdiff(5)) { + kamibroadcast("You noobs, you all deserve to die!", "Monster King"); + stopnpctimer; + // Clean Up + mapwarp("boss", "017-1", 120, 88); + killmonsterall("boss"); + // Raise difficulty + .FAILS+=1; + // Halt execution + end; + } + return; +} + +OnTimer60000: + initnpctimer; +OnTimer15000: + // Each fail raise curse duration in 0.1s - chance of curse is 15% each 15s + if (rand2(100) <= 15) { + areasc2("boss", 45, 45, 25, 3000+(.FAILS*100), SC_CURSE, BL_PC | BL_HOM | BL_MER); + //globalmes("MSG"); + unittalk(.MK, "Be cursed, you fools! I am the mighty Monster King!!"); + } +OnTimer5000: +OnTimer10000: +OnTimer20000: +OnTimer25000: +OnTimer30000: +OnTimer35000: +OnTimer40000: +OnTimer45000: +OnTimer50000: +OnTimer55000: + CheckFinalAssault(); + end; + } -- cgit v1.2.3-70-g09d2 From b08955ff55790712de30e71782b7829f0d1696bc Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:24:56 -0300 Subject: Monster King main basic functions --- npc/boss/throne.txt | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/npc/boss/throne.txt b/npc/boss/throne.txt index d44a63c99..10e2fff92 100644 --- a/npc/boss/throne.txt +++ b/npc/boss/throne.txt @@ -16,11 +16,20 @@ OnTouch: // Controls the Event OnBegin: + .CYCLES=0; .MK=monster("boss", 45, 45, "The Monster King", MonsterKing, 1, .name$+"::OnVictory"); .@bhp=getunitdata(.MK, UDT_MAXHP); setunitdata(.MK, UDT_MAXHP, .@bhp+50000+2000*.FAILS); setunitdata(.MK, UDT_HP, .@bhp+50000+2000*.FAILS); + // Spawn reinforcements + .@mobId=MonsterLieutenant; + .@ts$="Lieutenant"; + monster("boss", 40, 40, strmobinfo(1, .@mobId), .@mobId, 1, "#SiegeCtrl::On"+.@ts$+"Death"); + monster("boss", 50, 50, strmobinfo(1, .@mobId), .@mobId, 1, "#SiegeCtrl::On"+.@ts$+"Death"); + monster("boss", 40, 50, strmobinfo(1, .@mobId), .@mobId, 1, "#SiegeCtrl::On"+.@ts$+"Death"); + monster("boss", 50, 40, strmobinfo(1, .@mobId), .@mobId, 1, "#SiegeCtrl::On"+.@ts$+"Death"); + initnpctimer; end; @@ -39,7 +48,22 @@ function CheckFinalAssault { return; } -OnTimer60000: +OnTimer120000: + .CYCLES+=1; + //areamonster("boss", 20, 20, 70, 70, "Monster King Slave", ); + // Spawn several monsters on the Boss Room every 2 minutes + siege_cast("boss", .name$, .FAILS, TP_TULIM|TP_HURNS|TP_NIVAL); + // Spawn an extra mini-boss at minutes: 10 and 30 + if (.CYCLES == 5) { + .@mobId=MonsterColonel; + .@ts$="Colonel"; + monster("boss", 45, 44, strmobinfo(1, .@mobId), .@mobId, 1, "#SiegeCtrl::On"+.@ts$+"Death"); + } + if (.CYCLES == 15) { + .@mobId=MonsterGeneral; + .@ts$="General"; + monster("boss", 45, 44, strmobinfo(1, .@mobId), .@mobId, 1, "#SiegeCtrl::On"+.@ts$+"Death"); + } initnpctimer; OnTimer15000: // Each fail raise curse duration in 0.1s - chance of curse is 15% each 15s @@ -58,7 +82,35 @@ OnTimer40000: OnTimer45000: OnTimer50000: OnTimer55000: +OnTimer60000: +OnTimer65000: +OnTimer70000: +OnTimer75000: +OnTimer80000: +OnTimer85000: +OnTimer90000: +OnTimer95000: +OnTimer100000: +OnTimer105000: +OnTimer110000: +OnTimer115000: CheckFinalAssault(); end; +// Monster King was defeated - game won +OnVictory: + // Not killed by a player? It doesn't counts, then + if (!playerattached()) + end; + kamibroadcast("has just defeated the Monster King.", strcharinfo(0)); + stopnpctimer; + mapwarp("boss", "017-1", 120, 88); + $GAME_STORYLINE=5; + getitembound(AegisShield, 1, 1); + dispbottom l("For defeating the Monster King, you've got the Legendary @@.", getitemlink(AegisShield)); + dispbottom l("This item cannot be traded normally and is a Legendary Item."); + dispbottom l("You can transfer it with \"@grantpower\" command. Please contact a GM for more info."); + dispbottom l("Protip: If you plan in selling it, it's adviseable to ask for GM mediation."); + end; } + -- cgit v1.2.3-70-g09d2 From b59998c69271c96ca7b1297088f44d3ed8919c2b Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:29:34 -0300 Subject: It's pretty basic, but this should be an OK-fight for the server "final" event. --- npc/boss/throne.txt | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/npc/boss/throne.txt b/npc/boss/throne.txt index 10e2fff92..a04f2ba94 100644 --- a/npc/boss/throne.txt +++ b/npc/boss/throne.txt @@ -114,3 +114,36 @@ OnVictory: end; } +// Room Traps, only against players +boss,0,0,0 script #MKBossTrap01 NPC_TRAP,0,0,{ + end; + +OnTouch: + SteelTrap(rand2(10, 20)); + end; + +OnTimer10000: + stopnpctimer; + setnpctimer 0; + setnpcdisplay .name$, NPC_TRAP; + //end; + // Move the trap away after it disarms + +OnMinute14: +OnMinute26: +OnMinute40: +OnMinute54: +OnInit: + .@x=rand2(20,70); + .@y=rand2(20,70); + movenpc .name$, .@x, .@y; + end; +} + +// Create more traps. (They can be on walls) +boss,0,0,0 duplicate(#MKBossTrap01) #MKBossTrap02 NPC_TRAP,0,0 +boss,0,0,0 duplicate(#MKBossTrap01) #MKBossTrap03 NPC_TRAP,0,0 +boss,0,0,0 duplicate(#MKBossTrap01) #MKBossTrap04 NPC_TRAP,0,0 +boss,0,0,0 duplicate(#MKBossTrap01) #MKBossTrap05 NPC_TRAP,0,0 + + -- cgit v1.2.3-70-g09d2 From 2b55cdd7b705ca8ecfed377465ce08dde54e5242 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:33:54 -0300 Subject: If the big boss is dead - drop mob population to ΒΌ, disable precise chase, make they spawn 5x slower, and disable all aggressive monsters. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- npc/boss/throne.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/npc/boss/throne.txt b/npc/boss/throne.txt index a04f2ba94..539a4aa17 100644 --- a/npc/boss/throne.txt +++ b/npc/boss/throne.txt @@ -106,6 +106,15 @@ OnVictory: stopnpctimer; mapwarp("boss", "017-1", 120, 88); $GAME_STORYLINE=5; + // Without the Monster King to rule monsters... TODO Isbamuth + setbattleflag("monster_ai", 0x209); + setbattleflag("monster_active_enable", false); + setbattleflag("mob_count_rate", 25); + setbattleflag("mob_spawn_delay", 500); + charcommand("@reloadbattleconf"); // Careful! + donpcevent("@exprate::OnReload"); + donpcevent("@droprate::OnReload"); + // Player Reward getitembound(AegisShield, 1, 1); dispbottom l("For defeating the Monster King, you've got the Legendary @@.", getitemlink(AegisShield)); dispbottom l("This item cannot be traded normally and is a Legendary Item."); -- cgit v1.2.3-70-g09d2 From b4b5c304355ed0246627e33da616c72ca1d70694 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:39:08 -0300 Subject: Remove the spawn delay change, it won't work because day/night cycle overrides it --- npc/boss/throne.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/npc/boss/throne.txt b/npc/boss/throne.txt index 539a4aa17..784c51d4f 100644 --- a/npc/boss/throne.txt +++ b/npc/boss/throne.txt @@ -110,7 +110,6 @@ OnVictory: setbattleflag("monster_ai", 0x209); setbattleflag("monster_active_enable", false); setbattleflag("mob_count_rate", 25); - setbattleflag("mob_spawn_delay", 500); charcommand("@reloadbattleconf"); // Careful! donpcevent("@exprate::OnReload"); donpcevent("@droprate::OnReload"); -- cgit v1.2.3-70-g09d2 From 0a54c5c7cce42237a4403153666e7126112d14f2 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:39:57 -0300 Subject: Fix areasc2 bug --- npc/items/grenade.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npc/items/grenade.txt b/npc/items/grenade.txt index 59e0e4ae5..40959ad94 100644 --- a/npc/items/grenade.txt +++ b/npc/items/grenade.txt @@ -48,7 +48,7 @@ function script areasc { // areasc2(map, x, y, {range, time, sc, bl}) - can be used by NPC // Valid BL: BL_MOB | BL_PC | BL_HOM | BL_MER -function script areasc { +function script areasc2 { .@m$=getarg(0); .@x=getarg(1); .@y=getarg(2); -- cgit v1.2.3-70-g09d2 From 66203e9bba74774457133d8df8e0f7dd7e11c566 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Mon, 29 Jul 2019 20:43:40 -0300 Subject: $@MK_CHALLENGE control variable and NPC_AIRSHIP --- db/constants.conf | 1 + npc/boss/throne.txt | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/db/constants.conf b/db/constants.conf index c46df610b..e9319f9db 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -4157,6 +4157,7 @@ constants_db: { NPC_YETI: 457 NPC_MONSTERKING: 500 + NPC_AIRSHIP: 501 NPC_SOUL_NORMAL: 700 NPC_SOUL_DESERT: 701 diff --git a/npc/boss/throne.txt b/npc/boss/throne.txt index 784c51d4f..c34cbf6cd 100644 --- a/npc/boss/throne.txt +++ b/npc/boss/throne.txt @@ -2,7 +2,7 @@ // Author: // Jesusalva // Description: -// Monster King Throne +// Monster King Throne ($@MK_CHALLENGE) boss,45,45,0 script #monsterthrone NPC_HIDDEN,0,0,{ end; @@ -17,6 +17,7 @@ OnTouch: // Controls the Event OnBegin: .CYCLES=0; + $@MK_CHALLENGE=true; .MK=monster("boss", 45, 45, "The Monster King", MonsterKing, 1, .name$+"::OnVictory"); .@bhp=getunitdata(.MK, UDT_MAXHP); setunitdata(.MK, UDT_MAXHP, .@bhp+50000+2000*.FAILS); @@ -37,6 +38,7 @@ function CheckFinalAssault { if (!siege_calcdiff(5)) { kamibroadcast("You noobs, you all deserve to die!", "Monster King"); stopnpctimer; + $@MK_CHALLENGE=false; // Clean Up mapwarp("boss", "017-1", 120, 88); killmonsterall("boss"); @@ -102,6 +104,7 @@ OnVictory: // Not killed by a player? It doesn't counts, then if (!playerattached()) end; + $@MK_CHALLENGE=false; kamibroadcast("has just defeated the Monster King.", strcharinfo(0)); stopnpctimer; mapwarp("boss", "017-1", 120, 88); -- cgit v1.2.3-70-g09d2