Implemented Clock Tower quest

This commit is contained in:
Oven Bread 2023-08-12 08:39:53 +00:00 committed by Ryan
parent 6112abf673
commit bb21ad533b
6 changed files with 506 additions and 16 deletions

View file

@ -153,7 +153,7 @@
},
{
"npc_id": "47",
"loc_data": "{2521,3331,0,1,3}-{2531,3325,0,1,3}-{2526,3328,0,1,3}-{2523,3331,0,1,4}-{2523,3334,0,1,1}-{2530,3327,0,1,5}-{2531,3329,0,1,5}-{2532,3333,0,1,5}-{3108,9754,0,1,5}-{3110,9754,0,1,5}-{3108,9750,0,1,5}-{2930,9699,0,1,0}-{2933,9697,0,1,0}-{2932,9685,0,1,0}-{2930,9693,0,1,0}-{3097,3364,0,1,3}-{3102,3363,0,1,5}-{3341,3267,0,1,5}-{3235,3224,0,1,3}-{3229,3220,0,1,4}-{3211,3211,0,1,3}-{3225,3220,0,1,1}-{3237,3215,0,1,5}-{3211,3210,0,1,7}-{3227,3220,0,1,7}-{3233,3227,0,1,5}-{3227,3210,0,1,6}-{3228,3222,0,1,4}-{3229,3226,0,1,0}-{3127,3487,0,1,4}-{3125,3486,0,1,6}-{3127,3486,0,1,4}-{3019,3292,0,1,7}-{3018,3295,0,1,7}-{3001,3202,0,1,5}-{3021,3205,0,1,6}-{3026,3174,0,1,5}-{3019,3176,0,1,7}-{3076,3282,0,1,5}-{3089,3266,0,1,4}-{3091,3266,0,1,4}-{3243,3687,0,1,5}-{3249,3669,0,1,3}-{3252,3675,0,1,4}-{3252,3680,0,1,3}-{3259,3683,0,1,0}-{3276,9871,0,1,1}-{3277,9871,0,1,3}-{3225,9862,0,1,4}-{3222,9861,0,1,6}-{3220,9860,0,1,6}-{3219,9865,0,1,6}-{3237,9862,0,1,4}-{3236,3217,0,1,4}-{3259,3230,0,1,4}-{3158,3226,0,1,5}-{3160,3202,0,1,4}-{3233,3237,0,1,7}-{2821,3170,0,1,1}-{2801,3158,0,1,2}-{2852,9642,0,1,6}-{2858,9632,0,1,3}-{2536,2982,0,1,3}-{2531,2980,0,1,0}-{2522,2981,0,1,4}-{2545,2989,0,1,4}-{2523,2970,0,1,2}-{2603,9480,0,1,1}-{2600,9477,0,1,0}-{2579,9496,0,1,4}-{2580,9508,0,1,0}-{2571,9522,0,1,4}-{2654,9640,0,1,6}-{2655,9637,0,1,4}-{2656,9639,0,1,7}-{2651,9636,0,1,5}-{2648,9637,0,1,4}-{2651,9642,0,1,1}-{2654,9640,0,1,0}-{2654,9635,0,1,6}-{2655,9635,0,1,3}-{2664,9626,0,1,6}-{2664,9624,0,1,1}-{2661,9623,0,1,1}-{2663,9623,0,1,3}-{2664,9626,0,1,6}-{2592,9831,0,1,3}-{2588,9825,0,1,6}-{2583,9829,0,1,4}-{2581,9841,0,1,0}-{2597,9823,0,1,2}-{2579,9805,0,1,3}-{2576,9804,0,1,0}-{2573,9805,0,1,5}-{2571,9808,0,1,3}-{2576,9810,0,1,2}-{2587,9802,0,1,2}-{2592,9800,0,1,4}-{2596,9805,0,1,6}-{2601,9802,0,1,5}-{2585,9801,0,1,7}-{2594,9803,0,1,0}-{2590,9806,0,1,3}-{2612,9808,0,1,6}-{2604,9810,0,1,6}-{2579,9821,0,1,2}-{2576,9812,0,1,6}-{2580,9813,0,1,6}-{2600,9813,0,1,4}-{2599,9809,0,1,4}-{2514,3193,0,1,6}-{2518,3192,0,1,3}-{2507,3181,0,1,3}-{2508,3178,0,1,6}-{2511,3183,0,1,3}-{2515,3182,0,1,1}-{2565,9505,0,1,1}-{2566,9510,0,1,6}-{2594,9497,0,1,4}-{3475,9840,0,1,6}-{3481,9842,0,1,1}-{3486,9843,0,1,7}-{3483,9824,0,1,4}-{3496,9808,0,0,5}-{3490,9815,0,1,1}-{3478,9834,0,0,3}-{3490,9824,0,1,4}-{3192,3203,0,1,0}-{3194,3204,0,1,0}-{3196,3206,0,1,0}-{3197,3204,0,1,0}-{3205,3204,0,1,0}-{3206,3204,0,1,0}-{3205,3203,0,1,0}-{3206,3202,0,1,0}-{3207,3202,0,1,0}-{3208,3203,0,1,0}"
"loc_data": "{2521,3331,0,1,3}-{2531,3325,0,1,3}-{2526,3328,0,1,3}-{2523,3331,0,1,4}-{2523,3334,0,1,1}-{2530,3327,0,1,5}-{2531,3329,0,1,5}-{2532,3333,0,1,5}-{3108,9754,0,1,5}-{3110,9754,0,1,5}-{3108,9750,0,1,5}-{2930,9699,0,1,0}-{2933,9697,0,1,0}-{2932,9685,0,1,0}-{2930,9693,0,1,0}-{3097,3364,0,1,3}-{3102,3363,0,1,5}-{3341,3267,0,1,5}-{3235,3224,0,1,3}-{3229,3220,0,1,4}-{3211,3211,0,1,3}-{3225,3220,0,1,1}-{3237,3215,0,1,5}-{3211,3210,0,1,7}-{3227,3220,0,1,7}-{3233,3227,0,1,5}-{3227,3210,0,1,6}-{3228,3222,0,1,4}-{3229,3226,0,1,0}-{3127,3487,0,1,4}-{3125,3486,0,1,6}-{3127,3486,0,1,4}-{3019,3292,0,1,7}-{3018,3295,0,1,7}-{3001,3202,0,1,5}-{3021,3205,0,1,6}-{3026,3174,0,1,5}-{3019,3176,0,1,7}-{3076,3282,0,1,5}-{3089,3266,0,1,4}-{3091,3266,0,1,4}-{3243,3687,0,1,5}-{3249,3669,0,1,3}-{3252,3675,0,1,4}-{3252,3680,0,1,3}-{3259,3683,0,1,0}-{3276,9871,0,1,1}-{3277,9871,0,1,3}-{3225,9862,0,1,4}-{3222,9861,0,1,6}-{3220,9860,0,1,6}-{3219,9865,0,1,6}-{3237,9862,0,1,4}-{3236,3217,0,1,4}-{3259,3230,0,1,4}-{3158,3226,0,1,5}-{3160,3202,0,1,4}-{3233,3237,0,1,7}-{2821,3170,0,1,1}-{2801,3158,0,1,2}-{2852,9642,0,1,6}-{2858,9632,0,1,3}-{2536,2982,0,1,3}-{2531,2980,0,1,0}-{2522,2981,0,1,4}-{2545,2989,0,1,4}-{2523,2970,0,1,2}-{2603,9480,0,1,1}-{2600,9477,0,1,0}-{2579,9496,0,1,4}-{2580,9508,0,1,0}-{2571,9522,0,1,4}-{2654,9640,0,1,6}-{2655,9637,0,1,4}-{2656,9639,0,1,7}-{2651,9636,0,1,5}-{2648,9637,0,1,4}-{2651,9642,0,1,1}-{2654,9640,0,1,0}-{2654,9635,0,1,6}-{2655,9635,0,1,3}-{2664,9626,0,1,6}-{2664,9624,0,1,1}-{2661,9623,0,1,1}-{2663,9623,0,1,3}-{2664,9626,0,1,6}-{2592,9831,0,1,3}-{2588,9825,0,1,6}-{2583,9829,0,1,4}-{2581,9841,0,1,0}-{2597,9823,0,1,2}-{2579,9805,0,1,3}-{2576,9804,0,1,0}-{2573,9805,0,1,5}-{2571,9808,0,1,3}-{2576,9810,0,1,2}-{2587,9802,0,1,2}-{2592,9800,0,1,4}-{2596,9805,0,1,6}-{2601,9802,0,1,5}-{2585,9801,0,1,7}-{2594,9803,0,1,0}-{2590,9806,0,1,3}-{2612,9808,0,1,6}-{2604,9810,0,1,6}-{2579,9821,0,1,2}-{2576,9812,0,1,6}-{2580,9813,0,1,6}-{2600,9813,0,1,4}-{2599,9809,0,1,4}-{2514,3193,0,1,6}-{2518,3192,0,1,3}-{2507,3181,0,1,3}-{2508,3178,0,1,6}-{2511,3183,0,1,3}-{2515,3182,0,1,1}-{2565,9505,0,1,1}-{2566,9510,0,1,6}-{2594,9497,0,1,4}-{3475,9840,0,1,6}-{3481,9842,0,1,1}-{3486,9843,0,1,7}-{3483,9824,0,1,4}-{3496,9808,0,0,5}-{3490,9815,0,1,1}-{3478,9834,0,0,3}-{3490,9824,0,1,4}-{3192,3203,0,1,0}-{3194,3204,0,1,0}-{3196,3206,0,1,0}-{3197,3204,0,1,0}-{3205,3204,0,1,0}-{3206,3204,0,1,0}-{3205,3203,0,1,0}-{3206,3202,0,1,0}-{3207,3202,0,1,0}-{3208,3203,0,1,0}-{2568,9620,0,1,0}-{2573,9612,0,1,0}-{2579,9631,0,1,0}-{2580,9600,0,1,0}-{2580,9614,0,1,0}-{2580,9620,0,1,0}-{2580,9626,0,1,0}-{2583,9632,0,1,0}-{2584,9625,0,1,0}-{2584,9637,0,1,0}-{2589,9644,0,1,0}-{2590,9601,0,1,0}-{2590,9638,0,1,0}-{2591,9601,0,1,0}-{2591,9621,0,1,0}-{2594,9636,0,1,0}-{2594,9644,0,1,0}-{2597,9604,0,1,0}-{2607,9615,0,1,0}-{2608,9628,0,1,0}-{2614,9651,0,1,0}-{2614,9656,0,1,0}-{2615,9647,0,1,0}-{2615,9661,0,1,0}-{2616,9633,0,1,0}-{2618,9630,0,1,0}"
},
{
"npc_id": "48",
@ -189,7 +189,7 @@
},
{
"npc_id": "59",
"loc_data": "{3182,3244,0,1,1}-{3250,3239,0,1,1}-{3241,3241,0,1,1}-{3082,3362,0,1,4}-{3146,3347,0,1,3}-{3249,3249,0,1,1}-{3102,9881,0,1,3}-{3095,9883,0,1,2}-{3218,9890,0,1,3}-{3220,9887,0,1,0}-{3218,9887,0,1,1}-{3218,9889,0,1,5}-{3213,9890,0,1,1}-{3162,3223,0,1,7}-{2461,2880,0,1,5}-{2489,2935,0,1,7}-{2492,2907,0,1,1}-{2496,2890,0,1,4}-{2487,2894,0,1,2}-{2487,2888,0,1,7}-{2483,2877,0,1,3}-{2481,2876,0,1,4}-{2457,2867,0,1,4}-{2481,2847,0,1,0}-{2475,2854,0,1,3}-{2482,2873,0,1,3}-{2485,2876,0,1,2}-{2449,2865,0,1,1}-{2478,2916,0,1,5}-{2485,2902,0,1,3}-{2487,2902,0,1,2}-{2489,2894,0,1,2}-{2490,2905,0,1,7}-{2490,2917,0,1,5}-{2484,2890,0,1,1}-{2503,2889,0,1,1}-{2491,2927,0,1,1}-{2497,2939,0,1,2}-{2648,9766,0,1,4}-{2653,9761,0,1,3}-{3164,3242,0,1,0}-{3169,3246,0,1,0}-{3170,3250,0,1,0}-{3166,3247,0,1,0}-{3164,3249,0,1,0}-{3157,3226,0,1,0}-{3163,3227,0,1,0}-{3165,3223,0,1,0}-{3194,3236,0,1,0}"
"loc_data": "{3182,3244,0,1,1}-{3250,3239,0,1,1}-{3241,3241,0,1,1}-{3082,3362,0,1,4}-{3146,3347,0,1,3}-{3249,3249,0,1,1}-{3102,9881,0,1,3}-{3095,9883,0,1,2}-{3218,9890,0,1,3}-{3220,9887,0,1,0}-{3218,9887,0,1,1}-{3218,9889,0,1,5}-{3213,9890,0,1,1}-{3162,3223,0,1,7}-{2461,2880,0,1,5}-{2489,2935,0,1,7}-{2492,2907,0,1,1}-{2496,2890,0,1,4}-{2487,2894,0,1,2}-{2487,2888,0,1,7}-{2483,2877,0,1,3}-{2481,2876,0,1,4}-{2457,2867,0,1,4}-{2481,2847,0,1,0}-{2475,2854,0,1,3}-{2482,2873,0,1,3}-{2485,2876,0,1,2}-{2449,2865,0,1,1}-{2478,2916,0,1,5}-{2485,2902,0,1,3}-{2487,2902,0,1,2}-{2489,2894,0,1,2}-{2490,2905,0,1,7}-{2490,2917,0,1,5}-{2484,2890,0,1,1}-{2503,2889,0,1,1}-{2491,2927,0,1,1}-{2497,2939,0,1,2}-{2648,9766,0,1,4}-{2653,9761,0,1,3}-{3164,3242,0,1,0}-{3169,3246,0,1,0}-{3170,3250,0,1,0}-{3166,3247,0,1,0}-{3164,3249,0,1,0}-{3157,3226,0,1,0}-{3163,3227,0,1,0}-{3165,3223,0,1,0}-{3194,3236,0,1,0}-{2602,9640,0,1,0}-{2603,9635,0,1,0}-{2603,9638,0,1,0}-{2605,9637,0,1,0}-{2605,9639,0,1,0}-{2606,9635,0,1,0}-2606,9646,0,1,0}-{2607,9637,0,1,0}-{2607,9641,0,1,0}-{2607,9644,0,1,0}-{2607,9648,0,1,0}-{2608,9635,0,1,0}-{2608,9642,0,1,0}-{2609,9639,0,1,0}-{2609,9643,0,1,0}"
},
{
"npc_id": "60",
@ -273,7 +273,7 @@
},
{
"npc_id": "88",
"loc_data": "{2601,9802,0,1,6}-{2594,9805,0,1,1}-{2587,9806,0,1,2}-{2585,9803,0,1,1}-{2584,9801,0,1,5}"
"loc_data": "{2601,9802,0,1,6}-{2594,9805,0,1,1}-{2587,9806,0,1,2}-{2585,9803,0,1,1}-{2584,9801,0,1,5}-{2573,9630,0,1,0}"
},
{
"npc_id": "89",
@ -321,15 +321,15 @@
},
{
"npc_id": "100",
"loc_data": "{2551,3408,0,1,6}-{2553,3405,0,1,3}-{2559,3452,0,1,3}-{2567,3440,0,1,3}"
"loc_data": "{2551,3408,0,1,6}-{2553,3405,0,1,3}-{2559,3452,0,1,3}-{2567,3440,0,1,3}-{2564,9653,0,1,0}-{2565,9655,0,1,0}-{2566,9626,0,1,0}-{2567,9653,0,1,0}-{2569,9633,0,1,0}-{2607,9621,0,1,0}"
},
{
"npc_id": "101",
"loc_data": "{2555,3407,0,1,3}-{2624,3391,0,1,1}-{2622,3389,0,1,4}-{2619,3390,0,1,4}-{2553,3457,0,1,3}-{2573,3437,0,1,3}"
"loc_data": "{2555,3407,0,1,3}-{2624,3391,0,1,1}-{2622,3389,0,1,4}-{2619,3390,0,1,4}-{2553,3457,0,1,3}-{2573,3437,0,1,3}-{2562,9659,0,1,0}-{2563,9661,0,1,0}-{2599,9626,0,1,0}-{2601,9627,0,1,0}-{2605,9621,0,1,0}-{2610,9620,0,1,0}"
},
{
"npc_id": "102",
"loc_data": "{2622,3390,0,1,7}-{2622,3390,0,1,7}"
"loc_data": "{2622,3390,0,1,7}-{2622,3390,0,1,7}-{2562,9657,0,1,0}-{2571,9653,0,1,0}"
},
{
"npc_id": "103",
@ -377,7 +377,7 @@
},
{
"npc_id": "115",
"loc_data": "{2587,9741,0,1,4}-{2585,9739,0,1,7}-{2582,9736,0,1,3}-{2589,9734,0,1,4}-{2582,9743,0,1,3}-{2576,9746,0,1,7}-{2579,9741,0,1,6}-{2540,3020,0,0,0}-{2555,2953,0,0,0}-{2583,2967,0,1,0}-{2572,3028,0,1,2}-{2550,3046,0,1,4}-{2572,3034,0,1,3}-{2576,3026,0,1,4}-{2534,2975,0,1,1}-{2518,2974,0,1,1}-{2573,2987,0,1,1}-{2592,2967,0,1,3}-{2589,2961,0,0,2}-{2575,2989,0,1,0}-{2574,2992,0,1,4}-{2521,2974,0,1,4}-{2500,3092,0,1,6}-{2524,3375,0,1,3}-{2524,3374,0,1,3}-{2529,3374,0,1,3}-{2532,3375,0,1,1}-{2532,3373,0,1,1}-{2527,3376,0,1,6}-{2525,3373,0,1,7}-{2525,3373,0,1,5}-{2511,3086,0,1,1}-{2511,3084,0,1,3}-{2503,3114,0,1,6}-{2509,3120,0,1,4}-{2506,3107,0,1,4}-{2500,3112,0,1,4}-{2521,3045,0,1,6}-{2517,3043,0,1,5}-{2500,3095,0,1,3}-{2497,3090,0,1,4}-{2502,3099,0,1,4}-{2504,3097,0,1,4}-{2503,3134,0,1,3}-{2554,3196,0,1,7}-{2519,3039,0,1,4}-{2722,9701,0,1,1}-{2720,9715,0,1,1}-{2721,9669,0,1,1}-{2722,9707,0,1,1}-{2723,9716,0,1,1}-{2717,9669,0,1,1}"
"loc_data": "{2587,9741,0,1,4}-{2585,9739,0,1,7}-{2582,9736,0,1,3}-{2589,9734,0,1,4}-{2582,9743,0,1,3}-{2576,9746,0,1,7}-{2579,9741,0,1,6}-{2540,3020,0,0,0}-{2555,2953,0,0,0}-{2583,2967,0,1,0}-{2572,3028,0,1,2}-{2550,3046,0,1,4}-{2572,3034,0,1,3}-{2576,3026,0,1,4}-{2534,2975,0,1,1}-{2518,2974,0,1,1}-{2573,2987,0,1,1}-{2592,2967,0,1,3}-{2589,2961,0,0,2}-{2575,2989,0,1,0}-{2574,2992,0,1,4}-{2521,2974,0,1,4}-{2500,3092,0,1,6}-{2524,3375,0,1,3}-{2524,3374,0,1,3}-{2529,3374,0,1,3}-{2532,3375,0,1,1}-{2532,3373,0,1,1}-{2527,3376,0,1,6}-{2525,3373,0,1,7}-{2525,3373,0,1,5}-{2511,3086,0,1,1}-{2511,3084,0,1,3}-{2503,3114,0,1,6}-{2509,3120,0,1,4}-{2506,3107,0,1,4}-{2500,3112,0,1,4}-{2521,3045,0,1,6}-{2517,3043,0,1,5}-{2500,3095,0,1,3}-{2497,3090,0,1,4}-{2502,3099,0,1,4}-{2504,3097,0,1,4}-{2503,3134,0,1,3}-{2554,3196,0,1,7}-{2519,3039,0,1,4}-{2722,9701,0,1,1}-{2720,9715,0,1,1}-{2721,9669,0,1,1}-{2722,9707,0,1,1}-{2723,9716,0,1,1}-{2717,9669,0,1,1}-{2585,9608,0,1,0}-{2586,9614,0,1,0}-{2588,9606,0,1,0}"
},
{
"npc_id": "116",
@ -401,7 +401,7 @@
},
{
"npc_id": "122",
"loc_data": "{2996,9574,0,1,6}-{3007,9579,0,1,7}-{3001,9580,0,1,4}-{3018,9580,0,1,3}-{3021,9585,0,1,4}-{3024,9582,0,1,4}-{2507,3726,0,1,2}-{2523,3724,0,1,3}-{2535,9556,0,1,4}"
"loc_data": "{2996,9574,0,1,6}-{3007,9579,0,1,7}-{3001,9580,0,1,4}-{3018,9580,0,1,3}-{3021,9585,0,1,4}-{3024,9582,0,1,4}-{2507,3726,0,1,2}-{2523,3724,0,1,3}-{2535,9556,0,1,4}-{2566,9632,0,1,0}-{2573,9626,0,1,0}"
},
{
"npc_id": "123",
@ -627,6 +627,14 @@
"npc_id": "222",
"loc_data": "{2851,3351,0,0,7}-{2849,3348,0,0,7}"
},
{
"npc_id": "223",
"loc_data": "{2569,3250,0,1,0}"
},
{
"npc_id": "224",
"loc_data": "{2579,9655,0,1,0}-{2581,9656,0,1,0}-{2581,9659,0,1,0}-{2583,9659,0,1,0}-{2584,9656,0,1,0}-{2586,9659,0,1,0}-{2587,9656,0,1,0}-{2589,9654,0,1,0}-{2589,9658,0,1,0}-{2591,9656,0,1,0}-{2591,9659,0,1,0}"
},
{
"npc_id": "225",
"loc_data": "{2641,3437,0,0,0}"
@ -11203,14 +11211,6 @@
"npc_id": "3322",
"loc_data": "{2384,4439,0,1,0}"
},
{
"npc_id": "223",
"loc_data": "{2569,3250,0,1,0}"
},
{
"npc_id": "224",
"loc_data": "{2582,9656,0,1,0}-{2589,9657,0,1,0}-{2587,9658,0,1,0}-{2584,9657,0,1,0}-{2585,9656,0,1,0}-{2582,9658,0,1,0}-{2585,9653,0,1,0}-{2590,9658,0,1,0}-{2590,9655,0,1,0}"
},
{
"npc_id": "1080",
"loc_data": "{2900,3567,1,1,0}"

View file

@ -0,0 +1,29 @@
package content.region.kandarin.ardougne.dialogue
import content.region.kandarin.ardougne.quest.clocktower.BrotherKojoDialogueFile
import core.api.*
import core.game.dialogue.DialoguePlugin
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
/**
* Brother Kojo main dialogue.
* @author ovenbread
*/
@Initializable
class BrotherKojoDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
// Fallback to default. Always the start of Clocktower quest
openDialogue(player!!, BrotherKojoDialogueFile(), npc)
return true
}
override fun newInstance(player: Player?): DialoguePlugin {
return BrotherKojoDialogue(player)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.BROTHER_KOJO_223)
}
}

View file

@ -0,0 +1,108 @@
package content.region.kandarin.ardougne.quest.clocktower
import core.api.*
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.dialogue.Topic
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
class BrotherKojoDialogueFile : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
if (getAttribute(player!!, ClockTower.attributeAskKojoAboutRats, false) && !getAttribute(player!!, ClockTower.attributeRatsPoisoned, false)) {
when (stage) {
START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "I've found the white cog! But it's locked behind a gate. There's rats everywhere!").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "Rats again?! Kill them! Kill them all!").also { stage++ }
2 -> playerl(FacialExpression.FRIENDLY, "But how do I open the gate? Do you have a key?").also { stage++ }
3 -> npcl(FacialExpression.FRIENDLY, "Get rid of the rats! I'm sure I left some rat poison down there!").also { stage++ }
4 -> playerl(FacialExpression.FRIENDLY, "I guess I better go and deal with the rat problem...").also {
stage = END_DIALOGUE
}
}
return
}
when (getQuestStage(player!!, ClockTower.questName)) {
0 -> {
when (stage) {
START_DIALOGUE -> player(FacialExpression.FRIENDLY, "Hello monk.").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "Hello adventurer. My name is Brother Kojo. Do you happen to know the time?").also { stage++ }
2 -> player(FacialExpression.SAD, "No, sorry, I don't.").also { stage++ }
3 -> npcl(FacialExpression.NEUTRAL, "Exactly! This clock tower has recently broken down, and without it nobody can tell the correct time. I must fix it before the town people become too angry!").also { stage++ }
4 -> npcl(FacialExpression.ASKING, "I don't suppose you could assist me in the repairs? I'll pay you for your help.").also { stage++ }
5 -> showTopics(
Topic(FacialExpression.FRIENDLY, "Ok old monk, what can I do?", 30),
Topic(FacialExpression.ASKING, "So... how much reward are we talking then?", 10),
Topic(FacialExpression.FRIENDLY, "Not now old monk.", 20),
)
10 -> npcl(FacialExpression.STRUGGLE, "Well, I'm only a monk so I'm not exactly rich, but I assure you I will give you a fair reward for the time spent assisting me in repairing the clock.").also { stage = 4 }
20 -> npcl(FacialExpression.FRIENDLY, "OK then. Come back and let me know if you change your mind.").also { stage = END_DIALOGUE }
30 -> npc(FacialExpression.HAPPY, "Oh, thank you kind ${if (player!!.isMale) "sir" else "madam"}!",
"In the cellar below, you'll find four cogs.",
"They're too heavy for me, but you should be able to",
"carry them one at a time.").also { stage++ }
31 -> npcl(FacialExpression.THINKING, "I know one goes on each floor... but I can't exactly remember which goes where specifically. Oh well, I'm sure you can figure it out fairly easily.").also { stage++ }
32 -> player(FacialExpression.FRIENDLY, "Well, I'll do my best.").also { stage++ }
33 -> npcl(FacialExpression.HAPPY, "Thank you again! And remember to be careful, the cellar is full of strange beasts!").also {
stage = END_DIALOGUE
setQuestStage(player!!, ClockTower.questName, 1)
}
}
}
1 -> {
when (stage) {
START_DIALOGUE -> npcl(FacialExpression.ASKING, "Oh hello, are you having trouble? The cogs are in four rooms below us. Place one cog on a pole on each of the four tower levels.").also { stage++ }
1 -> showTopics(
Topic(FacialExpression.FRIENDLY, "Can I have a hint?", 2),
Topic(FacialExpression.ASKING, "I'll carry on looking.", END_DIALOGUE),
)
2 -> showTopics(
Topic(FacialExpression.FRIENDLY, "Have you any idea where I might find the red cog?", 3),
Topic(FacialExpression.FRIENDLY, "Have you any idea where I might find the blue cog?", 3),
Topic(FacialExpression.FRIENDLY, "Have you any idea where I might find the black cog?", 3),
Topic(FacialExpression.FRIENDLY, "Have you any idea where I might find the white cog?", 3),
)
3 -> npcl(FacialExpression.FRIENDLY, "If I knew, I wouldn't ask you to find it. It's in the basement somewhere.").also { stage = 1 }
}
}
2 -> {
when (stage) {
START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "I've placed a cog!").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "That's great. Come see me when you've done the other three.").also { stage = END_DIALOGUE }
}
}
3 -> {
when (stage) {
START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "Two down!").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "Two to go.").also { stage = END_DIALOGUE }
}
}
4 -> {
when (stage) {
START_DIALOGUE -> npcl(FacialExpression.FRIENDLY, "One left.").also { stage = END_DIALOGUE }
}
}
in 5 .. 10 -> {
when (stage) {
START_DIALOGUE -> playerl(FacialExpression.FRIENDLY, "I have replaced all the cogs!").also { stage++ }
1 -> npcl(FacialExpression.FRIENDLY, "Really..? Wait, listen! Well done, well done! Yes yes yes, you've done it! You ARE clever!").also { stage++ }
2 -> npcl(FacialExpression.FRIENDLY, "The townsfolk will all be able to know the correct time now! Thank you so much for all of your help! And as promised, here is your reward!").also { stage++ }
3 -> {
end()
finishQuest(player!!, ClockTower.questName)
}
}
}
100 -> {
when (stage) {
START_DIALOGUE -> npcl(FacialExpression.FRIENDLY, "Oh hello there traveller. You've done a grand job with the clock. It's just like new.").also { stage = END_DIALOGUE }
}
}
}
}
}

View file

@ -0,0 +1,74 @@
package content.region.kandarin.ardougne.quest.clocktower
import core.api.addItemOrDrop
import core.api.getAttribute
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.quest.Quest
import core.plugin.Initializable
import org.rs09.consts.Items
/**
* https://www.youtube.com/watch?v=Cl68Z0bsRq4
*/
@Initializable
class ClockTower : Quest("Clock Tower",38, 37, 1, 10, 0, 1, 8) {
companion object {
const val questName = "Clock Tower"
const val attributeBlueCog = "/save:quest:clocktower-bluecogplaced"
const val attributeBlackCog = "/save:quest:clocktower-blackcogplaced"
const val attributeWhiteCog = "/save:quest:clocktower-whitecogplaced"
const val attributeRedCog = "/save:quest:clocktower-redcogplaced"
const val attributeBlackCogCooled = "/save:quest:clocktower-blackcogcooled"
const val attributeRatsPoisoned = "/save:quest:clocktower-poisonplaced"
const val attributeAskKojoAboutRats = "quest:clocktower-askkojoaboutrats"
}
override fun drawJournal(player: Player?, stage: Int) {
super.drawJournal(player, stage)
var line = 12
var stage = getStage(player)
when (stage) {
0 -> {
line(player, "I can start this quest by speaking to !!Brother Kojo?? at the", line++)
line(player, "!!Clock Tower?? which is located !!South?? of !!Ardougne??", line++)
}
in 1 .. 10 -> {
line(player, "I spoke to Brother Kojo at the Clock Tower South of", line++, true)
line(player, "Ardougne and agreed to help him repair the clock.", line++, true)
line(player,"To repair the clock I need to find the four coloured cogs", line++, false)
line(player,"and place them on the four correctly coloured spindles.", line++, false)
line(player, if (getAttribute(player!!, attributeBlueCog, false)) "I placed the !!Blue Cog?? on it's !!spindle??." else "I haven't placed the !!Blue Cog?? on it's !!spindle?? yet.", line++, getAttribute(player!!, attributeBlueCog, false))
line(player, if (getAttribute(player!!, attributeBlackCog, false)) "I placed the !!Black Cog?? on it's !!spindle??." else "I haven't placed the !!Black Cog?? on it's !!spindle?? yet.", line++, getAttribute(player!!, attributeBlackCog, false))
line(player, if (getAttribute(player!!, attributeWhiteCog, false)) "I placed the !!White Cog?? on it's !!spindle??." else "I haven't placed the !!White Cog?? on it's !!spindle?? yet.", line++, getAttribute(player!!, attributeWhiteCog, false))
line(player, if (getAttribute(player!!, attributeRedCog, false)) "I placed the !!Red Cog?? on it's !!spindle??." else "I haven't placed the !!Red Cog?? on it's !!spindle?? yet.", line++, getAttribute(player!!, attributeRedCog, false))
}
100 -> {
line(player, "I spoke to Brother Kojo at the Clock Tower South of", line++, true)
line(player, "I have placed all four cogs successfully on the spindles.", line++, true)
line(player,"Brother Kojo was grateful for all my help and rewarded me.", line++, true)
line++
line(player,"<col=FF0000>QUEST COMPLETE!</col>", line)
}
}
}
override fun finish(player: Player) {
var ln = 10
super.finish(player)
player.packetDispatch.sendString("You have completed the Clock Tower Quest!", 277, 4)
player.packetDispatch.sendItemZoomOnInterface(Items.COINS_995, 240, 277, 5)
drawReward(player,"1 Quest Point", ln++)
drawReward(player,"500 coins", ln++)
addItemOrDrop(player, Items.COINS_995, 500)
}
override fun newInstance(`object`: Any?): Quest {
return this
}
}

View file

@ -0,0 +1,277 @@
package content.region.kandarin.ardougne.quest.clocktower
import core.api.*
import core.game.global.action.DoorActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.item.GroundItem
import core.game.node.item.Item
import core.game.world.map.Direction
import core.game.world.map.Location
import core.game.world.map.path.Pathfinder
import core.game.world.update.flag.context.Animation
import org.rs09.consts.Items
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
class ClockTowerListener : InteractionListener {
companion object {
val DOWN_ANIMATION = Animation(2140)
val UP_ANIMATION = Animation(2139)
}
override fun defineListeners() {
onUseWith(IntType.SCENERY, intArrayOf(Items.WHITE_COG_20, Items.BLACK_COG_21, Items.BLUE_COG_22, Items.RED_COG_23), Scenery.CLOCK_SPINDLE_25) { player, _, _ ->
sendMessage(player, "The cog doesn't seem to fit.")
return@onUseWith true
}
onUseWith(IntType.SCENERY, intArrayOf(Items.WHITE_COG_20, Items.BLACK_COG_21, Items.BLUE_COG_22, Items.RED_COG_23), Scenery.CLOCK_SPINDLE_26) { player, _, _ ->
sendMessage(player, "The cog doesn't seem to fit.")
return@onUseWith true
}
onUseWith(IntType.SCENERY, intArrayOf(Items.WHITE_COG_20, Items.BLACK_COG_21, Items.BLUE_COG_22, Items.RED_COG_23), Scenery.CLOCK_SPINDLE_27) { player, _, _ ->
sendMessage(player, "The cog doesn't seem to fit.")
return@onUseWith true
}
onUseWith(IntType.SCENERY, intArrayOf(Items.WHITE_COG_20, Items.BLACK_COG_21, Items.BLUE_COG_22, Items.RED_COG_23), Scenery.CLOCK_SPINDLE_28) { player, _, _ ->
sendMessage(player, "The cog doesn't seem to fit.")
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.WHITE_COG_20, Scenery.CLOCK_SPINDLE_31) { player, _, _ ->
if (!getAttribute(player, ClockTower.attributeWhiteCog, false)) {
if (removeItem(player, Items.WHITE_COG_20)) {
sendMessage(player, "The cog fits perfectly.")
setAttribute(player, ClockTower.attributeWhiteCog, true)
if (!isQuestComplete(player, ClockTower.questName)) {
setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1)
}
}
} else {
sendMessage(player, "The cog has already been placed.")
}
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.BLACK_COG_21, Scenery.CLOCK_SPINDLE_30) { player, _, _ ->
if (!getAttribute(player, ClockTower.attributeBlackCog, false)) {
if (removeItem(player, Items.BLACK_COG_21)) {
sendMessage(player, "The cog fits perfectly.")
setAttribute(player, ClockTower.attributeBlackCog, true)
if (!isQuestComplete(player, ClockTower.questName)) {
setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1)
}
}
} else {
sendMessage(player, "The cog has already been placed.")
}
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.BLUE_COG_22, Scenery.CLOCK_SPINDLE_32) { player, _, _ ->
if (!getAttribute(player, ClockTower.attributeBlueCog, false)) {
if (removeItem(player, Items.BLUE_COG_22)) {
sendMessage(player, "The cog fits perfectly.")
setAttribute(player, ClockTower.attributeBlueCog, true)
if (!isQuestComplete(player, ClockTower.questName)) {
setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1)
}
}
} else {
sendMessage(player, "The cog has already been placed.")
}
return@onUseWith true
}
onUseWith(IntType.SCENERY, Items.RED_COG_23, Scenery.CLOCK_SPINDLE_29) { player, _, _ ->
if (!getAttribute(player, ClockTower.attributeRedCog, false)) {
if (removeItem(player, Items.RED_COG_23)) {
sendMessage(player, "The cog fits perfectly.")
setAttribute(player, ClockTower.attributeRedCog, true)
if (!isQuestComplete(player, ClockTower.questName)) {
setQuestStage(player, ClockTower.questName, getQuestStage(player, ClockTower.questName) + 1)
}
}
} else {
sendMessage(player, "The cog has already been placed.")
}
return@onUseWith true
}
// The lever to the rats
val levers = intArrayOf(Scenery.LEVER_33, Scenery.LEVER_34)
on(levers, IntType.SCENERY, "pull") { player, node ->
val leverScenery = node.asScenery()
// This one opens the first and only gate
if (leverScenery.location.equals(2591, 9661, 0)) {
if (leverScenery.id == Scenery.LEVER_33) {
val metalGate = getScenery(2595, 9657, 0)!!
val location = metalGate.location.transform(1, 0, 0)
face(player, Location.create(2591, 9660, 0))
animate(player, UP_ANIMATION)
replaceScenery(metalGate, Scenery.GATE_37, -1, Direction.WEST, location)
replaceScenery(leverScenery, Scenery.LEVER_34, -1)
} else if (leverScenery.id == Scenery.LEVER_34) {
val metalGateOpen = getScenery(2596, 9657, 0)!!
val location = metalGateOpen.location.transform(-1, 0, 0)
face(player, Location.create(2591, 9660, 0))
animate(player, DOWN_ANIMATION)
replaceScenery(metalGateOpen, Scenery.GATE_37, -1, Direction.SOUTH, location)
replaceScenery(leverScenery, Scenery.LEVER_33, -1)
}
}
if (leverScenery.location.equals(2593, 9661, 0)) {
// This one doesn't do anything https://www.youtube.com/watch?v=2FXiYftAX9A
// The second gate is fixed and is not a Scenery
if (leverScenery.id == Scenery.LEVER_34) {
face(player, Location.create(2593, 9660, 0))
animate(player, DOWN_ANIMATION)
replaceScenery(leverScenery, Scenery.LEVER_33, -1)
} else if (leverScenery.id == Scenery.LEVER_33) {
face(player, Location.create(2593, 9660, 0))
animate(player, UP_ANIMATION)
replaceScenery(leverScenery, Scenery.LEVER_34, -1)
}
}
return@on true
}
// The gate to the rats
on(Scenery.GATE_37, IntType.SCENERY, "open") { player, _ ->
sendMessage(player, "The door doesn't seem to open from here...")
return@on true
}
// Poison the rats
onUseWith(IntType.SCENERY, Items.RAT_POISON_24, Scenery.FOOD_TROUGH_40) { player, _, _ ->
if (getAttribute(player, ClockTower.attributeRatsPoisoned, false)) {
sendDialogue(player, "The gate has already been damaged, you see no reason to cause more suffering.")
return@onUseWith true
}
if (removeItem(player, Items.RAT_POISON_24)) {
val loc = location(2579, 9656, 0) // Location of the gate
sendMessage(player, "The rats swarm towards the poisoned food...")
sendMessage(player, "... and devour it hungrily.")
sendMessage(player, "You see them smashing against the gates in a panic.")
sendMessage(player, "They seem to be dying.")
setAttribute(player, ClockTower.attributeRatsPoisoned, true)
runTask(player, 1) {
val rats = findLocalNPCs(player, intArrayOf(NPCs.DUNGEON_RAT_224))
rats.forEach { rat ->
if (rat.location.withinDistance(loc, 20)) {
var xDeath = 0
var yDeath = -1
for (rat in rats) {
Pathfinder.find(rat.location, location(loc.x + xDeath, loc.y + yDeath, loc.z), true, Pathfinder.SMART).walk(rat)
xDeath++
if (xDeath == 4) {
xDeath = 0
yDeath++
}
}
runTask(rat, 15) {
rat.startDeath(null)
}
}
}
}
}
return@onUseWith true
}
// Gate to White Cog (after rats die)
on(Scenery.GATE_39, IntType.SCENERY, "go-through") { player, node ->
if (getAttribute(player, ClockTower.attributeRatsPoisoned, false)) {
sendDialogueLines(player, "The death throws of the rats seem to have shaken the door loose of", "its hinges. You pick it up and go through.")
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
} else {
sendPlayerDialogue(player, "It won't open. Maybe the monk knows how to open this door?")
setAttribute(player, ClockTower.attributeAskKojoAboutRats, true)
}
return@on true
}
// Wall to Blue Cog
on(Scenery.WALL_1586, IntType.SCENERY, "push") { player, node ->
DoorActionHandler.handleAutowalkDoor(player, node.asScenery())
return@on true
}
on(Items.WHITE_COG_20, IntType.GROUNDITEM, "take") { player, groundItem ->
if (inInventory(player, Items.WHITE_COG_20) || inInventory(player, Items.BLACK_COG_21) || inInventory(player, Items.BLUE_COG_22) || inInventory(player, Items.RED_COG_23)) {
sendDialogue(player, "The cogs are too heavy to carry more than one at a time.")
} else if (hasSpaceFor(player, Item(Items.WHITE_COG_20))) {
addItem(player, Items.WHITE_COG_20)
removeGroundItem(groundItem as GroundItem)
}
return@on true
}
onUseWith(IntType.GROUNDITEM, Items.BUCKET_OF_WATER_1929, Items.BLACK_COG_21) { player, _, _ ->
if (removeItem(player, Items.BUCKET_OF_WATER_1929)) {
addItem(player, Items.BUCKET_1925)
sendDialogue(player, "You pour water over the cog. It quickly cools down enough to take.")
setAttribute(player, ClockTower.attributeBlackCogCooled, true)
}
return@onUseWith true
}
on(Items.BLACK_COG_21, IntType.GROUNDITEM, "take") { player, groundItem ->
if (inInventory(player, Items.WHITE_COG_20) || inInventory(player, Items.BLACK_COG_21) || inInventory(player, Items.BLUE_COG_22) || inInventory(player, Items.RED_COG_23)) {
sendDialogue(player, "The cogs are too heavy to carry more than one at a time.")
return@on true
}
if (hasSpaceFor(player, Item(Items.BLACK_COG_21)) && getAttribute(player, ClockTower.attributeBlackCogCooled, false)) {
addItem(player, Items.BLACK_COG_21)
removeGroundItem(groundItem as GroundItem)
return@on true
}
if (!inInventory(player, Items.BUCKET_OF_WATER_1929, 1) && !inEquipment(player, Items.ICE_GLOVES_1580)) {
sendDialogue(player, "The cog is red hot from the flames. You cannot pick it up.")
return@on true
}
if (hasSpaceFor(player, Item(Items.BLACK_COG_21)) && (inInventory(player, Items.BUCKET_OF_WATER_1929, 1) || inEquipment(player, Items.ICE_GLOVES_1580)) && !getAttribute(player, ClockTower.attributeBlackCogCooled, false)) {
// Picking up the Black Cog requires dousing it in water or using ice gloves
if (!inEquipment(player, Items.ICE_GLOVES_1580) && removeItem(player, Items.BUCKET_OF_WATER_1929)) {
sendDialogue(player, "You pour water over the cog. It quickly cools down enough to take.")
addItem(player, Items.BUCKET_1925)
addItem(player, Items.BLACK_COG_21)
setAttribute(player, ClockTower.attributeBlackCogCooled, true)
removeGroundItem(groundItem as GroundItem)
} else if (inEquipment(player, Items.ICE_GLOVES_1580) && !inInventory(player, Items.BUCKET_OF_WATER_1929)) {
sendDialogue(player, "You grab the cog with your ice gloves. It quickly cools down enough to take.")
setAttribute(player, ClockTower.attributeBlackCogCooled, true)
removeGroundItem(groundItem as GroundItem)
addItem(player, Items.BLACK_COG_21)
}
}
return@on true
}
on(Items.BLUE_COG_22, IntType.GROUNDITEM, "take") { player, groundItem ->
if (inInventory(player, Items.WHITE_COG_20) || inInventory(player, Items.BLACK_COG_21) || inInventory(player, Items.BLUE_COG_22) || inInventory(player, Items.RED_COG_23)) {
sendDialogue(player, "The cogs are too heavy to carry more than one at a time.")
} else if (hasSpaceFor(player, Item(Items.BLUE_COG_22))) {
addItem(player, Items.BLUE_COG_22)
removeGroundItem(groundItem as GroundItem)
}
return@on true
}
on(Items.RED_COG_23, IntType.GROUNDITEM, "take") { player, groundItem ->
if (inInventory(player, Items.WHITE_COG_20) || inInventory(player, Items.BLACK_COG_21) || inInventory(player, Items.BLUE_COG_22) || inInventory(player, Items.RED_COG_23)) {
sendDialogue(player, "The cogs are too heavy to carry more than one at a time.")
} else if (hasSpaceFor(player, Item(Items.RED_COG_23))) {
addItem(player, Items.RED_COG_23)
removeGroundItem(groundItem as GroundItem)
}
return@on true
}
}
}

View file

@ -31,6 +31,8 @@ public enum SpecialLadders implements LadderAchievementCheck {
ALKHARID_SOCRCERESS_UP(Location.create(3325,3142,0),Location.create(3325,3139,1)),
ALKHARID_SOCRCERESS_DOWN(Location.create(3325,3139,1),Location.create(3325,3143,0)),
CLOCKTOWER_HIDDEN_LADDER(Location.create(2572,9631,0),Location.create(2572,3230,0)),
DRAYNOR_SEWER_SOUTHEAST_DOWN(new Location(3118, 3244, 0), new Location(3118, 9643, 0)),
DRAYNOR_SEWER_SOUTHEAST_UP(new Location(3118, 9643, 0), new Location(3118, 3243, 0)),
DRAYNOR_SEWER_NORTHWEST_DOWN(new Location(3084, 3272, 0), new Location(3085, 9672, 0)),