diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3f98870017..f18a0bf19b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,6 +13,9 @@ ] } }, + "containerEnv": { + "SHELL": "/bin/bash" + }, "remoteUser": "vscode", "postStartCommand": "bash -c 'chmod +x setup.sh && ./setup.sh'" } diff --git a/.env.example b/.env.example index cd5356fd29..f8894b537c 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,9 @@ # WEB_PORT=80 # WEB_CORS=false +## management server +# WEB_MANAGEMENT_PORT=8898 + ## game server # NODE_ID=10 # NODE_PORT=43594 @@ -14,7 +17,7 @@ # NODE_KILLTIMER=50 # NODE_ALLOW_CHEATS=true # NODE_DEBUG=true -# NODE_DEBUG_PROFILER=false +# NODE_DEBUG_PROFILE=false # NODE_STAFF=pazaz # NODE_CLIENT_ROUTEFINDER=true # NODE_SOCKET_TIMEOUT=true diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 94ed4b9a4c..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,6 +0,0 @@ -data/* -prisma/* -public/* -ref/* -view/* -src/3rdparty/* diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index d7adf8a949..0000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,101 +0,0 @@ -/** - * TODO: Use flat config file as eslintrc is deprecated. - * https://eslint.org/docs/latest/use/configure/configuration-files - */ -module.exports = { - env: { - browser: true, - es2021: true, - node: true, - }, - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], - overrides: [ - { - env: { - node: true, - }, - files: ['.eslintrc.{js,cjs}'], - parserOptions: { - sourceType: 'script' - } - }, - { - files: ['src/**/*.test.ts'], - extends: ['plugin:vitest/legacy-recommended'], - plugins: ['vitest'], - rules: { - 'vitest/no-focused-tests': 'error', - 'vitest/no-disabled-tests': 'warn', - 'vitest/consistent-test-it': 'warn', - 'vitest/require-top-level-describe': [ - 'error', - { - 'maxNumberOfTopLevelDescribes': 1 - } - ] - } - } - ], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module' - }, - plugins: ['@typescript-eslint', 'unused-imports'], - rules: { - indent: ['error', 4, { SwitchCase: 1 }], - quotes: ['error', 'single', { avoidEscape: true }], - semi: ['error', 'always'], - - /** - * https://eslint.org/docs/latest/rules/no-constant-condition#checkloops - * - * Allows constant conditions in loops but not in if statements - */ - 'no-constant-condition': ['error', { checkLoops: false }], - - /** - * (jkm) this rule is included in the default ruleset, we should consider - * resolving the issues and setting it to error - * https://eslint.org/docs/latest/rules/no-case-declarations - */ - 'no-case-declarations': 'warn', - - /** - * (jkm) - * The following rules are included in @typescript-eslint/recommended - * I have set them to warn instead of error, to avoid having to fix them - * We should consider fixing them and setting them to error - */ - '@typescript-eslint/no-namespace': 'warn', - '@typescript-eslint/no-explicit-any': 'warn', - - /** - * https://eslint.org/docs/latest/rules/no-unused-vars - */ - '@typescript-eslint/no-unused-vars': [ - // TODO: Set to error - 'warn', - { - /** - * Allow variables prefixed with underscores to skip this rule. - * There aren't many good reasons to have unused variables, - * but the codebase has 100s of them. - */ - 'vars': 'all', - 'varsIgnorePattern': '^_', - /** - * Allow parameters prefixed with underscores to skip this rule. - * This is a common practice for router methods with req and res parameters. - */ - 'args': 'all', - 'argsIgnorePattern': '^_', - } - ], - - /** - * https://github.com/sweepline/eslint-plugin-unused-imports - */ - 'unused-imports/no-unused-imports': 'error', - } -}; diff --git a/data/src/maps/m42_153.jm2 b/data/src/maps/m42_153.jm2 index 138288d0db..58613783a8 100644 --- a/data/src/maps/m42_153.jm2 +++ b/data/src/maps/m42_153.jm2 @@ -7667,7 +7667,7 @@ 0 30 24: 1623 1 0 30 30: 995 1 0 32 23: 995 1 -0 33 24: 995 1 0 33 26: 995 3 0 33 27: 995 1 0 33 29: 995 7 +0 34 24: 995 1 diff --git a/data/src/maps/m43_51.jm2 b/data/src/maps/m43_51.jm2 index 540975818c..49598e429a 100644 --- a/data/src/maps/m43_51.jm2 +++ b/data/src/maps/m43_51.jm2 @@ -6367,5 +6367,5 @@ ==== OBJ ==== 0 10 22: 1469 1 -0 13 14: 1469 1 +0 13 25: 1469 1 0 32 25: 1467 1 diff --git a/data/src/pack/loc.pack b/data/src/pack/loc.pack index 0802b76450..7082e6fc38 100644 --- a/data/src/pack/loc.pack +++ b/data/src/pack/loc.pack @@ -649,7 +649,7 @@ 648=loc_648 649=loc_649 650=loc_650 -651=loc_651 +651=digsite_buried_skeleton 652=loc_652 653=loc_653 654=loc_654 @@ -2348,32 +2348,32 @@ 2347=loc_2347 2348=loc_2348 2349=loc_2349 -2350=loc_2350 -2351=loc_2351 -2352=loc_2352 -2353=loc_2353 -2354=loc_2354 +2350=digsite_winch +2351=digsite_private_dig_winch +2352=digsite_private_dig_exit_rope +2353=digsite_blocked_altar_exit_rope +2354=digsite_sacks_empty 2355=loc_2355 -2356=loc_2356 -2357=loc_2357 -2358=loc_2358 -2359=loc_2359 -2360=loc_2360 -2361=loc_2361 -2362=loc_2362 -2363=loc_2363 +2356=digsite_sacks_specimen_jars +2357=digsite_bush_empty +2358=digsite_bush_rock_sample +2359=digsite_sealed_barrel +2360=digsite_chest_open +2361=digsite_chest +2362=digsite_blocked_altar_brick +2363=digsite_panning_point 2364=loc_2364 2365=loc_2365 -2366=loc_2366 -2367=loc_2367 -2368=loc_2368 -2369=loc_2369 -2370=loc_2370 +2366=digsite_signpost_training_site +2367=digsite_signpost_level_1_site +2368=digsite_signpost_level_2_site +2369=digsite_signpost_level_3_site +2370=digsite_signpost_private_site 2371=loc_2371 -2372=loc_2372 -2373=loc_2373 -2374=loc_2374 -2375=loc_2375 +2372=exam_centre_bookcase_chemicals +2373=exam_centre_cupboard_rock_pick +2374=exam_centre_cupboard_rock_pick_open +2375=specimen_tray 2376=loc_2376 2377=loc_2377 2378=loc_2378 @@ -2419,19 +2419,19 @@ 2418=loc_2418 2419=loc_2419 2420=loc_2420 -2421=loc_2421 -2422=loc_2422 -2423=loc_2423 -2424=loc_2424 -2425=loc_2425 -2426=loc_2426 -2427=loc_2427 -2428=loc_2428 -2429=loc_2429 -2430=loc_2430 -2431=loc_2431 -2432=loc_2432 -2433=loc_2433 +2421=witchaven_north_lever_down +2422=witchaven_north_lever_up +2423=witchaven_south_lever_down +2424=witchaven_south_lever_up +2425=witchaven_north_room_lever_down +2426=witchaven_north_room_lever_up +2427=witchaven_south_west_door +2428=witchaven_door_open +2429=witchaven_south_east_door +2430=witchaven_goldmine_door +2431=witchaven_north_door +2432=edgeville_dungeon_chronozon_gate_west +2433=edgeville_dungeon_chronozon_gate_east 2434=loc_2434 2435=loc_2435 2436=loc_2436 diff --git a/data/src/pack/npc.pack b/data/src/pack/npc.pack index 3b024c013a..68f0c9620d 100644 --- a/data/src/pack/npc.pack +++ b/data/src/pack/npc.pack @@ -105,9 +105,9 @@ 104=ghost_draynor_manor 105=bear_brown 106=bear_black -107=npc_107 -108=npc_108 -109=npc_109 +107=scorpion +108=poison_scorpion +109=pit_scorpion 110=fire_giant 111=ice_giant 112=moss_giant @@ -173,7 +173,7 @@ 172=dark_wizard_earth 173=npc_173 174=dark_wizard_water -175=npc_175 +175=mugger 176=npc_176 177=npc_177 178=black_knight @@ -435,7 +435,7 @@ 434=macro_event_watchman4 435=macro_event_watchman5 436=macro_event_watchman6 -437=npc_437 +437=brownimp 438=macro_event_dryad1 439=macro_event_dryad2 440=macro_event_dryad3 @@ -975,15 +975,15 @@ 974=npc_974 975=npc_975 976=npc_976 -977=npc_977 -978=npc_978 -979=npc_979 -980=npc_980 -981=npc_981 -982=npc_982 -983=npc_983 -984=npc_984 -985=npc_985 +977=blessed_spider +978=blessed_giant_rat +979=slave1_upass +980=slave2_upass +981=slave3_upass +982=slave4_upass +983=slave5_upass +984=slave6_upass +985=slave7_upass 986=boulder_upass 987=unicorn_upass 988=sir_jerro diff --git a/data/src/pack/obj.pack b/data/src/pack/obj.pack index 4a71a1d546..d08ca03713 100644 --- a/data/src/pack/obj.pack +++ b/data/src/pack/obj.pack @@ -669,47 +669,47 @@ 668=blurite_ore 669=specimen_jar 670=specimen_brush -671=obj_671 -672=obj_672 -673=obj_673 -674=obj_674 +671=rock_sample_1 +672=rock_sample_2 +673=rock_sample_3 +674=cracked_rock_sample 675=rock_pick 676=trowel -677=obj_677 -678=obj_678 -679=obj_679 -680=obj_680 +677=panning_tray_empty +678=panning_tray_gold +679=panning_tray_mud +680=nuggets 681=talisman_of_zaros -682=obj_682 -683=obj_683 -684=obj_684 +682=unstamped_letter +683=stamped_letter +684=belt_buckle 685=old_boot 686=rusty_sword 687=broken_arrow 688=buttons 689=broken_staff 690=broken_glass -691=obj_691 -692=obj_692 -693=obj_693 -694=obj_694 +691=level_1_certificate +692=level_2_certificate +693=level_3_certificate +694=ceramic_remains 695=old_tooth -696=obj_696 +696=invitation_letter 697=damaged_armour -698=obj_698 -699=obj_699 -700=obj_700 -701=obj_701 -702=obj_702 -703=obj_703 -704=obj_704 -705=obj_705 -706=obj_706 -707=obj_707 +698=broken_armour +699=stone_tablet +700=chemical_powder +701=ammonium_nitrate +702=unidentified_liquid +703=nitroglycerin +704=ground_charcoal +705=mixed_chemicals1 +706=mixed_chemicals2 +707=chemical_compound 708=arcenia_root -709=obj_709 -710=obj_710 -711=obj_711 +709=digsite_chest_key +710=digsite_vase +711=book_on_chemicals 712=obj_712 713=obj_713 714=obj_714 @@ -771,16 +771,16 @@ 770=cert_arravcert_scroll 771=dramenbranch 772=dramenstaff -773=obj_773 -774=obj_774 +773=perfect_ring +774=perfect_necklace 775=gauntlets_of_cooking 776=gauntlets_of_goldsmithing -777=obj_777 -778=obj_778 -779=obj_779 -780=obj_780 -781=obj_781 -782=obj_782 +777=gauntlets_of_chaos +778=steel_gauntlets +779=crest_part_1 +780=crest_part_2 +781=crest_part_3 +782=family_crest 783=bark_sample 784=translation_book 785=gloughs_journal @@ -2363,7 +2363,7 @@ 2362=cert_adamantite_bar 2363=runite_bar 2364=cert_runite_bar -2365=obj_2365 +2365=perfect_gold_bar 2366=shield_left_half 2367=cert_shield_left_half 2368=shield_right_half diff --git a/data/src/pack/seq.pack b/data/src/pack/seq.pack index 7c7c83afb9..c19ca7a631 100644 --- a/data/src/pack/seq.pack +++ b/data/src/pack/seq.pack @@ -171,9 +171,9 @@ 170=imp_block 171=imp_ready 172=imp_death -173=imp_seq_173 -174=imp_seq_174 -175=imp_seq_175 +173=brownimp_grab +174=brownimp_appear +175=brownimp_disappear 176=lizardman_walk 177=lizardman_attack 178=lizardman_block @@ -403,7 +403,7 @@ 402=seq_402 403=human_blunt_defend1 404=human_blunt_defend2 -405=human_spear_lunge +405=seq_405 406=human_2h_crush 407=human_2h_slash 408=human_dspear_lunge diff --git a/data/src/pack/varp.pack b/data/src/pack/varp.pack index bd9731de3b..2f410e2864 100644 --- a/data/src/pack/varp.pack +++ b/data/src/pack/varp.pack @@ -147,7 +147,7 @@ 146=phoenixgang_progress 147=zanaris_progress 148=crest_progress -149=open_book +149=crest_spells_levers_gauntlets 150=grandtree_progress 151=daconia_rock_root 152=femi_help @@ -161,7 +161,7 @@ 160=imp_progress 161=upass_progress 162=upass_map_mechanisms -163=varp_163 +163=open_book 164=varp_164 165=elena_progress 166=game_brightness @@ -265,7 +265,7 @@ 264=gnome_course_progress 265=barbarian_course_progress 266=wilderness_course_progress -267=magearena_progress +267=magearena 268=saradomin_strike_casts 269=claws_of_guthix_casts 270=flames_of_zamorak_casts diff --git a/data/src/scripts/_test/scripts/cheats/cheat_quest.rs2 b/data/src/scripts/_test/scripts/cheats/cheat_quest.rs2 index 820214b419..8e327225de 100644 --- a/data/src/scripts/_test/scripts/cheats/cheat_quest.rs2 +++ b/data/src/scripts/_test/scripts/cheats/cheat_quest.rs2 @@ -62,13 +62,16 @@ if (p_finduid(uid) = true) { case 18 : queue(quest_chompybird_complete, 0); case 19 : queue(quest_biohazard_complete, 0); case 20 : queue(cog_complete, 0); - case 21 : mes("Quest not implemented"); + case 21 : queue(itexam_complete, 0); case 22 : if (npc_find(0_45_54_45_30, kaqemeex, 7, 0) = true) { queue(druid_quest_complete, 0, npc_uid); } case 23 : queue(mcannon_complete, 0); - case 24 : mes("Quest not implemented"); + case 24 : + queue(crest_complete, 0); + // Complete all blast spells and levers, gauntlet choice unselected + %crest_spells_levers_gauntlets = calc(pow(2, ^crest_south_lever) - 1); case 25 : queue(arena_quest_complete, 0); case 26 : queue(fishingcompo_quest_complete, 0); case 27 : queue(fluffs_complete, 0); @@ -145,12 +148,14 @@ if (p_finduid(uid) = true) { %chompybird_progress = 0; case 19 : %biohazard_progress = 0; case 20 : %cog_progress = 0; - case 21 : mes("Quest not implemented"); + case 21 : %itexam_progress = 0; case 22 : %druid_progress = 0; case 23 : %mcannon_railings = 0; %mcannon_progress = 0; - case 24 : mes("Quest not implemented"); + case 24 : + %crest_progress = 0; + %crest_spells_levers_gauntlets = 0; case 25 : %arena_progress = 0; case 26 : %fishingcompo_progress = 0; case 27 : diff --git a/data/src/scripts/_test/scripts/cheats/cheat_reset.rs2 b/data/src/scripts/_test/scripts/cheats/cheat_reset.rs2 index 339eb4cdaa..0613a00083 100644 --- a/data/src/scripts/_test/scripts/cheats/cheat_reset.rs2 +++ b/data/src/scripts/_test/scripts/cheats/cheat_reset.rs2 @@ -110,7 +110,7 @@ if (p_finduid(uid) = true) { %hazeelcult_progress = 0; %ball_progress = 0; %thread_used = 0; - %magearena_progress = 0; + %magearena = 0; %prince_progress = 0; %prince_keystatus = 0; %tutorial_progress = 0; diff --git a/data/src/scripts/_unpack/all.hunt b/data/src/scripts/_unpack/all.hunt index bb3ecb7573..d603364c2a 100644 --- a/data/src/scripts/_unpack/all.hunt +++ b/data/src/scripts/_unpack/all.hunt @@ -467,7 +467,7 @@ find_newmode=queue20 [example2] type=player -check_inv=worn,dragon_longsword,1,1 +check_inv=worn,dragon_longsword,=1 check_vis=lineofsight check_nottoostrong=off check_notcombat=%lastcombat @@ -476,7 +476,7 @@ find_newmode=queue20 [example3] type=player -check_invparam=worn,zamorakitem,1,2147483647 +check_invparam=worn,zamorakitem,>0 check_vis=lineofsight check_nottoostrong=off check_notcombat=%lastcombat @@ -497,7 +497,7 @@ find_newmode=queue20 [example6] type=player -check_inv=worn,dragon_longsword,0,0 +check_inv=worn,dragon_longsword,=0 check_vis=lineofsight check_nottoostrong=off check_notcombat=%lastcombat diff --git a/data/src/scripts/_unpack/all.loc b/data/src/scripts/_unpack/all.loc index 4c756bc4e3..6d732ef587 100644 --- a/data/src/scripts/_unpack/all.loc +++ b/data/src/scripts/_unpack/all.loc @@ -3348,7 +3348,7 @@ length=2 [loc_650] model=model_loc_650 -[loc_651] +[digsite_buried_skeleton] name=Buried skeleton desc=Dead and half buried. model=model_loc_651 @@ -11926,33 +11926,33 @@ model=model_loc_2349 width=2 length=2 -[loc_2350] +[digsite_winch] name=Winch desc=Used to move earth to, and from, the dig shaft. model=model_loc_2350 op1=Operate length=2 -[loc_2351] +[digsite_private_dig_winch] name=Winch desc=Used to move earth to, and from, the dig shaft. model=model_loc_2350 op1=Operate length=2 -[loc_2352] +[digsite_private_dig_exit_rope] name=Rope desc=This leads back up the dig shaft. model=model_loc_1762 op1=Climb-up -[loc_2353] +[digsite_blocked_altar_exit_rope] name=Rope desc=This leads back up the dig shaft. model=model_loc_1762 op1=Climb-up -[loc_2354] +[digsite_sacks_empty] name=Sacks desc=Yep, they're sacks! model=model_loc_23 @@ -11964,32 +11964,32 @@ desc=Yep, they're sacks! model=model_loc_23 op1=Search -[loc_2356] +[digsite_sacks_specimen_jars] name=Sacks desc=Yep, they're sacks! model=model_loc_23 op1=Search -[loc_2357] +[digsite_bush_empty] name=Bush desc=A leafy bush. model=model_loc_1124 op1=Search -[loc_2358] +[digsite_bush_rock_sample] name=Bush desc=A leafy bush. model=model_loc_1124 op1=Search -[loc_2359] +[digsite_sealed_barrel] name=Barrel desc=A sealed barrel with a warning sign on it. model=model_loc_2359 op1=Open op2=Search -[loc_2360] +[digsite_chest_open] name=Chest desc=I wonder what's inside... model=model_loc_76 @@ -11997,20 +11997,20 @@ op1=Search op2=Close forceapproach=north -[loc_2361] +[digsite_chest] name=Chest desc=A sturdy chest to keep things in. model=wooden_chest op1=Open forceapproach=north -[loc_2362] +[digsite_blocked_altar_brick] name=Brick desc=A large stone block. model=model_loc_2343 op1=Search -[loc_2363] +[digsite_panning_point] name=Panning point desc=A place where you can pan for gold. model=model_loc_42 @@ -12026,31 +12026,31 @@ name=Crate desc=A wooden container. model=model_loc_63 -[loc_2366] +[digsite_signpost_training_site] name=Signpost desc=A signpost! model=model_loc_1034 op1=Read -[loc_2367] +[digsite_signpost_level_1_site] name=Signpost desc=A signpost! model=model_loc_1034 op1=Read -[loc_2368] +[digsite_signpost_level_2_site] name=Signpost desc=A signpost! model=model_loc_1034 op1=Read -[loc_2369] +[digsite_signpost_level_3_site] name=Signpost desc=A signpost! model=model_loc_1034 op1=Read -[loc_2370] +[digsite_signpost_private_site] name=Signpost desc=A signpost! model=model_loc_1034 @@ -12062,21 +12062,21 @@ desc=A signpost! model=model_loc_1033 op1=Read -[loc_2372] +[exam_centre_bookcase_chemicals] name=Bookcase desc=Shelves filled with interesting books. model=model_loc_380 length=2 op1=Search -[loc_2373] +[exam_centre_cupboard_rock_pick] name=Cupboard desc=A cupboard. model=model_loc_367 op1=Open forceapproach=east -[loc_2374] +[exam_centre_cupboard_rock_pick_open] name=Cupboard desc=A cupboard. model=model_loc_370 @@ -12084,7 +12084,7 @@ op1=Search op2=Close forceapproach=east -[loc_2375] +[specimen_tray] name=Specimen tray desc=Used to keep specimens on. model=model_loc_2375 @@ -12099,6 +12099,7 @@ model=model_loc_184 hillskew=yes active=yes blockwalk=no +category=digsite_soil [loc_2377] name=Soil @@ -12107,6 +12108,7 @@ model=model_loc_185 hillskew=yes active=yes blockwalk=no +category=digsite_soil [loc_2378] name=Soil @@ -12115,6 +12117,7 @@ model=model_loc_186 hillskew=yes active=yes blockwalk=no +category=digsite_soil [loc_2379] name=Campsite bed @@ -12348,126 +12351,6 @@ mapscene=44 model=model_loc_771 mapscene=45 -[loc_2421] -name=Lever -desc=This lever is down. -model=model_loc_33 -active=yes -op1=Pull - -[loc_2422] -name=Lever -desc=This lever is up. -model=model_loc_34 -active=yes -op1=Pull - -[loc_2423] -name=Lever -desc=This lever is down. -model=model_loc_33 -active=yes -op1=Pull - -[loc_2424] -name=Lever -desc=This lever is up. -model=model_loc_34 -active=yes -op1=Pull - -[loc_2425] -name=Lever -desc=This lever is down. -model=model_loc_33 -active=yes -op1=Pull - -[loc_2426] -name=Lever -desc=This lever is up. -model=model_loc_34 -active=yes -op1=Pull - -[loc_2427] -name=Door -desc=This door is closed by an unknown mechanism. -model=model_loc_3 -active=yes -op1=Open -retex1s=wall -retex1d=door2 -recol2s=6342 -recol2d=11458 - -[loc_2428] -name=Door -desc=This door is closed by an unknown mechanism. -model=model_loc_3 -active=yes -op1=Open -retex1s=wall -retex1d=door2 -recol2s=6342 -recol2d=11458 - -[loc_2429] -name=Door -desc=This door is closed by an unknown mechanism. -model=model_loc_3 -active=yes -op1=Open -retex1s=wall -retex1d=door2 -recol2s=6342 -recol2d=11458 - -[loc_2430] -name=Door -desc=This door is closed by an unknown mechanism. -model=model_loc_3 -active=yes -op1=Open -retex1s=wall -retex1d=door2 -recol2s=6342 -recol2d=11458 - -[loc_2431] -name=Door -desc=This door is closed by an unknown mechanism. -model=model_loc_3 -active=yes -op1=Open -retex1s=wall -retex1d=door2 -recol2s=6342 -recol2d=11458 - -[loc_2432] -name=Gate -desc=This gate is closed shut. -model=model_loc_52 -active=yes -op1=Open -retex1s=wall -retex1d=door2 -recol2s=6342 -recol2d=11458 - -[loc_2433] -name=Gate -desc=This gate is closed shut. -model=model_loc_52 -active=yes -op1=Open -mirror=yes -retex1s=wall -retex1d=door2 -recol2s=6342 -recol2d=11458 - [loc_2493] name=Ruined Pillar desc=A part of an old temple. diff --git a/data/src/scripts/_unpack/all.npc b/data/src/scripts/_unpack/all.npc index 529dda2877..e2c33e345c 100644 --- a/data/src/scripts/_unpack/all.npc +++ b/data/src/scripts/_unpack/all.npc @@ -26,7 +26,9 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style category=citizen +// osrs stats and Vislvl match 1:1 [man_blue] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -56,7 +58,9 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style category=citizen +// osrs stats and Vislvl match 1:1 [man_brown] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -88,7 +92,9 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style category=citizen +// osrs stats and Vislvl match 1:1 [woman_purple] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -119,9 +125,11 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death category=citizen +// osrs stats and Vislvl match 1:1 [woman_brown] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -158,9 +166,11 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death category=citizen +// osrs stats and Vislvl match 1:1 [woman_red] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -199,9 +209,11 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death category=citizen +// osrs stats and Vislvl match 1:1 [farmer] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -240,6 +252,7 @@ param=defend_anim,human_farmersfork_defend param=attack_sound,staff_stab // osrs attack sound farmersfork_stab // runescape classic wander range is 15. +// osrs stats and Vislvl match 1:1 [thief] name=Thief @@ -270,6 +283,7 @@ strength=13 defence=12 wanderrange=7 param=retreat,8 +// osrs stats and Vislvl match 1:1 [guard_sword] name=Guard @@ -294,7 +308,6 @@ model6=model_254_idk model7=model_185_obj_wear model8=model_519_obj_wear model9=model_541_obj_wear -// Todo: proof wanderrange=2 maxrange=7 respawnrate=100 @@ -315,7 +328,8 @@ param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_stab // param=defend_sound,blade4 category=guard -// osrs att seq_386 and defend seq_387, 2024 defend seq_387 +// osrs att seq_386 and defend seq_387 +// osrs stats and Vislvl match 1:1 [guard_crossbow] name=Guard @@ -339,15 +353,15 @@ model5=model_176_idk model6=model_254_idk model7=model_185_obj_wear model8=model_508_obj_wear -// Todo: proof + attackrange wanderrange=2 maxrange=4 +attackrange=5 respawnrate=100 hitpoints=22 attack=15 strength=15 defence=16 -ranged=16 +ranged=26 param=attackrate,6 param=attackbonus,6 param=strengthbonus,10 @@ -359,9 +373,13 @@ param=magicdefence,-4 param=rangedefence,15 param=damagetype,^ranged_style param=attack_anim,human_crossbow -param=attack_sound,crossbow +param=rangeattack_sound,crossbow +param=proj_launch,crossbowbolt_launch +param=proj_travel,crossbowbolt_travel // param=defend_sound,blade4 category=guard +// osrs version havent rangeattack sound. +// osrs stats and Vislvl match 1:1 [tramp] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -394,6 +412,7 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style [barbarian] name=Barbarian @@ -429,17 +448,21 @@ head3=model_75_npc_head respawnrate=50 hitpoints=14 attack=6 -strength=5 -defence=5 +strength=6 +defence=2 +param=attackrate,6 param=attackbonus,8 -param=strengthbonus,10 +param=strengthbonus,13 param=stabdefence,1 param=slashdefence,1 -param=attackrate,6 +param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash category=barbarian +// param=defend_sound,swordclash2 +// param stats are guesses. // sounds taken Gunthor the Brave +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3256 [wizard] name=Wizard @@ -464,7 +487,6 @@ model7=model_265_obj_wear model8=model_202_obj_wear head1=model_53_idk_head head2=model_44_obj_wear -// osrs attackrange=8 respawnrate=60 hitpoints=14 @@ -473,6 +495,7 @@ strength=8 defence=5 magic=10 param=magicdefence,3 +// osrs stats and Vislvl match 1:1 [warrior_woman] name=Warrior woman @@ -502,8 +525,6 @@ strength=22 defence=22 param=attackbonus,6 param=strengthbonus,7 -param=magicattack,6 -param=rangeattack,6 param=stabdefence,40 param=slashdefence,41 param=crushdefence,37 @@ -515,6 +536,7 @@ param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_stab // param=defend_sound,steel param=death_sound,female_death +// Stats match osrs version but our version Vislvl is different. [barbarian_woman] name=Barbarian woman @@ -540,17 +562,16 @@ model8=model_540_obj_wear model9=model_414_npc head1=model_113_idk_head head2=model_101_obj_wear -// osrs In the varrock bar there is still an 8lv Barbarian woman on the osrs side whose movement distances are 5/7 respawnrate=50 hitpoints=14 attack=6 strength=5 defence=5 +param=attackrate,6 param=attackbonus,8 param=strengthbonus,10 param=stabdefence,1 param=slashdefence,1 -param=attackrate,6 param=damagetype,^stab_style param=attack_anim,human_spear_stab param=defend_anim,human_spear_def @@ -558,6 +579,8 @@ param=attack_sound,staff_stab param=defend_sound,female_hit param=death_sound,female_death category=barbarian +// data taken from this npc https://oldschool.runescape.wiki/w/Barbarian (wander 5 / maxrange 7). +// osrs stats and Vislvl match 1:1 [paladin] name=Paladin @@ -606,6 +629,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash // param=defend_sound,blade3 +// Stats match osrs version but our version Vislvl is different. [hero] name=Hero @@ -654,6 +678,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_blunt_defend1 param=attack_sound,hacksword_slash // param=defend_sound,brassclash +// Stats match osrs version but our version Vislvl is different. [forester] name=Forester @@ -694,7 +719,9 @@ param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash -// osrs side woodcutting guild forester use defend seq_398 +// osrs side wc guild forester +// osrs defend seq_398 and wander is 4 maxranges is 6. +// osrs stats and Vislvl match 1:1 [knight_of_ardougne_1] name=Knight of Ardougne @@ -740,6 +767,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_slash // param=defend_sound,blade5 +// osrs stats and Vislvl match 1:1 [man_cavalier] name=Man @@ -774,7 +802,9 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 -category=citizen +param=damagetype,^crush_style +// TODO: check dialogues category=citizen +// osrs stats and Vislvl match 1:1 [woman_east_ardougne] name=Woman @@ -806,8 +836,11 @@ param=slashdefence,-21 param=crushdefence,-21 param=magicdefence,-21 param=rangedefence,-21 +param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death +// TODO: check dialogues category=citizen +// osrs stats and Vislvl match 1:1 [knight_of_ardougne_2] name=Knight of Ardougne @@ -851,8 +884,9 @@ param=rangedefence,36 param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 -param=attack_sound,hacksword_slash +param=attack_sound,stabsword_slash // param=defend_sound,blade5 +// https://oldschool.runescape.wiki/w/Knight_of_Ardougne_(unused) (data taken from normal knight of ardougne.) [watchman] name=Watchman @@ -885,6 +919,7 @@ param=magicdefence,-4 param=rangedefence,16 param=damagetype,^crush_style // param=defend_sound,blade3_mail +// Stats match osrs version but our version Vislvl is different. [soldier] name=Soldier @@ -924,6 +959,7 @@ param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash // param=defend_sound, // osrs defend sound blade3_mail +// Stats match osrs version but our version Vislvl is different. [shipyard_worker1] name=Shipyard worker @@ -953,10 +989,11 @@ hitpoints=10 attack=10 strength=10 defence=10 -param=attackbonus,6 -param=strengthbonus,6 +magic=0 +ranged=0 param=damagetype,^crush_style category=shipyard_worker +// Stats match osrs version but our version Vislvl is different. [shipyard_worker2] name=Shipyard worker @@ -984,6 +1021,9 @@ hitpoints=10 attack=10 strength=10 defence=10 +magic=0 +ranged=0 +param=attackrate,6 param=attackbonus,6 param=strengthbonus,6 param=damagetype,^crush_style @@ -992,6 +1032,7 @@ param=defend_anim,human_blunt_defend1 param=attack_sound,baxe_slash category=shipyard_worker // osrs attack sound warhammer_crush +// Stats match osrs version but our version Vislvl is different. [shark_Shipyard] name=Shark @@ -1027,6 +1068,7 @@ param=defend_sound,chicken_hit param=death_sound,chicken_death param=retreat,1 category=chicken +// osrs stats and Vislvl match 1:1 [sheep_sheared] vislevel=hide @@ -1057,7 +1099,7 @@ op2=Attack minimap=no vislevel=1 model1=model_2847_npc -// todo: proof recheck wanderranges +// todo: proof recheck wanderranges / maxrange is 40 confirmed. wanderrange=35 maxrange=40 moverestrict=blocked @@ -1079,6 +1121,7 @@ param=defend_sound,duck_hit param=death_sound,duck_death param=death_drop,null category=duck +// osrs stats and Vislvl match 1:1 [duck] name=Duck @@ -1095,6 +1138,7 @@ recol2d=11491 recol3s=22197 recol3d=10433 model1=model_2847_npc +// todo: proof recheck wanderranges / maxrange is 40 confirmed. wanderrange=35 maxrange=40 moverestrict=blocked @@ -1116,6 +1160,7 @@ param=defend_sound,duck_hit param=death_sound,duck_death param=death_drop,null category=duck +// osrs stats and Vislvl match 1:1 [duckling] name=Duckling @@ -1158,6 +1203,7 @@ param=death_drop,null category=duckling huntmode=duck_hunt huntrange=2 +// osrs stats and Vislvl match 1:1 [rat] name=Rat @@ -1187,6 +1233,7 @@ param=attack_sound,rat_attack param=defend_sound,rat_hit param=death_sound,rat_death param=death_drop,null +// osrs stats and Vislvl match 1:1 [oomlie_bird] name=Oomlie Bird @@ -1220,6 +1267,7 @@ param=defend_sound,chicken_hit param=death_sound,chicken_death huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [hellhound] size=2 @@ -1245,6 +1293,7 @@ param=attack_sound,growl6 param=defend_sound,growl5 huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [baby_dragon] size=2 @@ -1278,6 +1327,8 @@ param=death_sound,babydragon_death param=death_drop,babydragon_bones huntmode=cowardly huntrange=2 +// https://oldschool.runescape.wiki/w/Baby_dragon_(unused) +// all data taken Baby blue dragon. [baby_blue_dragon] size=2 @@ -1312,6 +1363,7 @@ param=death_sound,babydragon_death param=death_drop,babydragon_bones huntmode=cowardly huntrange=2 +// Stats match osrs version but our version Vislvl is different. [red_dragon] size=4 @@ -1347,6 +1399,7 @@ param=death_sound,dragon_death param=death_drop,dragon_bones huntmode=cowardly huntrange=4 +// Stats match osrs version but our version Vislvl is different. [black_dragon] size=4 @@ -1383,6 +1436,7 @@ param=death_sound,dragon_death param=death_drop,dragon_bones huntmode=cowardly huntrange=4 +// Stats match osrs version but our version Vislvl is different. [blue_dragon] size=4 @@ -1418,6 +1472,7 @@ param=death_sound,dragon_death param=death_drop,dragon_bones huntmode=cowardly huntrange=4 +// Stats match osrs version but our version Vislvl is different. [dryad] name=Dryad @@ -1429,6 +1484,9 @@ model1=model_2856_npc param=attack_anim,dryhad_attack param=defend_anim,dryhad_block param=death_anim,dryhad_death +param=attack_sound,null +param=defend_sound,null +param=death_sound,null [fairy] vislevel=hide @@ -1471,7 +1529,7 @@ param=death_sound,insect_death param=death_drop,null huntmode=cowardly huntrange=1 -// TODO spider prayer drain attack +// Stats match osrs version but our version Vislvl is different. [giant_spider1] walkanim=giantspider_walk @@ -1503,8 +1561,8 @@ param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null huntmode=cowardly -// osrs huntrange=1 +// osrs stats and Vislvl match 1:1 [giant_spider2] walkanim=giantspider_walk @@ -1532,8 +1590,8 @@ param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null huntmode=cowardly -// osrs huntrange=1 +// osrs stats and Vislvl match 1:1 [spider] walkanim=spider_walk @@ -1561,6 +1619,7 @@ param=attack_sound,insect_attack param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null +// osrs stats and Vislvl match 1:1 [jungle_spider] walkanim=giantspider_walk @@ -1595,6 +1654,8 @@ param=death_sound,insect_death param=death_drop,null huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. +// osrs wander=3 / max=5 [deadly_red_spider] walkanim=giantspider_walk @@ -1628,6 +1689,7 @@ param=death_sound,insect_death param=death_drop,null huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [ice_spider] walkanim=giantspider_walk @@ -1660,6 +1722,7 @@ param=death_sound,insect_death param=death_drop,null huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [leprechaun] walkanim=midget_walk @@ -1672,12 +1735,10 @@ model1=model_2909_npc model2=model_2896_npc model3=model_2915_npc respawnrate=100 -hitpoints=7 -attack=11 -strength=12 -defence=14 -param=slashdefence,3 -param=crushdefence,3 +hitpoints=16 +attack=10 +strength=10 +defence=7 param=damagetype,^crush_style param=attack_anim,midget_attackunarmed param=defend_anim,midget_block @@ -1685,107 +1746,9 @@ param=death_anim,midget_death param=attack_sound,gnome_attack param=defend_sound,gnome_hit param=death_sound,gnome_death - -[gnome_green] -name=Gnome -desc=Like a mini man! -walkanim=midget_walk -readyanim=midget_ready -op1=Talk-to -op2=Attack -op3=Pickpocket -vislevel=1 -model1=model_2909_npc -model2=model_2890_npc -model3=model_2915_npc -head1=model_21_npc_head -respawnrate=120 -hitpoints=3 -param=attackbonus,-42 -param=strengthbonus,-42 -param=rangebonus,2 -param=stabdefence,-42 -param=slashdefence,-42 -param=crushdefence,-42 -param=magicdefence,-42 -param=rangedefence,-42 -param=damagetype,^crush_style -param=attack_anim,midget_attackbow -param=defend_anim,midget_block -param=death_anim,midget_death -param=attack_sound,arrowlaunch2 -param=defend_sound,gnome_hit -param=death_sound,gnome_death - -[gnome_brown] -name=Gnome -desc=Like a mini man! -walkanim=midget_walk -readyanim=midget_ready -op1=Talk-to -op2=Attack -op3=Pickpocket -vislevel=1 -recol1s=352 -recol1d=14625 -model1=model_2909_npc -model2=model_2890_npc -model3=model_2915_npc -head1=model_21_npc_head -respawnrate=120 -hitpoints=3 -param=attackbonus,-42 -param=strengthbonus,-42 -param=rangebonus,2 -param=stabdefence,-42 -param=slashdefence,-42 -param=crushdefence,-42 -param=magicdefence,-42 -param=rangedefence,-42 -param=damagetype,^crush_style -param=attack_anim,midget_attackbow -param=defend_anim,midget_block -param=death_anim,midget_death -param=attack_sound,arrowlaunch2 -param=defend_sound,gnome_hit -param=death_sound,gnome_death - -[gnome_black] -name=Gnome -desc=Like a mini man! -walkanim=midget_walk -readyanim=midget_ready -op1=Talk-to -op2=Attack -op3=Pickpocket -vislevel=1 -recol1s=24075 -recol1d=13537 -recol2s=21961 -recol2d=13537 -recol3s=20904 -recol3d=13537 -model1=model_2909_npc -model2=model_2890_npc -model3=model_2915_npc -head1=model_21_npc_head -respawnrate=120 -hitpoints=3 -param=attackbonus,-42 -param=strengthbonus,-42 -param=rangebonus,2 -param=stabdefence,-42 -param=slashdefence,-42 -param=crushdefence,-42 -param=magicdefence,-42 -param=rangedefence,-42 -param=damagetype,^crush_style -param=attack_anim,midget_attackbow -param=defend_anim,midget_block -param=death_anim,midget_death -param=attack_sound,arrowlaunch2 -param=defend_sound,gnome_hit -param=death_sound,gnome_death +// stats taken Lost city leprechaun shamus. stats match to Vislvl +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1162 +// where these data is taken from? hitpoints=7, attack=11, strength=12, defence=14, param=slashdefence,3, param=crushdefence,3 [lizardman] name=Lizard man @@ -1804,6 +1767,7 @@ param=defend_sound,lizardman_hit param=death_sound,lizardman_death huntmode=cowardly huntrange=2 +// TODO [mummy] name=Mummy @@ -1821,6 +1785,7 @@ param=defend_sound,mummy_hit param=death_sound,mummy_death huntmode=cowardly huntrange=1 +// TODO [orc] name=Orc @@ -1838,6 +1803,7 @@ param=defend_sound,orc_hit param=death_sound,orc_death huntmode=cowardly huntrange=1 +// TODO [troll] name=Troll @@ -1847,11 +1813,30 @@ readyanim=troll_ready op2=Attack vislevel=69 model1=model_2930_npc +// wanderrange= +// maxrange= +hitpoints=90 +attack=40 +strength=75 +defence=40 +magic=0 +ranged=0 +param=attackrate,6 +param=attackbonus,20 +param=strengthbonus,20 +param=crushdefence,10 +param=magicdefence,200 +param=rangedefence,200 +param=damagetype,^crush_style param=attack_anim,troll_attack param=defend_anim,troll_block param=death_anim,troll_death +param=attack_sound,null +param=defend_sound,null +param=death_sound,null huntmode=cowardly huntrange=1 +// stats taken from Mountain Troll // Sounds is possible same as river troll that mean no sounds. [zombie1] name=Zombie @@ -1868,9 +1853,7 @@ hitpoints=22 attack=8 strength=9 defence=10 -param=attackbonus,5 -param=attackrate,5 -param=damagetype,^slash_style +param=damagetype,^crush_style param=attack_anim,zombie_attack param=defend_anim,zombie_block param=death_anim,zombie_death @@ -1880,6 +1863,7 @@ param=death_sound,zombie_death param=undead,^true huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [zombie2] name=Zombie @@ -1896,9 +1880,7 @@ hitpoints=24 attack=13 strength=13 defence=18 -param=attackbonus,5 -param=attackrate,5 -param=damagetype,^slash_style +param=damagetype,^crush_style param=attack_anim,zombie_attack param=defend_anim,zombie_block param=death_anim,zombie_death @@ -1908,6 +1890,7 @@ param=death_sound,zombie_death param=undead,^true huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [zombie3] name=Zombie @@ -1925,9 +1908,14 @@ hitpoints=30 attack=19 strength=21 defence=16 +param=attackrate,5 param=attackbonus,5 param=strengthbonus,7 -param=attackrate,5 +param=stabdefence,9 +param=slashdefence,8 +param=crushdefence,12 +param=magicdefence,10 +param=rangedefence,11 param=damagetype,^slash_style param=attack_anim,zombie_attack param=defend_anim,zombie_block @@ -1938,6 +1926,7 @@ param=death_sound,zombie_death param=undead,^true huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [zombie_entrana] name=Zombie @@ -1950,15 +1939,18 @@ model1=model_2931_npc model2=model_2932_npc wanderrange=9 maxrange=11 -// TODO find correct respawnrate=70 hitpoints=30 attack=19 strength=21 -defence=16 +defence=21 param=attackbonus,5 param=strengthbonus,7 -param=attackrate,5 +param=stabdefence,10 +param=slashdefence,8 +param=crushdefence,12 +param=magicdefence,10 +param=rangedefence,10 param=damagetype,^slash_style param=attack_anim,zombie_attack param=defend_anim,zombie_block @@ -1969,6 +1961,7 @@ param=death_sound,zombie_death param=undead,^true huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [summoned_zombie] name=Summoned Zombie @@ -1992,6 +1985,7 @@ param=death_sound,zombie_death param=undead,^true huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [giant_bat] name=Giant bat @@ -2025,6 +2019,7 @@ param=death_sound,bat_death param=death_drop,bat_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [death_wing] name=Death wing @@ -2060,6 +2055,8 @@ param=defend_sound,bat_hit param=death_sound,bat_death huntmode=aggressive_melee huntrange=2 +// osrs stats and Vislvl match 1:1 +// osrs huntmode cowardly 2024 [cow_1] size=2 @@ -2089,6 +2086,7 @@ param=attack_sound,cow_attack param=defend_sound,cow_hit param=death_sound,cow_death category=cow +// osrs stats and Vislvl match 1:1 [lesser_demon] size=2 @@ -2117,8 +2115,9 @@ param=defend_sound,demon_hit param=death_sound,demon_death param=death_drop,ashes huntmode=cowardly -// huntrange: https://youtu.be/bU8sQbojKH4?list=PLn23LiLYLb1aqrojPTi1_Np81LJku2Nd0&t=127 huntrange=2 +// huntrange: https://youtu.be/bU8sQbojKH4?list=PLn23LiLYLb1aqrojPTi1_Np81LJku2Nd0&t=127 +// osrs stats and Vislvl match 1:1 [greater_demon] size=3 @@ -2150,6 +2149,7 @@ param=death_sound,demon_death param=death_drop,ashes huntmode=cowardly huntrange=3 +// osrs stats and Vislvl match 1:1 [black_demon] size=3 @@ -2186,6 +2186,7 @@ param=death_drop,ashes category=black_demon huntmode=cowardly huntrange=3 +// osrs stats and Vislvl match 1:1 [golem] name=Golem @@ -2196,6 +2197,10 @@ readyanim=golem_ready op2=Attack vislevel=55 model1=model_2969_npc +hitpoints=70 +attack=35 +strength=60 +defence=30 param=attack_anim,golem_attack param=defend_anim,golem_block param=death_anim,golem_death @@ -2203,6 +2208,8 @@ param=attack_sound,golem_attack param=defend_sound,golem_hit param=death_sound,golem_death param=death_drop,null +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_2836 +// TODO try get more infos param stats, wander and max ranges. [giant_rat1] size=2 @@ -2227,8 +2234,8 @@ param=death_anim,giantrat_death param=attack_sound,rat_attack param=defend_sound,rat_hit param=death_sound,rat_death -// osrs // category= +// osrs stats and Vislvl match 1:1 [giant_rat2] size=2 @@ -2254,9 +2261,9 @@ param=attack_sound,rat_attack param=defend_sound,rat_hit param=death_sound,rat_death huntmode=cowardly -// osrs huntrange=1 // category= +// osrs stats and Vislvl match 1:1 [dungeon_rat] size=2 @@ -2284,9 +2291,9 @@ param=attack_sound,rat_attack param=defend_sound,rat_hit param=death_sound,rat_death huntmode=cowardly -// osrs huntrange=2 // category= +// Stats match osrs version but our version Vislvl is different. [unicorn] size=2 @@ -2312,7 +2319,7 @@ param=attack_sound,horse_hit param=defend_sound,horse_hit param=retreat,6 category=unicorn -// osrs +// osrs stats and Vislvl match 1:1 [skeleton1] name=Skeleton @@ -2322,12 +2329,10 @@ readyanim=skeleton_ready op2=Attack vislevel=18 model1=model_2944_npc -wanderrange=3 -maxrange=5 respawnrate=140 -hitpoints=29 -attack=15 -strength=18 +hitpoints=24 +attack=17 +strength=17 defence=17 param=stabdefence,5 param=slashdefence,5 @@ -2343,7 +2348,8 @@ param=death_sound,skeleton_death param=undead,^true huntmode=cowardly huntrange=1 -// Todo: proof old wander/maxranges early 2004 / rsc wander 8 +// Todo: proof old wander/maxranges early 2004 / rsc wander 8 / osrs wander 3 max 5 +// Stats match osrs version but our version Vislvl is different. [skeleton2] name=Skeleton @@ -2356,14 +2362,15 @@ model1=model_2944_npc wanderrange=8 maxrange=10 respawnrate=70 -hitpoints=24 -attack=17 -strength=17 +hitpoints=29 +attack=15 +strength=18 defence=17 param=stabdefence,5 param=slashdefence,5 param=crushdefence,-5 param=rangedefence,5 +param=damagetype,^crush_style param=attack_anim,skeleton_attack param=defend_anim,skeleton_block param=death_anim,skeleton_death @@ -2373,7 +2380,7 @@ param=death_sound,skeleton_death param=undead,^true huntmode=cowardly huntrange=1 -// osrs +// Stats match osrs version but our version Vislvl is different. [skeleton3] name=Skeleton @@ -2398,7 +2405,7 @@ param=slashdefence,11 param=crushdefence,-2 param=magicdefence,1 param=rangedefence,4 -param=damagetype,^crush_style +param=damagetype,^slash_style param=attack_anim,skeleton_attack param=defend_anim,skeleton_block param=death_anim,skeleton_death @@ -2409,7 +2416,7 @@ param=undead,^true huntmode=cowardly // huntrange: https://youtu.be/bU8sQbojKH4?list=PLn23LiLYLb1aqrojPTi1_Np81LJku2Nd0&t=127 huntrange=1 -// osrs +// Stats match osrs version but our version Vislvl is different. [skeleton4] name=Skeleton @@ -2447,7 +2454,7 @@ param=undead,^true huntmode=cowardly // huntrange: https://youtu.be/bU8sQbojKH4?list=PLn23LiLYLb1aqrojPTi1_Np81LJku2Nd0&t=127 huntrange=1 -// osrs +// osrs stats and Vislvl match 1:1 [skeleton_mage] name=Skeleton Mage @@ -2474,12 +2481,12 @@ attack=14 strength=14 defence=14 magic=18 -param=damagetype,^stab_style +param=damagetype,^crush_style param=attack_sound,skeleton_attack param=defend_sound,skelly_hit param=death_sound,skeleton_death param=undead,^true -// TODO magic attack + somekind curse +// Stats match osrs version but our version Vislvl is different. [npc_95] name=Wolf @@ -2507,6 +2514,7 @@ param=death_sound,wolf_death param=death_drop,wolf_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_96] size=2 @@ -2538,6 +2546,7 @@ param=death_sound,wolf_death param=death_drop,wolf_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_97] size=2 @@ -2569,6 +2578,7 @@ param=death_sound,wolf_death param=death_drop,wolf_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_98] name=Dog @@ -2603,6 +2613,8 @@ param=attack_sound,wolf_attack2 param=defend_sound,wolf_hit huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 +// TODO sounds [goblin_unarmed1] name=Goblin @@ -2633,6 +2645,7 @@ param=death_anim,goblin_death param=attack_sound,goblin_attack param=defend_sound,goblin_hit param=death_sound,goblin_death +// osrs stats and Vislvl match 1:1 [goblin_armed] name=Goblin @@ -2652,16 +2665,17 @@ respawnrate=140 hitpoints=12 attack=3 defence=4 +param=attackrate,6 param=attackbonus,12 param=strengthbonus,12 -param=attackrate,6 -param=damagetype,^crush_style +param=damagetype,^stab_style param=attack_anim,goblin_attack_armed param=defend_anim,goblin_block param=death_anim,goblin_death param=attack_sound,goblin_attack param=defend_sound,goblin_hit param=death_sound,goblin_death +// osrs stats and Vislvl match 1:1 [goblin_unarmed2] name=Goblin @@ -2694,6 +2708,7 @@ param=death_anim,goblin_death param=attack_sound,goblin_attack param=defend_sound,goblin_hit param=death_sound,goblin_death +// osrs stats and Vislvl match 1:1 [ghost] name=Ghost @@ -2730,6 +2745,7 @@ param=death_drop,null param=undead,^true huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [ghost_draynor_manor] name=Ghost @@ -2762,6 +2778,7 @@ param=defend_sound,ghost_hit param=death_sound,ghost_death param=death_drop,null param=undead,^true +// osrs stats and Vislvl match 1:1 [bear_brown] size=2 @@ -2788,8 +2805,8 @@ param=defend_sound,bear_hit param=death_sound,bear_death category=bear huntmode=cowardly -// osrs huntrange=1 +// osrs stats and Vislvl match 1:1 [bear_black] size=2 @@ -2819,8 +2836,9 @@ param=death_sound,bear_death category=bear huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 -[npc_107] +[scorpion] size=2 walkanim=scorpion_walk readyanim=scorpion_ready @@ -2840,7 +2858,7 @@ param=stabdefence,5 param=slashdefence,15 param=crushdefence,15 param=rangedefence,5 -param=damagetype,^slash_style +param=damagetype,^stab_style param=attack_anim,scorpion_attack param=defend_anim,scorpion_parry param=death_anim,scorpion_death @@ -2850,8 +2868,9 @@ param=death_sound,insect_death param=death_drop,null huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 -[npc_108] +[poison_scorpion] size=2 walkanim=scorpion_walk readyanim=scorpion_ready @@ -2882,8 +2901,9 @@ param=death_drop,null param=poison_severity,15 huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 -[npc_109] +[pit_scorpion] name=Pit Scorpion desc=Tiny, annoying, stinging thing. walkanim=smallscorpion_walk @@ -2910,6 +2930,7 @@ param=death_sound,insect_death param=death_drop,null huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [fire_giant] size=2 @@ -2947,6 +2968,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// Stats match osrs version but our version Vislvl is different. [ice_giant] size=2 @@ -2980,6 +3002,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// Stats match osrs version but our version Vislvl is different. [moss_giant] size=2 @@ -3015,6 +3038,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// Stats match osrs version but our version Vislvl is different. [jogre] size=2 @@ -3039,9 +3063,9 @@ hitpoints=60 attack=43 strength=43 defence=43 +param=attackrate,6 param=attackbonus,22 param=strengthbonus,20 -param=attackrate,6 param=damagetype,^crush_style param=attack_anim,giant_attack param=defend_anim,giant_block @@ -3052,6 +3076,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// Stats match osrs version but our version Vislvl is different. [npc_114] size=2 @@ -3070,9 +3095,9 @@ hitpoints=60 attack=43 strength=43 defence=43 +param=attackrate,6 param=attackbonus,22 param=strengthbonus,20 -param=attackrate,6 param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block @@ -3083,6 +3108,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// Stats match osrs version but our version Vislvl is different. [npc_115] size=2 @@ -3101,9 +3127,9 @@ hitpoints=60 attack=43 strength=43 defence=43 +param=attackrate,6 param=attackbonus,22 param=strengthbonus,20 -param=attackrate,6 param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block @@ -3115,6 +3141,7 @@ param=death_drop,big_bones huntmode=cowardly huntrange=2 // osrs attack_sound,giant_attack & defend_sound,mace_crush +// Stats match osrs version but our version Vislvl is different. [cyclops] size=2 @@ -3126,8 +3153,8 @@ op2=Attack vislevel=56 model1=model_2870_npc model2=model_2867_npc -wanderrange=4 -maxrange=6 +wanderrange=3 +maxrange=5 respawnrate=60 hitpoints=55 attack=47 @@ -3143,6 +3170,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [giant] size=2 @@ -3161,9 +3189,9 @@ hitpoints=35 attack=18 strength=22 defence=26 +param=attackrate,6 param=attackbonus,18 param=strengthbonus,16 -param=attackrate,6 param=damagetype,^crush_style param=attack_anim,giant_attack param=defend_anim,giant_block @@ -3174,6 +3202,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_118] walkanim=dwarf_walk @@ -3197,15 +3226,17 @@ hitpoints=16 attack=8 strength=8 defence=6 +param=attackrate,5 param=attackbonus,5 param=strengthbonus,7 param=magicdefence,5 -param=attackrate,5 -param=damagetype,^crush_style +param=damagetype,^stab_style param=attack_anim,dwarf_attack param=defend_anim,dwarf_block param=death_anim,dwarf_death param=attack_sound,baxe_crush +// osrs stats and Vislvl match 1:1 +// TODO SOUNDS [npc_119] walkanim=dwarf_walk @@ -3245,10 +3276,12 @@ param=attack_anim,dwarf_attack param=defend_anim,dwarf_block param=death_anim,dwarf_death param=attack_sound,baxe_crush -// param=defend_sound,brassclash2 possible used this before??? -// TODO sounds osrs use these sounds warhammer_crush, dwarf_hit, dwarf_death +// param=defend_sound, huntmode=cowardly huntrange=1 +// Osrs sounds warhammer_crush, dwarf_hit, dwarf_death +// osrs stats and Vislvl match 1:1 +// TODO SOUNDS [npc_120] walkanim=dwarf_walk @@ -3270,16 +3303,18 @@ hitpoints=26 attack=15 strength=16 defence=16 +param=attackrate,6 param=attackbonus,11 param=strengthbonus,9 param=magicdefence,5 -param=attackrate,6 param=damagetype,^crush_style param=attack_anim,dwarf_attack param=defend_anim,dwarf_block param=death_anim,dwarf_death param=attack_sound,baxe_crush -// osrs souns use these sounds warhammer_crush, dwarf_hit, dwarf_death +// osrs sounds warhammer_crush, dwarf_hit, dwarf_death +// osrs stats and Vislvl match 1:1 +// TODO SOUNDS [npc_121] walkanim=dwarf_walk @@ -3297,12 +3332,13 @@ model6=model_2993_npc wanderrange=13 maxrange=15 respawnrate=100 -hitpoints=10 -attack=6 -strength=6 +hitpoints=16 +attack=8 +strength=8 defence=6 -param=attackbonus,5 -param=strengthbonus,7 +param=attackrate,6 +param=attackbonus,11 +param=strengthbonus,9 param=magicdefence,5 param=damagetype,^crush_style param=attack_anim,dwarf_attack @@ -3310,6 +3346,7 @@ param=defend_anim,dwarf_block param=death_anim,dwarf_death param=attack_sound,baxe_crush // possible use same sound datas what npc ID 120 +// all data is guess. stats taken npc 118 and param taken npc 120 [hobgoblin] walkanim=hobgoblin_walk @@ -3334,6 +3371,7 @@ param=defend_sound,goblin_hit param=death_sound,goblin_death huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [hobgoblin_armed] walkanim=hobgoblin_walk @@ -3350,11 +3388,11 @@ hitpoints=49 attack=33 strength=31 defence=36 +param=attackrate,6 param=attackbonus,8 param=strengthbonus,10 param=stabdefence,1 param=slashdefence,1 -param=attackrate,6 param=damagetype,^stab_style param=attack_anim,hobgoblin_spear_attack param=defend_anim,hobgoblin_block @@ -3364,6 +3402,7 @@ param=defend_sound,goblin_hit param=death_sound,goblin_death huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [earth_warrior] hasalpha=yes @@ -3409,13 +3448,13 @@ param=rangedefence,30 param=damagetype,^crush_style param=attack_anim,earthwarrior_chop param=defend_anim,human_baxe_defend2 -// param=defend_anim,earthwarrior_def param=death_anim,earthwarrior_death param=attack_sound,mace_crush // param=defend_sound,blade5 huntmode=cowardly huntrange=1 // osrs sound attack warhammer_crush +// Stats match osrs version but our version Vislvl is different. [ice_warrior] hasalpha=yes @@ -3465,6 +3504,7 @@ param=defend_sound,ice_warrior_hit param=death_sound,ice_warrior_death huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [otherworldly_being] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -3495,11 +3535,12 @@ param=slashdefence,10 param=crushdefence,20 param=magicdefence,-5 param=rangedefence,15 -param=damagetype,^slash_style +param=damagetype,^crush_style param=attack_sound,otherworld_attack param=defend_sound,otherworld_hit param=death_sound,otherworld_death param=death_drop,null +// osrs stats and Vislvl match 1:1 [magic_axe] walkanim=magicaxe_walk @@ -3531,6 +3572,7 @@ param=defend_sound,sword_hit2 param=death_drop,iron_battleaxe huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [snake] name=Snake @@ -3554,6 +3596,7 @@ param=defend_sound,snake_hit param=death_sound,snake_death huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [npc_129] walkanim=skavid_walk @@ -3563,6 +3606,7 @@ desc=Servant race to the ogres. op2=Attack vislevel=2 model1=model_2999_npc +hitpoints=6 param=attack_anim,skavid_attack param=defend_anim,skavid_block param=death_anim,skavid_death @@ -3579,9 +3623,17 @@ readyanim=yeti_ready op2=Attack vislevel=58 model1=model_3001_npc +hitpoints=55 +attack=48 +strength=60 +defence=39 param=attack_anim,yeti_attack param=defend_anim,yeti_block param=death_anim,yeti_death +// param=attack_sound, +// param=defend_sound, +// param=death_sound, +// TODO SOUNDS possible, should be the same sounds as the Giants npc.. [penguin] name=Penguin @@ -3604,6 +3656,7 @@ param=death_anim,penguin_death param=attack_sound,penguin_attack param=defend_sound,penguin_hit param=death_sound,penguin_death +// osrs stats and Vislvl match 1:1 [monkey] name=Monkey @@ -3627,6 +3680,7 @@ param=death_anim,monkey_death param=attack_sound,monkey_attack param=defend_sound,monkey_hit param=death_sound,monkey_death +// osrs stats and Vislvl match 1:1 [black_unicorn] size=2 @@ -3658,6 +3712,7 @@ param=defend_sound,horse_hit huntmode=cowardly huntrange=2 category=unicorn +// osrs stats and Vislvl match 1:1 [npc_134] walkanim=giantspider_walk @@ -3691,6 +3746,7 @@ param=death_drop,null param=poison_severity,27 huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [mammoth] size=3 @@ -3710,88 +3766,6 @@ param=death_sound,mammoth_death huntmode=cowardly huntrange=3 -[terrorbird] -name=Terrorbird -desc=A giant raptor. -size=2 -walkanim=terrorbird_walk -readyanim=terrorbird_ready -op2=Attack -vislevel=28 -model1=model_3011_npc -wanderrange=12 -maxrange=14 -respawnrate=60 -hitpoints=34 -attack=23 -strength=23 -defence=19 -param=damagetype,^stab_style -param=attack_anim,terrorbird_attack -param=defend_anim,terrorbird_block -param=death_anim,terrorbird_death -param=attack_sound,terrorbird_attack -param=defend_sound,terrorbird_hit -param=death_sound,terrorbird_death - -[npc_137] -name=Mounted terrorbird gnome -desc=These gnomes know how to get around! -size=2 -walkanim=mounted_terrorbird_walk -readyanim=mounted_terrorbird_ready -op2=Attack -vislevel=29 -model1=model_3012_npc -wanderrange=12 -maxrange=14 -respawnrate=60 -hitpoints=36 -attack=25 -strength=25 -defence=25 -param=stabdefence,16 -param=slashdefence,16 -param=crushdefence,18 -param=magicdefence,15 -param=rangedefence,10 -param=damagetype,^stab_style -param=attack_anim,mounted_terrorbird_attack -param=defend_anim,mounted_terrorbird_defend -param=death_anim,mounted_terrorbird_death -param=attack_sound,terrorbird_attack -param=defend_sound,terrorbird_hit -param=death_sound,terrorbird_death - -[npc_138] -name=Mounted terrorbird gnome -desc=These gnomes know how to get around! -size=2 -walkanim=mounted_terrorbird_walk -readyanim=mounted_terrorbird_ready -op2=Attack -vislevel=46 -model1=model_3013_npc -wanderrange=12 -maxrange=14 -respawnrate=60 -hitpoints=55 -attack=40 -strength=40 -defence=40 -param=stabdefence,16 -param=slashdefence,16 -param=crushdefence,18 -param=magicdefence,15 -param=rangedefence,10 -param=damagetype,^stab_style -param=attack_anim,mounted_terrorbird_gnome_hands_over_food -param=defend_anim,mounted_terrorbird_defend -param=death_anim,mounted_terrorbird_death -param=attack_sound,terrorbird_attack -param=defend_sound,terrorbird_hit -param=death_sound,terrorbird_death - [npc_140] walkanim=souless_walk readyanim=souless_ready @@ -3817,6 +3791,7 @@ param=death_anim,souless_death param=retreat,9 huntmode=cowardly huntrange=1 +// TODO [npc_141] size=2 @@ -3850,6 +3825,7 @@ param=death_sound,wolf_death param=death_drop,wolf_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_142] size=2 @@ -3881,6 +3857,7 @@ param=death_sound,wolf_death param=death_drop,wolf_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_143] name=Jungle Wolf @@ -3912,6 +3889,7 @@ param=death_sound,wolf_death param=death_drop,wolf_bones huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_144] size=2 @@ -3945,6 +3923,7 @@ param=death_sound,insect_death param=death_drop,null huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [npc_145] hasalpha=yes @@ -3988,14 +3967,13 @@ param=rangedefence,30 param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 -// param=attack_anim,human_sword_transslash -// param=defend_anim,earthwarrior_def param=death_anim,earthwarrior_death param=attack_sound,hacksword_slash param=defend_sound,ice_warrior_hit param=death_sound,ice_warrior_death huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [npc_146] name=Gull @@ -4006,10 +3984,19 @@ readyanim=bird_ready minimap=no vislevel=26 model1=model_2850_npc -moverestrict=blocked+normal wanderrange=8 +moverestrict=blocked+normal +hitpoints=32 +attack=22 +strength=22 +defence=17 +param=attack_anim,bird_attack +param=defend_anim,bird_hit param=death_anim,bird_death +param=death_sound,bird_attack +param=death_sound,bird_hit param=death_sound,bird_death +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_281 [npc_147] name=Cormorant @@ -4020,9 +4007,17 @@ readyanim=bird_ready minimap=no vislevel=26 model1=model_2850_npc -wanderrange=15 +hitpoints=32 +attack=22 +strength=22 +defence=17 +param=attack_anim,bird_attack +param=defend_anim,bird_hit param=death_anim,bird_death +param=death_sound,bird_attack +param=death_sound,bird_hit param=death_sound,bird_death +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_282 [npc_148] name=Albatross @@ -4033,9 +4028,17 @@ readyanim=bird_ready minimap=no vislevel=26 model1=model_2850_npc -wanderrange=20 +hitpoints=32 +attack=22 +strength=22 +defence=17 +param=attack_anim,bird_attack +param=defend_anim,bird_hit param=death_anim,bird_death +param=death_sound,bird_attack +param=death_sound,bird_hit param=death_sound,bird_death +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_283 [npc_149] name=Gull @@ -4050,8 +4053,17 @@ recol1d=21140 recol2s=31649 recol2d=4428 model1=model_2850_npc +hitpoints=32 +attack=22 +strength=22 +defence=17 +param=attack_anim,bird_attack +param=defend_anim,bird_hit param=death_anim,bird_death +param=death_sound,bird_attack +param=death_sound,bird_hit param=death_sound,bird_death +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_284 [npc_150] name=Gull @@ -4062,8 +4074,17 @@ readyanim=bird_ready vislevel=hide minimap=no model1=model_2850_npc +hitpoints=32 +attack=22 +strength=22 +defence=17 +param=attack_anim,bird_attack +param=defend_anim,bird_hit param=death_anim,bird_death +param=death_sound,bird_attack +param=death_sound,bird_hit param=death_sound,bird_death +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_285 [fly_trap] vislevel=hide @@ -4074,6 +4095,15 @@ model1=model_loc_1395_8 wanderrange=0 moverestrict=nomove blockwalk=all +hitpoints=100 +attack=15 +strength=15 +defence=30 +param=stabdefence,30 +param=slashdefence,8 +param=crushdefence,45 +// https://oldschool.runescape.wiki/w/Fly_trap +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_2852 [nasty_tree] vislevel=hide @@ -4088,8 +4118,10 @@ model1=model_3014_npc wanderrange=0 moverestrict=nomove blockwalk=all +hitpoints=250 attack=20 strength=20 +defence=40 param=damagetype,^slash_style param=attack_anim,nasty_tree_attack param=attack_sound,nasty_tree_attack @@ -4097,6 +4129,7 @@ huntmode=aggressive_melee huntrange=1 // https://vxtwitter.com/JagexAsh/status/1775970463061049645?t=dBzjxnZ88IdFRi86mMgqjw&s=19 // "They have level 20 Attack & Strength" - ash +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4416 [npc_153] name=Butterfly @@ -4198,6 +4231,7 @@ defence=14 magic=22 param=magicdefence,3 huntmode=ranged +// osrs stats and Vislvl match 1:1 [npc_173] name=Invrigar the Necromancer @@ -4226,6 +4260,8 @@ strength=17 defence=14 magic=18 param=magicdefence,3 +param=damagetype,^crush_style +// osrs stats and Vislvl match 1:1 [dark_wizard_water] name=Dark wizard @@ -4258,10 +4294,10 @@ defence=5 magic=6 param=magicdefence,3 huntmode=ranged -// osrs huntrange=3 +// osrs stats and Vislvl match 1:1 -[npc_175] +[mugger] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready name=Mugger @@ -4293,8 +4329,8 @@ param=strengthbonus,-21 param=damagetype,^crush_style param=defend_anim,human_unarmedblock huntmode=cowardly -// osrs huntrange=5 +// Stats match osrs version but our version Vislvl is different. [npc_176] name=Witch @@ -4320,7 +4356,14 @@ model4=model_353_idk model5=model_428_idk model6=model_361_obj_wear model7=model_377_obj_wear +// TODO respawnrate hitpoints=10 +attack=25 +strength=25 +defence=25 +magic=30 +// TODO param stats +param=damagetype,^crush_style param=attack_anim,human_unarmedkick param=attack_sound,unarmed_kick param=defend_sound,female_hit @@ -4348,7 +4391,14 @@ model4=model_353_idk model5=model_428_idk model6=model_361_obj_wear model7=model_377_obj_wear +// TODO respawnrate hitpoints=10 +attack=25 +strength=25 +defence=25 +magic=30 +// TODO param stats +param=damagetype,^crush_style param=attack_anim,human_unarmedkick param=attack_sound,unarmed_kick param=defend_sound,female_hit @@ -4385,6 +4435,7 @@ hitpoints=42 attack=25 strength=25 defence=25 +param=attackrate,5 param=attackbonus,18 param=strengthbonus,16 param=stabdefence,73 @@ -4392,12 +4443,12 @@ param=slashdefence,76 param=crushdefence,70 param=magicdefence,-11 param=rangedefence,72 -param=attackrate,5 param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash // param=defend_sound,steel +// Stats match osrs version but our version Vislvl is different. [black_knight_aggre] name=Black Knight @@ -4430,6 +4481,7 @@ hitpoints=42 attack=25 strength=25 defence=25 +param=attackrate,5 param=attackbonus,18 param=strengthbonus,16 param=stabdefence,73 @@ -4437,7 +4489,6 @@ param=slashdefence,76 param=crushdefence,70 param=magicdefence,-11 param=rangedefence,72 -param=attackrate,5 param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 @@ -4445,6 +4496,7 @@ param=attack_sound,2H_slash // param=defend_sound,steel huntmode=cowardly huntrange=5 +// Stats match osrs version but our version Vislvl is different. [highwayman] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -4495,6 +4547,7 @@ param=attack_sound,hacksword_slash // https://www.youtube.com/watch?v=ympIobOpG4M // year 2024 attack seq_386 defend seq_387 and same animations used 2007 + original osrs launch huntmode=ranged +// osrs stats and Vislvl match 1:1 [chaos_druid] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -4521,10 +4574,12 @@ hitpoints=20 attack=8 strength=8 defence=12 +magic=10 attackrange=8 huntrange=3 param=damagetype,^crush_style huntmode=ranged +// osrs stats and Vislvl match 1:1 [npc_182] name=Pirate @@ -4556,6 +4611,7 @@ strength=20 defence=20 param=attackbonus,10 param=strengthbonus,9 +param=slashdefence,1 param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 @@ -4563,6 +4619,7 @@ param=attack_sound,hacksword_slash huntmode=cowardly huntrange=1 category=pirate +// Stats match osrs version but our version Vislvl is different. [npc_183] name=Pirate @@ -4608,6 +4665,7 @@ param=attack_sound,hacksword_slash huntmode=cowardly huntrange=1 category=pirate +// Stats match osrs version but our version Vislvl is different. [npc_184] name=Pirate @@ -4652,6 +4710,7 @@ param=attack_sound,hacksword_slash category=pirate huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [npc_185] name=Pirate @@ -4693,6 +4752,7 @@ param=attack_sound,hacksword_slash category=pirate huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [thug] name=Thug @@ -4731,6 +4791,7 @@ param=attack_sound,hacksword_stab huntmode=aggressive_melee huntrange=3 members=yes +// osrs stats and Vislvl match 1:1 [rogue] name=Rogue @@ -4770,6 +4831,7 @@ param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_stab huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [monk_of_zamorak_22] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -4803,6 +4865,7 @@ param=damagetype,^crush_style category=monk_of_zamorak huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [monk_of_zamorak_17] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -4836,6 +4899,7 @@ param=damagetype,^crush_style category=monk_of_zamorak huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [monk_of_zamorak_45] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -4868,6 +4932,7 @@ param=damagetype,^crush_style category=monk_of_zamorak huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [tribesman] name=Tribesman @@ -4907,6 +4972,7 @@ param=poison_severity,55 // huntmode is just a guess huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [dark_warrior] name=Dark warrior @@ -4952,49 +5018,7 @@ param=attack_sound,hacksword_slash // param=defend_sound,steel huntmode=cowardly huntrange=1 - -[chaos_druid_warrior] -name=Chaos druid warrior -desc=A crazy evil druid. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op2=Attack -vislevel=37 -recol1s=14724 -recol1d=19588 -recol2s=2340 -recol2d=19588 -recol3s=6273 -recol3d=21140 -model1=model_206_idk -model2=model_181_idk -model3=model_246_idk -model4=model_294_obj_wear -model5=model_170_idk -model6=model_176_idk -model7=model_260_npc -model8=model_502_obj_wear -respawnrate=100 -hitpoints=40 -attack=32 -strength=34 -defence=25 -param=attackrate,5 -param=attackbonus,9 -param=strengthbonus,5 -param=stabdefence,13 -param=slashdefence,17 -param=crushdefence,14 -param=magicdefence,-4 -param=rangedefence,14 -param=damagetype,^crush_style -param=attack_anim,human_blunt_crush -param=defend_anim,human_blunt_defend1 -param=attack_sound,mace_crush -// param=defend_sound,steel_mail -// osrs attack sound warhammer_crush -huntmode=cowardly -huntrange=1 +// osrs stats and Vislvl match 1:1 [necromancer] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -5022,6 +5046,8 @@ hitpoints=40 attack=18 strength=18 defence=18 +param=damagetype,^crush_style +// Stats match osrs version but our version Vislvl is different. [bandit] name=Bandit @@ -5061,8 +5087,8 @@ param=attack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_stab huntmode=cowardly -// osrs huntrange=6 +// Stats match osrs version but our version Vislvl is different. [guard_bandit] name=Guard Bandit @@ -5106,8 +5132,8 @@ param=attack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_stab huntmode=cowardly -// osrs huntrange=6 +// Stats match osrs version but our version Vislvl is different. [npc_197] name=Barbarian guard @@ -5137,12 +5163,22 @@ model6=model_274_idk model7=model_242_npc model8=model_185_obj_wear model9=model_550_obj_wear -// damage style +hitpoints=14 +attack=6 +strength=6 +defence=6 +param=attackrate,6 +param=attackbonus,8 +param=strengthbonus,13 +param=stabdefence,1 +param=slashdefence,1 +param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash // param=defend_sound,swordclash2 -// possibly the same defend sound as gunthor the brave on barbarian. +// param stats are guesses. // sounds taken Gunthor the Brave +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1028 [gunthor_the_brave] name=Gunthor the brave @@ -5191,35 +5227,7 @@ param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash // param=defend_sound,swordclash2 - -[salarin_the_twisted] -name=Salarin the twisted -desc=Twisted by name, twisted by nature. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -desc=A crazy evil druid -op2=Attack -vislevel=70 -recol1s=2340 -recol1d=19588 -recol2s=14724 -recol2d=19588 -recol3s=6273 -recol3d=22850 -model1=model_203_idk -model2=model_181_idk -model3=model_250_idk -model4=model_292_idk -model5=model_170_idk -model6=model_176_idk -model7=model_260_npc -respawnrate=100 -hitpoints=70 -attack=58 -strength=58 -defence=62 -param=damagetype,^slash_style -param=max_dealt,0 +// osrs stats and Vislvl match 1:1 [monk_entrana] name=Monk @@ -5250,6 +5258,7 @@ strength=2 defence=3 param=damagetype,^crush_style param=retreat,7 +// osrs stats and Vislvl match 1:1 [forester_mcgrubor] vislevel=hide @@ -5317,6 +5326,7 @@ param=defend_sound,ghost_hit param=death_sound,ghost_death param=death_drop,null param=undead,^true +// TODO monster examine spell [npc_282] name=Thief @@ -5340,6 +5350,8 @@ hitpoints=17 attack=14 strength=10 defence=9 +magic=0 +ranged=2 param=attackbonus,6 param=strengthbonus,7 param=stabdefence,8 @@ -5347,10 +5359,12 @@ param=slashdefence,13 param=crushdefence,14 param=magicdefence,4 param=rangedefence,9 +param=damagetype,^stab_style param=attack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_stab param=retreat,8 +// osrs stats and Vislvl match 1:1 [head_thief] name=Head Thief @@ -5374,6 +5388,8 @@ hitpoints=37 attack=24 strength=18 defence=16 +magic=0 +ranged=2 param=attackrate,5 param=strengthbonus,10 param=stabdefence,8 @@ -5385,6 +5401,7 @@ param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_slash +// osrs stats and Vislvl match 1:1 [doric] vislevel=hide @@ -5476,125 +5493,6 @@ model1=model_loc_42_8 wanderrange=0 moverestrict=nomove -[npc_344] -vislevel=hide -name=Guard -desc=He tries to keep order around here. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=15855 -recol1d=8420 -model1=model_208_npc -model2=model_185_obj_wear -model3=model_248_idk -model4=model_311_obj_wear -model5=model_151_idk -model6=model_179_obj_wear -model7=model_254_idk -model8=model_276_npc -model9=model_502_obj_wear -model10=model_541_obj_wear -head1=model_48_npc_head -head2=model_80_idk_head -wanderrange=1 - -[npc_345] -vislevel=hide -name=Guard -desc=He tries to keep order around here. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=15855 -recol1d=8420 -model1=model_208_npc -model2=model_185_obj_wear -model3=model_248_idk -model4=model_311_obj_wear -model5=model_151_idk -model6=model_179_obj_wear -model7=model_254_idk -model8=model_276_npc -model9=model_508_obj_wear -head1=model_48_npc_head -head2=model_80_idk_head -wanderrange=1 - -[npc_346] -vislevel=hide -name=Guard -desc=He tries to keep order around here. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=15855 -recol1d=8420 -model1=model_208_npc -model2=model_185_obj_wear -model3=model_248_idk -model4=model_311_obj_wear -model5=model_151_idk -model6=model_179_obj_wear -model7=model_254_idk -model8=model_276_npc -model9=model_508_obj_wear -head1=model_48_npc_head -head2=model_80_idk_head - -[npc_359] -vislevel=hide -name=Man -desc=One of RuneScapes' many citizens. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -recol1s=14801 -recol1d=12547 -recol2s=2340 -recol2d=6208 -recol3s=14724 -recol3d=16808 -recol4s=24075 -recol4d=12547 -model1=model_230_idk -model2=model_185_obj_wear -model3=model_250_idk -model4=model_299_npc -model5=model_159_npc -model6=model_179_obj_wear -model7=model_275_idk -head1=model_63_idk_head -head2=model_82_idk_head - -[npc_361] -name=Woman -desc=One of RuneScapes' many citizens. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -op2=Attack -vislevel=12 -recol1s=14801 -recol1d=12547 -recol2s=2340 -recol2d=6208 -recol3s=24075 -recol3d=12547 -model1=model_404_npc -model2=model_478_npc -model3=model_351_idk -model4=model_353_idk -model5=model_437_idk -model6=model_358_idk -head1=model_121_npc_head -respawnrate=100 -hitpoints=13 -attack=10 -strength=10 -defence=10 -param=defend_sound,female_hit -param=death_sound,female_death - [npc_365] name=Paladin desc=A military man. @@ -5626,10 +5524,10 @@ model9=model_518_obj_wear model10=model_523_npc model11=model_3330_obj_wear respawnrate=100 -hitpoints=57 -attack=54 -strength=54 -defence=54 +hitpoints=13 +attack=63 +defence=63 +strength=63 param=attackrate,5 param=attackbonus,20 param=strengthbonus,22 @@ -5643,6 +5541,9 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash // param=defend_sound,blade3 +// stats taken here +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1144 +// param stats is guess. [npc_368] vislevel=hide @@ -5672,37 +5573,6 @@ head2=model_80_idk_head wanderrange=0 moverestrict=nomove -[npc_374] -name=Ogre -desc=Big, ugly, and smelly. -size=2 -walkanim=ogre_walk -readyanim=ogre_ready -op2=Attack -vislevel=53 -model1=model_2878_npc -model2=model_2874_npc -respawnrate=100 -hitpoints=60 -attack=54 -strength=54 -defence=54 -param=attackbonus,8 -param=strengthbonus,6 -param=stabdefence,19 -param=slashdefence,23 -param=crushdefence,24 -param=damagetype,^crush_style -param=attack_anim,ogre_attack -param=defend_anim,ogre_block -param=death_anim,ogre_death -param=attack_sound,giant_attack -param=defend_sound,giant_hit -param=death_sound,giant_death -param=death_drop,big_bones -huntmode=cowardly -huntrange=2 - [npc_382] vislevel=hide walkanim=dwarf_walk @@ -5793,6 +5663,7 @@ param=attack_sound,cow_attack param=defend_sound,cow_hit param=death_sound,cow_death category=cow +// osrs stats and Vislvl match 1:1 [npc_401] vislevel=hide @@ -5889,597 +5760,45 @@ param=strengthbonus,10 param=stabdefence,46 param=slashdefence,50 param=crushdefence,45 -param=magicdefence,-12 -param=rangedefence,45 -param=damagetype,^slash_style -param=attack_anim,human_sword_slash -param=defend_anim,human_sword_defend2 -param=attack_sound,stabsword_slash -param=defend_sound,animated_hit -param=death_sound,animated_death -param=death_drop,null - -[npc_500] -vislevel=hide -name=Mosol Rei -desc=Slightly under dressed. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_staffready -op1=Talk-to -recol1s=14801 -recol1d=20804 -recol2s=24075 -recol2d=20804 -recol3s=24075 -recol3d=20804 -model1=model_206_idk -model2=model_249_idk -model3=model_315_npc -model4=model_173_npc -model5=model_176_idk -model6=model_279_npc -model7=model_181_idk -model8=model_553_npc -head1=model_46_idk_head -head2=model_81_idk_head - -[npc_501] -vislevel=hide -name=Zadimus' spirit. -desc=The animated spirit of a soul not at rest. -hasalpha=yes -walkanim=ghost_walk -readyanim=ghost_ready -hasalpha=yes -op1=Talk-to -model1=model_2962_npc -model2=model_2964_npc -model3=model_2965_npc -head1=model_27_npc_head -param=undead,^true -param=death_anim,ghost_death -param=death_sound,ghost_death - -[npc_502] -name=Undead One -desc=It rattles when it walks. -walkanim=skeleton_walk -readyanim=skeleton_ready -op2=Attack -vislevel=55 -recol1s=29562 -recol1d=22218 -model1=model_2944_npc -wanderrange=3 -maxrange=20 -respawnrate=100 -hitpoints=47 -attack=55 -strength=55 -defence=55 -param=attack_anim,skeleton_attack -param=defend_anim,skeleton_block -param=death_anim,skeleton_death -param=attack_sound,skeleton_attack -param=defend_sound,skelly_hit -param=death_sound,skeleton_death -param=undead,^true -huntmode=cowardly -huntrange=1 -category=undead_one - -[npc_503] -name=Undead One -desc=A minion of Rashiliyia. -walkanim=skeleton_walk -readyanim=skeleton_ready -op2=Attack -vislevel=47 -recol1s=29562 -recol1d=26515 -model1=model_2944_npc -model2=model_2946_npc -wanderrange=3 -maxrange=20 -respawnrate=100 -hitpoints=47 -attack=63 -strength=63 -defence=63 -param=attack_anim,skeleton_attack -param=defend_anim,skeleton_block -param=death_anim,skeleton_death -param=attack_sound,skeleton_attack -param=defend_sound,skelly_hit -param=death_sound,skeleton_death -param=undead,^true -huntmode=cowardly -huntrange=1 -category=undead_one - -[npc_504] -name=Undead One -desc=The animated dead, one of Rashiliyias' minions. -walkanim=zombie_walk -readyanim=zombie_ready -op2=Attack -vislevel=50 -recol1s=4526 -recol1d=12777 -recol2s=4322 -recol2d=8417 -recol3s=10240 -recol3d=7142 -recol4s=28538 -recol4d=24393 -recol5s=2081 -recol5d=9408 -model1=model_2931_npc -respawnrate=100 -hitpoints=47 -attack=63 -strength=63 -defence=63 -param=damagetype,^slash_style -param=attack_anim,zombie_attack -param=defend_anim,zombie_block -param=death_anim,zombie_death -param=attack_sound,zombie_attack -param=defend_sound,zombie_hit -param=death_sound,zombie_death -param=undead,^true -param=death_drop,null -huntmode=cowardly -huntrange=1 -category=undead_one - -[npc_505] -name=Undead One -desc=The animated dead, one of Rashiliyias' minions. -walkanim=zombie_walk -readyanim=zombie_ready -op2=Attack -vislevel=62 -recol1s=4526 -recol1d=11690 -recol2s=4322 -recol2d=8417 -recol3s=10240 -recol3d=26545 -recol4s=28538 -recol4d=24393 -recol5s=2081 -recol5d=9408 -model1=model_2931_npc -model2=model_2932_npc -wanderrange=3 -maxrange=20 -respawnrate=100 -hitpoints=59 -attack=65 -strength=65 -defence=65 -param=attackbonus,4 -param=strengthbonus,5 -param=damagetype,^slash_style -param=attack_anim,zombie_attack -param=defend_anim,zombie_block -param=death_anim,zombie_death -param=attack_sound,zombie_attack -param=defend_sound,zombie_hit -param=death_sound,zombie_death -param=undead,^true -param=death_drop,null -huntmode=cowardly -huntrange=1 -category=undead_one - -[npc_506] -vislevel=hide -name=Rashiliyia -desc=The animated spirit of Rashiliyia the Zombie Queen. -walkanim=ghost_walk -readyanim=ghost_ready -hasalpha=yes -op1=Talk-to -recol1s=6144 -recol1d=3363 -recol2s=15855 -recol2d=14724 -recol3s=24075 -recol3d=15979 -recol4s=6273 -recol4d=20104 -recol5s=20870 -recol5d=8712 -recol6s=12352 -recol6d=3363 -model1=model_2960_npc -model2=model_2963_npc -model3=model_2965_npc -head1=model_113_idk_head -param=undead,^true -param=death_anim,ghost_death -param=death_sound,ghost_death - -[npc_507] -name=Nazastarool -desc=A giant zombie of huge strength and devastating power. -walkanim=zombie_walk -readyanim=zombie_ready -resizev=190 -resizeh=190 -op2=Attack -vislevel=86 -recol1s=4526 -recol1d=11690 -recol2s=4322 -recol2d=8417 -recol3s=10240 -recol3d=26545 -recol4s=28538 -recol4d=24393 -recol5s=2081 -recol5d=9408 -model1=model_2931_npc -hitpoints=70 -attack=85 -strength=80 -defence=80 -magic=0 -ranged=0 -param=damagetype,^slash_style -param=attack_anim,zombie_attack -param=defend_anim,zombie_block -param=death_anim,zombie_death -param=attack_sound,zombie_attack -param=defend_sound,zombie_hit -param=death_sound,zombie_death -param=undead,^true - -[npc_508] -name=Nazastarool -desc=A giant skeleton of huge strength and devastating power. -walkanim=skeleton_walk -readyanim=skeleton_ready -resizev=190 -resizeh=190 -op2=Attack -vislevel=65 -recol1s=29562 -recol1d=26515 -model1=model_2944_npc -model2=model_2946_npc -hitpoints=70 -attack=58 -strength=54 -defence=58 -magic=0 -ranged=0 -param=attackbonus,15 -param=strengthbonus,15 -param=stabdefence,5 -param=slashdefence,5 -param=crushdefence,5 -param=magicdefence,5 -param=rangedefence,5 -param=damagetype,^slash_style -param=attack_anim,skeleton_attack -param=defend_anim,skeleton_block -param=death_anim,skeleton_death -param=attack_sound,skeleton_attack -param=defend_sound,skelly_hit -param=death_sound,skeleton_death -param=undead,^true - -[npc_509] -name=Nazastarool -desc=A giant ghost of huge strength and devastating power. -hasalpha=yes -walkanim=ghost_walk -readyanim=ghost_ready -resizev=190 -resizeh=190 -op2=Attack -vislevel=88 -model1=model_2961_npc -model2=model_2964_npc -model3=model_2965_npc -head1=model_10_npc_head -hitpoints=80 -attack=85 -strength=80 -defence=80 -magic=0 -ranged=0 -param=damagetype,^slash_style -param=attack_anim,ghost_attack -param=defend_anim,ghost_block -param=death_anim,ghost_death -param=attack_sound,ghost_attack -param=defend_sound,ghost_hit -param=death_sound,ghost_death -param=death_drop,null -param=undead,^true - -[captain_shanks] -vislevel=hide -name=Captain Shanks -desc=He's the Captain of the 'Lady of the Waves'. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=24075 -recol1d=20804 -recol2s=2340 -recol2d=4234 -recol3s=14724 -recol3d=4334 -recol4s=14801 -recol4d=24075 -recol5s=6273 -recol5d=4226 -model1=model_214_idk -model2=model_249_idk -model3=model_292_idk -model4=model_151_idk -model5=model_176_idk -model6=model_254_idk -model7=model_181_idk -model8=model_194_npc -head1=model_52_idk_head -head2=model_81_idk_head -head3=model_37_npc_head - -[digsite_workman] -vislevel=hide -name=Digsite workman -desc=This person is working on the site. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -op3=Steal-from -recol1s=14801 -recol1d=8320 -recol2s=32735 -recol2d=8320 -model1=model_235_idk -model2=model_246_idk -model3=model_302_npc -model4=model_173_npc -model5=model_179_obj_wear -model6=model_274_idk -model7=model_181_idk -model8=model_185_obj_wear -head1=model_67_idk_head - -[digsite_workman_cave] -vislevel=hide -name=Digsite workman -desc=This person is working on the site. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -op3=Steal-from -recol1s=14801 -recol1d=8320 -recol2s=32735 -recol2d=8320 -model1=model_235_idk -model2=model_246_idk -model3=model_302_npc -model4=model_173_npc -model5=model_179_obj_wear -model6=model_274_idk -model7=model_181_idk -model8=model_185_obj_wear -head1=model_67_idk_head - -[student1] -vislevel=hide -name=Student -desc=A student busily digging. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=14724 -recol1d=5636 -recol2s=2340 -recol2d=23171 -model1=model_217_idk -model2=model_249_idk -model3=model_292_idk -model4=model_324_idk -model5=model_151_idk -model6=model_179_obj_wear -model7=model_254_idk -model8=model_185_obj_wear -head1=model_55_idk_head -head2=model_81_idk_head - -[student2] -vislevel=hide -name=Student -desc=A student busily digging. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=24075 -recol1d=14594 -recol2s=14724 -recol2d=23937 -recol3s=2340 -recol3d=3171 -recol4s=24329 -recol4d=3171 -model1=model_215_idk -model2=model_246_idk -model3=model_292_idk -model4=model_322_idk -model5=model_163_idk -model6=model_179_obj_wear -model7=model_257_npc -model8=model_276_npc -head1=model_53_idk_head - -[student3] -vislevel=hide -name=Student -desc=A student busily digging. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=6273 -recol1d=24205 -recol2s=14724 -recol2d=20952 -recol3s=2340 -recol3d=7400 -model1=model_390_idk -model2=model_456_idk -model3=model_447_obj_wear -model4=model_332_idk -model5=model_356_obj_wear -model6=model_429_idk -model7=model_185_obj_wear -head1=model_113_idk_head -param=death_sound,female_death - -[examiner] -vislevel=hide -name=Examiner -desc=Upon examining the examiner you examine it is indeed an examiner! -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=6273 -recol1d=21921 -recol2s=14724 -recol2d=7311 -recol3s=2340 -recol3d=3171 -model1=model_378_idk -model2=model_418_npc -model3=model_470_idk -model4=model_421_idk -model5=model_358_idk -model6=model_348_idk -model7=model_353_idk -head1=model_103_idk_head -head2=model_137_npc_head -param=death_sound,female_death - -[archaeological_expert] -vislevel=hide -name=Archaeological expert -desc=An expert on archaeology. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=2340 -recol1d=22627 -recol2s=14801 -recol2d=11457 -recol3s=14724 -recol3d=16912 -recol4s=24075 -recol4d=11457 -model1=model_217_idk -model2=model_250_idk -model3=model_299_npc -model4=model_327_idk -model5=model_159_npc -model6=model_254_idk -model7=model_179_obj_wear -model8=model_185_obj_wear -head1=model_55_idk_head -head2=model_82_idk_head - -[panning_guide] -vislevel=hide -name=Panning guide -desc=A specialist in panning for gold. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=7298 -recol1d=3171 -recol2s=2340 -recol2d=11459 -recol3s=14724 -recol3d=14596 -model1=model_215_idk -model2=model_246_idk -model3=model_292_idk -model4=model_170_idk -model5=model_179_obj_wear -model6=model_254_idk -model7=model_276_npc -model8=model_185_obj_wear -model9=model_326_idk -head1=model_53_idk_head - -[crest_man] -vislevel=hide -name=Man -desc=A well dressed nobleman. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=2340 -recol1d=11627 -recol2s=14724 -recol2d=22226 -recol3s=8386 -recol3d=31649 -recol4s=15360 -recol4d=31649 -recol5s=14801 -recol5d=24075 -model1=model_215_idk -model2=model_281_obj_wear -model3=model_246_idk -model4=model_292_idk -model5=model_151_idk -model6=model_176_idk -model7=model_254_idk -model8=model_181_idk -model9=model_323_obj_wear -head1=model_53_idk_head - -[crest_chronozon] -size=3 -walkanim=demon_walk -readyanim=demon_ready -name=Chronozon -desc=Chronozon the blood demon. -op2=Attack -resizeh=110 -resizev=110 -vislevel=139 -recol1s=29596 -recol1d=18597 -recol2s=15393 -recol2d=18597 -model1=model_2942_npc -wanderrange=6 -maxrange=8 -respawnrate=60 -hitpoints=60 -attack=173 -strength=172 -defence=173 +param=magicdefence,-12 +param=rangedefence,45 param=damagetype,^slash_style -param=attack_anim,demon_attack -param=defend_anim,demon_block -param=death_anim,demon_death -param=demonbane_vulnerable,yes -param=attack_sound,demon_attack -param=defend_sound,demon_hit -param=death_sound,demon_death -param=death_drop,ashes -huntmode=cowardly -huntrange=3 +param=attack_anim,human_sword_slash +param=defend_anim,human_sword_defend2 +param=attack_sound,stabsword_slash +param=defend_sound,animated_hit +param=death_sound,animated_death +param=death_drop,null +// osrs stats and Vislvl match 1:1 + +[captain_shanks] +vislevel=hide +name=Captain Shanks +desc=He's the Captain of the 'Lady of the Waves'. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=24075 +recol1d=20804 +recol2s=2340 +recol2d=4234 +recol3s=14724 +recol3d=4334 +recol4s=14801 +recol4d=24075 +recol5s=6273 +recol5d=4226 +model1=model_214_idk +model2=model_249_idk +model3=model_292_idk +model4=model_151_idk +model5=model_176_idk +model6=model_254_idk +model7=model_181_idk +model8=model_194_npc +head1=model_52_idk_head +head2=model_81_idk_head +head3=model_37_npc_head [imp] name=Imp @@ -6512,75 +5831,7 @@ param=death_sound,imp_death param=death_drop,ashes param=retreat,4 // https://oldschool.runescape.wiki/w/Demon_(attribute) - -[npc_726] -vislevel=hide -name=Man -desc=One of RuneScapes' many citizens. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=14801 -recol1d=24075 -recol2s=2340 -recol2d=6208 -model1=model_235_idk -model2=model_185_obj_wear -model3=model_250_idk -model4=model_310_idk -model5=model_173_npc -model6=model_176_idk -model7=model_275_idk -head1=model_67_idk_head -head2=model_82_idk_head - -[npc_727] -vislevel=hide -name=Man -desc=One of RuneScapes' many citizens. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=14801 -recol1d=24075 -recol2s=2340 -recol2d=6208 -recol3s=14724 -recol3d=21000 -model1=model_235_idk -model2=model_185_obj_wear -model3=model_250_idk -model4=model_310_idk -model5=model_151_idk -model6=model_179_obj_wear -model7=model_275_idk -head1=model_67_idk_head -head2=model_82_idk_head - -[npc_730] -vislevel=hide -name=Man -desc=One of RuneScapes' many citizens. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -recol1s=14801 -recol1d=12547 -recol2s=2340 -recol2d=6208 -recol3s=14724 -recol3d=16808 -recol4s=24075 -recol4d=12547 -model1=model_214_idk -model2=model_185_obj_wear -model3=model_250_idk -model4=model_310_idk -model5=model_173_npc -model6=model_179_obj_wear -model7=model_275_idk -head1=model_52_idk_head -head2=model_82_idk_head +// osrs stats and Vislvl match 1:1 [bartender_dancingdonkey] vislevel=hide @@ -6675,6 +5926,7 @@ param=damagetype,^crush_style param=defend_sound,ice_warrior_hit param=death_sound,female_death param=death_drop,ice_gloves +// Stats match osrs version but our version Vislvl is different. [pirate_guard] name=Pirate Guard @@ -6716,6 +5968,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_slash // param=defend_sound,big_bar_mail +// osrs stats and Vislvl match 1:1 [donovan] vislevel=hide @@ -7241,13 +6494,15 @@ hitpoints=16 attack=7 strength=7 defence=7 +magic=0 +ranged=0 param=damagetype,^crush_style -param=attack_anim,human_blunt_crush param=defend_anim,human_unarmedblock param=attack_sound,baxe_crush huntmode=aggressive_melee huntrange=1 // Unknown reason osrs side this npc use unarmed attacks --attack seq_422 defend seq_424-- +// Stats match osrs version but our version Vislvl is different. [npc_828] name=Mercenary @@ -7284,6 +6539,8 @@ hitpoints=60 attack=32 strength=32 defence=39 +magic=0 +ranged=0 param=attackbonus,9 param=strengthbonus,14 param=stabdefence,17 @@ -7291,10 +6548,11 @@ param=slashdefence,15 param=crushdefence,19 param=magicdefence,-3 param=rangedefence,19 -param=damagetype,^slash_style +param=damagetype,^crush_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +// Stats match osrs version but our version Vislvl is different. [npc_829] name=Mercenary @@ -7331,6 +6589,8 @@ hitpoints=60 attack=32 strength=32 defence=39 +magic=0 +ranged=0 param=attackbonus,9 param=strengthbonus,14 param=stabdefence,17 @@ -7338,10 +6598,11 @@ param=slashdefence,15 param=crushdefence,19 param=magicdefence,-3 param=rangedefence,19 -param=damagetype,^slash_style +param=damagetype,^crush_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +// Stats match osrs version but our version Vislvl is different. [npc_830] name=Mercenary Captain @@ -7383,6 +6644,8 @@ hitpoints=80 attack=32 strength=29 defence=32 +magic=0 +ranged=0 param=attackbonus,9 param=strengthbonus,14 param=stabdefence,17 @@ -7394,6 +6657,7 @@ param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +// Stats match osrs version but our version Vislvl is different. [npc_831] name=Captain Siad @@ -7479,10 +6743,26 @@ model9=model_517_obj_wear head1=model_57_obj_wear wanderrange=3 maxrange=3 -// TODO stats data +hitpoints=60 +attack=32 +strength=32 +defence=32 +magic=0 +ranged=0 +param=attackbonus,9 +param=strengthbonus,14 +param=stabdefence,17 +param=slashdefence,15 +param=crushdefence,19 +param=magicdefence,-3 +param=rangedefence,19 +param=damagetype,^crush_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +// https://oldschool.runescape.wiki/w/Guard_(Desert_Mining_Camp)#Brown_hair +// stats taken here and param taken osrs desert mining camp guards. +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4654 [npc_852] name=Ogre chieftain @@ -7518,6 +6798,7 @@ param=death_sound,giant_death param=death_drop,big_bones huntmode=cowardly huntrange=2 +// Stats match osrs version but our version Vislvl is different. [npc_853] vislevel=hide @@ -7596,6 +6877,7 @@ param=attack_sound,mace_crush // param=defend_sound,blade3_mail param=death_sound,giant_death param=death_drop,big_bones +// Stats match osrs version but our version Vislvl is different. [npc_857] name=Ogre guard @@ -7608,14 +6890,26 @@ vislevel=74 model1=model_2880_npc model2=model_2874_npc head1=model_141_npc_head +respawnrate=100 +hitpoints=80 +attack=70 +strength=70 +defence=70 +param=attackrate,6 +param=attackbonus,22 +param=strengthbonus,20 +param=stabdefence,13 +param=slashdefence,24 +param=crushdefence,19 param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block param=death_anim,ogre_death -param=attack_sound,mace_crush -param=defend_sound,giant_hit +param=attack_sound,giant_attack +// param=defend_sound,blade3_mail param=death_sound,giant_death param=death_drop,big_bones +// param taken city guard attack param take normal ogre [npc_858] name=Ogre guard @@ -7628,14 +6922,26 @@ vislevel=74 model1=model_2880_npc model2=model_2874_npc head1=model_141_npc_head +respawnrate=100 +hitpoints=80 +attack=70 +strength=70 +defence=70 +param=attackrate,6 +param=attackbonus,22 +param=strengthbonus,20 +param=stabdefence,13 +param=slashdefence,24 +param=crushdefence,19 param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block param=death_anim,ogre_death -param=attack_sound,mace_crush -param=defend_sound,giant_hit +param=attack_sound,giant_attack +// param=defend_sound,blade3_mail param=death_sound,giant_death param=death_drop,big_bones +// param taken city guard attack param take normal ogre [npc_859] name=Ogre guard @@ -7648,14 +6954,26 @@ vislevel=74 model1=model_2880_npc model2=model_2874_npc head1=model_141_npc_head +respawnrate=100 +hitpoints=80 +attack=70 +strength=70 +defence=70 +param=attackrate,6 +param=attackbonus,22 +param=strengthbonus,20 +param=stabdefence,13 +param=slashdefence,24 +param=crushdefence,19 param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block param=death_anim,ogre_death -param=attack_sound,mace_crush -param=defend_sound,giant_hit +param=attack_sound,giant_attack +// param=defend_sound,blade3_mail param=death_sound,giant_death param=death_drop,big_bones +// param taken city guard attack param take normal ogre [npc_860] name=Ogre guard @@ -7668,14 +6986,26 @@ vislevel=74 model1=model_2880_npc model2=model_2874_npc head1=model_141_npc_head +respawnrate=100 +hitpoints=80 +attack=70 +strength=70 +defence=70 +param=attackrate,6 +param=attackbonus,22 +param=strengthbonus,20 +param=stabdefence,13 +param=slashdefence,24 +param=crushdefence,19 param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block param=death_anim,ogre_death -param=attack_sound,mace_crush -param=defend_sound,giant_hit +param=attack_sound,giant_attack +// param=defend_sound,blade3_mail param=death_sound,giant_death param=death_drop,big_bones +// param taken city guard attack param take normal ogre [npc_861] name=Ogre guard @@ -7688,14 +7018,28 @@ vislevel=74 model1=model_2880_npc model2=model_2874_npc head1=model_141_npc_head +respawnrate=100 +hitpoints=80 +attack=70 +strength=70 +defence=70 +param=attackrate,6 +param=attackbonus,22 +param=strengthbonus,20 +param=stabdefence,13 +param=slashdefence,24 +param=crushdefence,19 param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block param=death_anim,ogre_death -param=attack_sound,mace_crush -param=defend_sound,giant_hit +param=attack_sound,giant_attack +// param=defend_sound,blade3_mail param=death_sound,giant_death param=death_drop,big_bones +// param taken city guard attack param take normal ogre +// stats taken here -- npc_4368 - npc_4372 -- +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc [npc_862] name=City guard @@ -7727,6 +7071,7 @@ param=attack_sound,mace_crush param=defend_sound,giant_hit param=death_sound,giant_death param=death_drop,big_bones +// Stats match osrs version but our version Vislvl is different. [npc_863] vislevel=hide @@ -7739,7 +7084,7 @@ op1=Talk-to model1=model_2999_npc head1=model_146_npc_head param=death_anim,skavid_death -// param=death_sound,imp_death +param=death_sound,imp_death [npc_864] vislevel=hide @@ -7853,6 +7198,7 @@ param=attack_sound,mace_stab // param=defend_sound,blade3_mail param=death_sound,giant_death param=death_drop,big_bones +// Stats match osrs version but our version Vislvl is different. [npc_871] name=Ogre shaman @@ -7866,8 +7212,11 @@ vislevel=113 model1=model_2879_npc model2=model_2877_npc head1=model_141_npc_head -// TODO respawnrate=102 +hitpoints=99 +attack=99 +strength=99 +defence=99 param=attack_anim,ogre_attack param=magicattack_anim,ogre_attack param=defend_anim,ogre_block @@ -7875,7 +7224,8 @@ param=death_anim,ogre_death param=attack_sound,giant_attack param=defend_sound,giant_hit param=death_sound,giant_death -param=death_drop,big_bones +// TODO monster examine spell +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4386 - 4396 [npc_872] vislevel=hide @@ -7920,6 +7270,11 @@ model2=model_2874_npc head1=model_141_npc_head wanderrange=2 maxrange=4 +hitpoints=60 +attack=62 +strength=60 +defence=63 +// TODO attackrate some trader can attack player. param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block @@ -7928,7 +7283,8 @@ param=attack_sound,giant_attack param=defend_sound,giant_hit param=death_sound,giant_death param=death_drop,big_bones -// TODO +// stats taken here npc_4401 - npc_4405 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc [npc_874] name=Ogre merchant @@ -7946,6 +7302,11 @@ model2=model_2874_npc head1=model_141_npc_head wanderrange=2 maxrange=4 +hitpoints=60 +attack=62 +strength=60 +defence=63 +// TODO attackrate some trader can attack player. param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block @@ -7954,7 +7315,8 @@ param=attack_sound,giant_attack param=defend_sound,giant_hit param=death_sound,giant_death param=death_drop,big_bones -// TODO +// stats taken here npc_4401 - npc_4405 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc [npc_875] name=Ogre trader @@ -7972,6 +7334,11 @@ model2=model_2874_npc head1=model_141_npc_head wanderrange=2 maxrange=4 +hitpoints=60 +attack=62 +strength=60 +defence=63 +// TODO attackrate some trader can attack player. param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block @@ -7980,7 +7347,8 @@ param=attack_sound,giant_attack param=defend_sound,giant_hit param=death_sound,giant_death param=death_drop,big_bones -// TODO +// stats taken here npc_4401 - npc_4405 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc [npc_876] name=Ogre trader @@ -7998,6 +7366,11 @@ model2=model_2874_npc head1=model_141_npc_head wanderrange=3 maxrange=5 +hitpoints=60 +attack=62 +strength=60 +defence=63 +// TODO attackrate some trader can attack player. param=damagetype,^crush_style param=attack_anim,ogre_attack param=defend_anim,ogre_block @@ -8006,7 +7379,8 @@ param=attack_sound,giant_attack param=defend_sound,giant_hit param=death_sound,giant_death param=death_drop,big_bones -// TODO +// stats taken here npc_4401 - npc_4405 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc [npc_928] vislevel=hide @@ -8068,7 +7442,7 @@ head1=model_52_idk_head head2=model_82_idk_head wanderrange=1 maxrange=30 -// TODO respawnrate? +// respawnrate=50 hitpoints=65 attack=57 strength=61 @@ -8077,11 +7451,13 @@ magic=65 ranged=0 param=attackbonus,7 param=strengthbonus,3 -param=rangebonus,7 +param=damagetype,^crush_style param=attack_anim,human_staff_pound param=defend_anim,human_staff_def param=attack_sound,staff_hit // osrs attack sound staff_double +// TODO: check respawn time. +// osrs stats and Vislvl match 1:1 [npc_930] name=Ungadulu @@ -8122,14 +7498,17 @@ strength=147 defence=147 magic=0 ranged=0 +param=attackbonus,7 param=strengthbonus,3 -param=rangebonus,7 +param=damagetype,^crush_style param=attack_anim,human_staff_pound param=defend_anim,human_staff_def param=attack_sound,staff_hit // osrs attack sound staff_double // sound and animation data taken normal version ungadulu // wander distance attack distance missing. +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3958 +// Stats match osrs version but our version Vislvl is different. [jungle_savage] name=Jungle Savage @@ -8176,6 +7555,7 @@ param=defend_anim,human_spear_block param=attack_sound,staff_stab huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [nezikchened] name=Nezikchened @@ -8205,10 +7585,11 @@ param=attack_anim,demon_attack param=defend_anim,demon_block param=death_anim,demon_death param=demonbane_vulnerable,yes -param=attack_sound,demon_attack -param=defend_sound,demon_hit -param=death_sound,demon_death -param=death_drop,ashes +param=attack_sound,black_demon_attack +param=defend_sound,black_demon_hit +param=death_sound,black_demon_death +param=death_drop,null +// osrs stats and Vislvl match 1:1 [npc_935] name=Viyeldi @@ -8231,6 +7612,8 @@ model5=model_534_obj_wear model6=model_209_npc head1=model_54_npc_head head2=model_44_obj_wear +wanderrange=0 +moverestrict=nomove // TODO respawnrate? hitpoints=80 attack=62 @@ -8239,6 +7622,15 @@ defence=70 magic=0 ranged=0 param=attackbonus,7 +param=strengthbonus,3 +param=damagetype,^crush_style +// param=attack_anim,human_staff_pound +param=defend_anim,human_staff_def +// param=attack_sound,staff_hit +// TODO Try to find out if this npc can be killed on the osrs side somehow.... +// and also find out if you can make this npc attack the player.... +// try to find out if the npc is using any sounds on the osrs side if possible. +// defend animation https://discord.com/channels/953326730632904844/1126857544523063367/1300620868782788709 [npc_936] name=San Tojalon @@ -8275,12 +7667,15 @@ param=slashdefence,22 param=crushdefence,20 param=magicdefence,-1 param=rangedefence,20 +param=damagetype,^stab_style param=attack_anim,skeleton_trans_attack param=defend_anim,skeleton_trans_block param=death_anim,skeleton_trans_death param=attack_sound,skeleton_attack param=defend_sound,skelly_hit param=death_sound,skeleton_death +param=death_drop,null +// Stats match osrs version but our version Vislvl is different. [npc_937] name=Irvig Senay @@ -8317,12 +7712,15 @@ param=slashdefence,31 param=crushdefence,29 param=magicdefence,-1 param=rangedefence,29 +param=damagetype,^slash_style param=attack_anim,skeleton_trans_attack param=defend_anim,skeleton_trans_block param=death_anim,skeleton_trans_death param=attack_sound,skeleton_attack param=defend_sound,skelly_hit param=death_sound,skeleton_death +param=death_drop,null +// osrs stats and Vislvl match 1:1 [npc_938] name=Ranalph Devere @@ -8360,12 +7758,15 @@ param=stabdefence,38 param=slashdefence,40 param=crushdefence,36 param=rangedefence,38 +param=damagetype,^slash_style param=attack_anim,skeleton_trans_attack param=defend_anim,skeleton_trans_block param=death_anim,skeleton_trans_death param=attack_sound,skeleton_attack param=defend_sound,skelly_hit param=death_sound,skeleton_death +param=death_drop,null +// Stats match osrs version but our version Vislvl is different. [npc_939] name=Boulder @@ -8393,7 +7794,17 @@ model1=model_2961_npc model2=model_2964_npc model3=model_2965_npc head1=model_10_npc_head +hitpoints=150 +attack=165 +strength=168 +defence=167 +ranged=0 +magic=0 param=undead,^true +param=death_anim,ghost_death +param=death_sound,ghost_death +param=death_drop,null +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3968 [green_dragon] size=4 @@ -8431,6 +7842,9 @@ param=death_sound,dragon_death param=death_drop,dragon_bones huntmode=cowardly huntrange=4 +// stats match osrs 1:1 but defence stats don't. +// but the defense stats matches according to this site 1:1 +// http://web.archive.org/web/20190722072117/https://oldschool.runescape.wiki/w/Green_dragon [cow_3] size=2 @@ -8466,6 +7880,7 @@ param=attack_sound,cow_attack param=defend_sound,cow_hit param=death_sound,cow_death category=cow +// osrs stats and Vislvl match 1:1 [zamorak_wizard] name=Zamorak Wizard @@ -8493,16 +7908,18 @@ model6=model_170_idk model7=model_176_idk model8=model_265_obj_wear model9=model_544_obj_wear +// TODO respawnrates wanderrange=3 -attackrange=5 maxrange=5 -hitpoints=76 +attackrange=5 +hitpoints=80 attack=24 strength=24 defence=24 magic=80 timer=20 param=magicdefence,3 +// Stats match osrs version but our version Vislvl is different. [poison_spider_observatory] walkanim=giantspider_walk @@ -8534,4 +7951,5 @@ param=death_sound,insect_death param=death_drop,null // Tested this npc in osrs, doesnt seem to poison? Seems like the chests have a chance to poison huntmode=cowardly -huntrange=1 \ No newline at end of file +huntrange=1 +// TODO monster examine spell \ No newline at end of file diff --git a/data/src/scripts/_unpack/all.obj b/data/src/scripts/_unpack/all.obj index b7382ab781..e7b55aaffe 100644 --- a/data/src/scripts/_unpack/all.obj +++ b/data/src/scripts/_unpack/all.obj @@ -9,7 +9,6 @@ model=model_2559_obj 2dyan=1260 2dxan=444 weight=1lb -tradeable=yes [bear_fur] name=Fur @@ -22,7 +21,6 @@ model=model_2631_obj 2dxan=388 cost=10 weight=3kg -tradeable=yes [silk] name=Silk @@ -35,7 +33,6 @@ recol1d=22870 2dzoom=1360 2dxan=368 weight=1kg -tradeable=yes [spade] name=Spade @@ -51,7 +48,6 @@ womanwear=model_496_obj_wear,0 2dxan=332 weight=4lb iop1=Dig -tradeable=yes [rope] name=Rope @@ -66,7 +62,6 @@ recol1d=7296 2dyan=1976 2dxan=188 weight=3lb -tradeable=yes [flier] name=Flier @@ -79,7 +74,6 @@ model=model_2600_obj 2dyan=120 2dxan=380 weight=15g -tradeable=yes [grey_wolf_fur] model=model_2631_obj @@ -94,7 +88,6 @@ desc=This would make warm clothing. cost=50 weight=3kg members=yes -tradeable=yes [plank] model=model_2694_obj @@ -105,7 +98,6 @@ desc=A plank of wood! 2dxan=356 weight=800g category=category_475 -tradeable=yes [christmas_cracker] name=Christmas cracker @@ -117,7 +109,6 @@ model=model_2637_obj 2dyan=1728 2dxan=272 weight=200g -tradeable=yes [obj_964] name=Skull @@ -132,7 +123,6 @@ recol1d=28433 2dzan=1996 2dxan=160 weight=80g -tradeable=yes [obj_966] name=Tile @@ -144,7 +134,6 @@ model=model_2617_obj 2dyan=100 2dxan=340 weight=70g -tradeable=yes [obj_968] name=Rock @@ -156,7 +145,6 @@ model=model_2571_obj 2dyan=20 2dxan=204 weight=1kg -tradeable=yes [papyrus] name=Papyrus @@ -170,7 +158,6 @@ womanwear=model_532_obj_wear,6 2dxan=248 weight=20g members=yes -tradeable=yes [obj_972] name=Papyrus @@ -182,6 +169,7 @@ womanwear=model_532_obj_wear,6 2dxan=248 weight=20g members=yes +tradeable=no [charcoal] name=Charcoal @@ -195,7 +183,6 @@ womanwear=model_494_obj_wear,6 2dyan=220 2dxan=288 weight=5g -tradeable=yes [machete] name=Machete @@ -216,7 +203,6 @@ manwear=model_566_obj_wear,0 womanwear=model_566_obj_wear,6 category=weapon_slash weight=3lb -tradeable=yes param=slashattack,6 param=crushattack,-2 param=strengthbonus,5 @@ -240,7 +226,6 @@ recol3d=12448 2dyan=36 2dxan=116 weight=1g -tradeable=yes // jagex name [highwayman_mask] @@ -249,7 +234,6 @@ model=model_2500_obj 2dzoom=290 2dyan=224 2dxan=488 -tradeable=yes [disk_of_returning] name=Disk of returning @@ -262,7 +246,6 @@ model=model_2724_obj 2dzan=260 2dxan=460 weight=1lb -tradeable=yes [brass_key] name=Brass key @@ -276,7 +259,6 @@ recol1d=22945 2dyan=20 2dxan=328 weight=10g -tradeable=yes [half_key1] name=Half of a key @@ -289,7 +271,6 @@ model=model_2414_obj 2dyan=8 2dxan=296 weight=5g -tradeable=yes [half_key2] name=Half of a key @@ -302,7 +283,6 @@ model=model_2415_obj 2dyan=1980 2dxan=292 weight=5g -tradeable=yes [crystal_key] name=Crystal key @@ -317,7 +297,6 @@ recol1d=14800 2dyan=20 2dxan=328 weight=10g -tradeable=yes [muddy_key] name=Muddy key @@ -331,7 +310,6 @@ recol1d=15621 2dyan=20 2dxan=328 weight=10g -tradeable=yes [sinister_key] name=Sinister key @@ -346,7 +324,6 @@ recol1d=4226 2dyan=20 2dxan=328 weight=10g -tradeable=yes [coins] name=Coins @@ -367,7 +344,6 @@ count6=coins_100,100 count7=coins_250,250 count8=coins_1000,1000 count9=coins_10000,10000 -tradeable=yes [coins_2] model=model_2485_obj @@ -467,7 +443,6 @@ wearpos=torso manwear=model_305_obj_wear,0 womanwear=model_467_obj_wear,0 weight=1lb -tradeable=yes [brass_necklace] cost=30 @@ -486,7 +461,6 @@ wearpos=front manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=10g -tradeable=yes [blue_skirt] cost=2 @@ -503,7 +477,6 @@ wearpos=legs manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=2lb -tradeable=yes [pink_skirt] cost=2 @@ -520,7 +493,6 @@ wearpos=legs manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=2lb -tradeable=yes [black_skirt] cost=2 @@ -537,7 +509,6 @@ wearpos=legs manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=2lb -tradeable=yes [eyepatch] name=Eye patch @@ -555,7 +526,6 @@ manhead=model_68_obj_wear womanhead=model_126_obj_wear weight=6g members=yes -tradeable=yes [zamorak_monk_bottom] name=Robe of zamorak @@ -573,7 +543,6 @@ manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=2lb members=yes -tradeable=yes param=zamorakitem,1 param=magicattack,2 param=magicdefence,3 @@ -598,7 +567,6 @@ manwear2=model_292_idk womanwear2=model_456_idk weight=2lb members=yes -tradeable=yes param=zamorakitem,1 param=magicattack,2 param=magicdefence,3 @@ -624,6 +592,7 @@ param=slashdefence,7 param=crushdefence,7 param=magicdefence,7 param=rangedefence,7 +tradeable=no [iban_staff] members=yes @@ -652,14 +621,14 @@ param=slashdefence,3 param=crushdefence,1 param=magicdefence,10 param=strengthbonus,50 -param=ready_baseanim,human_staffready param=attackrate,5 +param=ready_baseanim,human_staffready +param=crushattack_anim,human_blunt_crush +param=defend_anim,human_ibanstaff_2h_defend // param=crushattack_anim,earthwarrior_chop -// param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 -param=crushattack_anim,human_trans_axe_chop -param=defend_anim,human_ibanstaff_2h_defend // osrs use attack seq_401 and defend seq_403 + the weapon was already 1 handed in 2006 +tradeable=no [broken_iban_staff] name=Broken iban staff @@ -672,6 +641,7 @@ model=model_2835_obj members=yes cost=20 weight=4lb +tradeable=no [obj_1411] name=Farmers fork @@ -682,7 +652,6 @@ model=model_2411_obj 2dyan=904 2dxan=812 weight=5lb -tradeable=yes [obj_1413] name=Halberd @@ -693,7 +662,6 @@ model=model_2791_obj 2dyan=400 2dxan=224 weight=10lb -tradeable=yes [obj_1415] name=Warhammer @@ -704,7 +672,6 @@ model=model_2731_obj 2dyan=456 2dxan=344 weight=4lb -tradeable=yes [obj_1417] name=Javelin @@ -715,7 +682,6 @@ model=model_2763_obj 2dyan=1964 2dxan=268 weight=3lb -tradeable=yes [scythe] name=Scythe @@ -744,8 +710,10 @@ param=slashattack_anim,human_scythe_slash param=crushattack_anim,human_scythe_lunge param=stabattack_anim,human_scythe_sweep param=defend_anim,human_scythe_block +param=stab_sound,scythe_slash param=slash_sound,scythe_slash param=crush_sound,scythe_slash +tradeable=no [archery_ticket] name=Archery ticket @@ -760,7 +728,6 @@ cost=25 members=yes stackable=yes weight=5g -tradeable=yes [obj_1465] name=Weapon poison @@ -775,6 +742,7 @@ recol1d=15871 2dxan=84 weight=20g members=yes +tradeable=no [sea_slug] cost=4 @@ -788,6 +756,7 @@ model=model_2658_obj 2dyan=140 2dxan=272 weight=8oz +tradeable=no [damp_sticks] name=Damp sticks @@ -803,6 +772,7 @@ recol1d=5251 2dxan=316 weight=3oz // todo: osrs has a respawnrate of 0. Not sure if its authentic, probably not? +tradeable=no [dry_sticks] name=Dry sticks @@ -818,6 +788,7 @@ recol1d=5251 2dxan=316 iop1=Rub-together weight=2oz +tradeable=no [seaslug_broken_glass] members=yes @@ -831,6 +802,7 @@ model=model_2676_obj 2dxan=412 cost=0 weight=2oz +tradeable=no [amulet_accuracy] name=Amulet of accuracy @@ -851,7 +823,6 @@ wearpos=front manwear=model_280_obj_wear,0 womanwear=model_444_obj_wear,0 weight=10g -tradeable=yes param=stabattack,4 param=slashattack,4 param=crushattack,4 @@ -870,7 +841,6 @@ members=yes cost=20 weight=10g category=category_715 -tradeable=yes [garlic] name=Garlic @@ -881,7 +851,6 @@ model=model_loc_3366_8 2dyan=116 2dxan=116 weight=1oz -tradeable=yes [ice_gloves] name=Ice gloves @@ -906,6 +875,7 @@ members=yes param=slashdefence,3 param=crushdefence,4 param=rangedefence,2 +tradeable=no [oily_fishing_rod] name=Oily fishing rod @@ -919,8 +889,10 @@ model=model_2828_obj 2dxan=328 weight=3lb members=yes +tradeable=no [obj_1589] +tradeable=no [dusty_key] name=Dusty key @@ -935,6 +907,7 @@ recol1d=22945 2dyan=20 2dxan=328 weight=10g +tradeable=no [jail_key] name=Jail key @@ -949,6 +922,7 @@ recol1d=22945 2dyan=20 2dxan=328 weight=10g +tradeable=no [water_skin4] name=Waterskin(4) @@ -963,7 +937,6 @@ model=model_2699_obj 2dyan=156 2dxan=52 members=yes -tradeable=yes [water_skin3] name=Waterskin(3) @@ -978,7 +951,6 @@ members=yes 2dzoom=780 2dyan=156 2dxan=52 -tradeable=yes [water_skin2] name=Waterskin(2) @@ -993,7 +965,6 @@ members=yes 2dzoom=780 2dyan=156 2dxan=52 -tradeable=yes [water_skin1] name=Waterskin(1) @@ -1008,7 +979,6 @@ members=yes 2dzoom=780 2dyan=156 2dxan=52 -tradeable=yes [water_skin0] name=Waterskin(0) @@ -1022,7 +992,6 @@ model=model_2699_obj 2dzoom=780 2dyan=156 2dxan=52 -tradeable=yes [desert_shirt] name=Desert shirt @@ -1043,7 +1012,6 @@ womanwear=model_456_idk,0 womanwear2=model_348_idk iop2=Wear weight=2lb -tradeable=yes [desert_robe] name=Desert robe @@ -1061,7 +1029,6 @@ iop2=Wear weight=2lb manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 -tradeable=yes [desert_boots] name=Desert boots @@ -1084,7 +1051,6 @@ weight=8oz members=yes manwear=model_185_obj_wear,0 womanwear=model_361_obj_wear,0 -tradeable=yes [obj_1839] name=Metal key @@ -1101,6 +1067,7 @@ recol1d=21071 2dyan=20 2dxan=328 members=yes +tradeable=no [obj_1840] name=Cell door key @@ -1116,6 +1083,7 @@ recol1d=15819 2dyan=20 2dxan=328 members=yes +tradeable=no [obj_1841] name=Barrel @@ -1128,6 +1096,7 @@ cost=1 2dyan=76 2dxan=136 members=yes +tradeable=no [obj_1842] name=Ana in a barrel @@ -1142,6 +1111,7 @@ model=model_2821_obj members=yes iop1=Look weight=32kg +tradeable=no [obj_1843] name=Wrought iron key @@ -1157,6 +1127,7 @@ recol1d=10432 2dzoom=700 2dyan=20 2dxan=328 +tradeable=no [obj_1844] name=Slaves' shirt @@ -1177,6 +1148,7 @@ manwear2=model_170_idk womanwear=model_456_idk,0 womanwear2=model_348_idk members=yes +tradeable=no [obj_1845] name=Slave robe @@ -1194,6 +1166,7 @@ wearpos=legs members=yes manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 +tradeable=no [obj_1846] name=Slave boots @@ -1214,6 +1187,7 @@ category=category_118 members=yes manwear=model_185_obj_wear,0 womanwear=model_361_obj_wear,0 +tradeable=no [obj_1847] name=Scrumpled paper @@ -1230,6 +1204,7 @@ recol1d=24319 members=yes iop1=Read weight=10g +tradeable=no [shantay_disclaimer] name=Shantay disclaimer @@ -1246,6 +1221,7 @@ members=yes 2dxan=472 iop1=Read weight=10g +tradeable=no [obj_1849] name=Prototype dart @@ -1264,6 +1240,7 @@ recol1d=8354 2dzoom=720 2dyan=336 2dxan=396 +tradeable=no [obj_1850] name=Technical plans @@ -1278,6 +1255,7 @@ model=model_2809_obj 2dxan=472 iop1=Read weight=15g +tradeable=no [obj_1851] name=Tenti pineapple @@ -1292,6 +1270,7 @@ members=yes 2dzoom=1740 2dyan=48 2dxan=228 +tradeable=no [obj_1852] name=Bedobin key @@ -1307,6 +1286,7 @@ members=yes 2dzoom=700 2dyan=20 2dxan=328 +tradeable=no [obj_1853] name=Prototype dart tip @@ -1320,6 +1300,7 @@ model=model_2518_obj 2dxan=344 members=yes stackable=yes +tradeable=no [shantay_pass] name=Shantay pass @@ -1336,7 +1317,6 @@ recol1d=13840 2dxan=320 members=yes stackable=yes -tradeable=yes [obj_1855] name=Rock @@ -1351,6 +1331,7 @@ recol1d=7400 2dyan=1904 2dxan=120 members=yes +tradeable=no [ogre_relic] name=Ogre relic @@ -1361,6 +1342,7 @@ model=model_2698_obj 2dyan=1668 2dxan=104 weight=3kg +tradeable=no [relic_part_1] name=Relic part 1 @@ -1373,6 +1355,7 @@ members=yes 2dxan=128 weight=1kg category=category_1399 +tradeable=no [relic_part_2] name=Relic part 2 @@ -1383,6 +1366,7 @@ members=yes 2dyan=1696 weight=1kg category=category_1399 +tradeable=no [relic_part_3] name=Relic part 3 @@ -1393,6 +1377,7 @@ members=yes 2dyan=108 weight=1kg category=category_1399 +tradeable=no [skavid_map] name=Skavid map @@ -1405,6 +1390,7 @@ model=model_2383_obj 2dxan=312 weight=10g members=yes +tradeable=no [ogre_tooth] name=Ogre tooth @@ -1417,6 +1403,7 @@ model=model_2522_obj 2dxan=292 weight=10g members=yes +tradeable=no [obj_2378] name=Toban key @@ -1428,6 +1415,7 @@ model=model_2372_obj 2dxan=328 weight=10g members=yes +tradeable=no [rock_cake] name=Rock cake @@ -1440,6 +1428,7 @@ weight=25g members=yes iop2=Eat category=category_734 +tradeable=no [obj_2380] name=Crystal @@ -1454,6 +1443,7 @@ code9=yes 2dxan=216 weight=2lb members=yes +tradeable=no [obj_2381] name=Crystal @@ -1468,6 +1458,7 @@ code9=yes 2dxan=216 weight=2lb members=yes +tradeable=no [obj_2382] name=Crystal @@ -1482,6 +1473,7 @@ code9=yes 2dxan=216 weight=2lb members=yes +tradeable=no [obj_2383] name=Crystal @@ -1496,6 +1488,7 @@ code9=yes 2dxan=216 weight=2lb members=yes +tradeable=no [obj_2384] name=Finger nails @@ -1507,6 +1500,7 @@ model=model_1787_obj 2dxan=348 weight=2g members=yes +tradeable=no [obj_2385] name=Old robe @@ -1517,6 +1511,7 @@ model=model_2786_obj 2dxan=536 weight=4lb members=yes +tradeable=no [obj_2386] name=Unusual armour @@ -1527,6 +1522,7 @@ model=model_2574_obj 2dxan=608 weight=8lb members=yes +tradeable=no [obj_2387] name=Damaged dagger @@ -1538,6 +1534,7 @@ model=model_2672_obj 2dxan=472 weight=1lb members=yes +tradeable=no [tattered_eye_patch] name=Tattered eye patch @@ -1548,6 +1545,7 @@ model=model_2417_obj 2dxan=296 weight=6g members=yes +tradeable=no [nightshade] name=Nightshade @@ -1563,18 +1561,25 @@ iop2=Eat weight=15g members=yes category=category_1748 +tradeable=no [obj_2420] +tradeable=no [obj_2422] +tradeable=no [obj_2425] +tradeable=no [obj_2480] +tradeable=no [obj_2512] +tradeable=no [obj_2513] +tradeable=no [rotten_tomato] model=model_2632_obj @@ -1591,7 +1596,6 @@ desc=Pretty smelly. cost=1 weight=80g members=yes -tradeable=yes [toy_horsey_brown] cost=100 @@ -1607,7 +1611,6 @@ womanwear=model_3333_obj_wear,6 2dxan=40 weight=50g iop1=Play-with -tradeable=yes [toy_horsey_white] cost=100 @@ -1627,7 +1630,6 @@ womanwear=model_3333_obj_wear,6 2dxan=40 weight=50g iop1=Play-with -tradeable=yes [toy_horsey_black] cost=100 @@ -1647,7 +1649,6 @@ womanwear=model_3333_obj_wear,6 2dxan=40 weight=50g iop1=Play-with -tradeable=yes [toy_horsey_grey] cost=100 @@ -1667,7 +1668,6 @@ womanwear=model_3333_obj_wear,6 2dxan=40 weight=50g iop1=Play-with -tradeable=yes [obj_2529] name=Orb of light @@ -1676,6 +1676,7 @@ cost=1 model=model_loc_771_0 members=yes respawnrate=50 +tradeable=no [obj_2530] name=Bones @@ -1687,4 +1688,3 @@ model=model_2674_obj 2dxan=400 iop1=Bury weight=500g -tradeable=yes diff --git a/data/src/scripts/_unpack/all.seq b/data/src/scripts/_unpack/all.seq index 415970dfdc..226aa184da 100644 --- a/data/src/scripts/_unpack/all.seq +++ b/data/src/scripts/_unpack/all.seq @@ -1817,7 +1817,7 @@ frame8=anim_3856 frame9=anim_3864 delay9=20000 -[imp_seq_173] +[brownimp_grab] frame1=anim_3844 frame2=anim_3852 frame3=anim_3859 @@ -1827,14 +1827,14 @@ frame6=anim_3878 frame7=anim_3838 frame8=anim_3845 -[imp_seq_174] +[brownimp_appear] frame1=anim_3839 frame2=anim_3846 frame3=anim_3853 frame4=anim_3861 frame5=anim_3868 -[imp_seq_175] +[brownimp_disappear] frame1=anim_3851 frame2=anim_3858 frame3=anim_3865 @@ -4219,7 +4219,7 @@ frame8=anim_1550 frame9=anim_1270 frame10=anim_984 -[human_spear_lunge] +[seq_405] walkmerge=label_1,label_2,label_9,label_11,label_13,label_15,label_17,label_19,label_37,label_39,label_41,label_43,label_45 priority=6 frame1=anim_659 diff --git a/data/src/scripts/_unpack/all.varp b/data/src/scripts/_unpack/all.varp index 4d3e0b7d16..76e7511c3e 100644 --- a/data/src/scripts/_unpack/all.varp +++ b/data/src/scripts/_unpack/all.varp @@ -196,8 +196,6 @@ scope=perm [gnomeball_progress] scope=perm -[varp_163] - [varp_164] [elena_progress] @@ -350,7 +348,7 @@ transmit=yes [option3] transmit=yes -[magearena_progress] +[magearena] protect=no scope=perm diff --git a/data/src/scripts/areas/area_alkharid/configs/alkharid.npc b/data/src/scripts/areas/area_alkharid/configs/alkharid.npc index 46c8120cf9..b0a811dabd 100644 --- a/data/src/scripts/areas/area_alkharid/configs/alkharid.npc +++ b/data/src/scripts/areas/area_alkharid/configs/alkharid.npc @@ -223,7 +223,6 @@ param=shop_buy_multiplier,400 param=shop_delta,30 param=shop_title,Al-Kharid General Store moverestrict=indoors -param=defend_sound,female_hit param=death_sound,female_death [gem_trader] @@ -331,7 +330,6 @@ param=shop_buy_multiplier,650 param=shop_delta,10 param=shop_title,Ranael's Super Skirt Store. moverestrict=indoors -param=defend_sound,female_hit param=death_sound,female_death [dommik] @@ -396,7 +394,9 @@ model6=model_254_idk model7=model_181_idk respawnrate=50 hitpoints=7 +param=damagetype,^crush_style category=citizen +// osrs stats and Vislvl match 1:1 [silk_trader] vislevel=hide @@ -458,7 +458,7 @@ attack=7 strength=5 defence=4 param=attackbonus,10 -param=strengthbonus,10 +param=strengthbonus,9 param=stabdefence,12 param=slashdefence,15 param=crushdefence,10 @@ -468,4 +468,5 @@ param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash -// param=defend_sound,brassclash2 \ No newline at end of file +// param=defend_sound,brassclash2 +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/areas/area_alkharid/scripts/gem_trader.rs2 b/data/src/scripts/areas/area_alkharid/scripts/gem_trader.rs2 index 074e120f88..2f5570a1c1 100644 --- a/data/src/scripts/areas/area_alkharid/scripts/gem_trader.rs2 +++ b/data/src/scripts/areas/area_alkharid/scripts/gem_trader.rs2 @@ -1,10 +1,25 @@ [opnpc1,gem_trader] ~chatnpc("Good day to you traveller.|Would you be interested in buying some gems?"); -def_int $option = ~p_choice2("Yes please.", 1, "No thank you.", 2); -if($option = 1) { - ~chatplayer("Yes please."); - ~openshop_activenpc; -} else if($option = 2) { - ~chatplayer("No thank you."); - ~chatnpc("Eh, suit yourself."); +if (%crest_progress = ^crest_caleb_where) { + @multi3("Yes please.", gem_trader_yes, "No thank you.", gem_trader_no, "I'm in search of a man named Avan Fitzharmon.", gem_trader_crest); } +else { + @multi2("Yes please.", gem_trader_yes, "No thank you.", gem_trader_no); +} + +[label,gem_trader_yes] +~chatplayer("Yes please."); +~openshop_activenpc; + +[label,gem_trader_no] +~chatplayer("No thank you."); +~chatnpc("Eh, suit yourself."); + +[label,gem_trader_crest] +~chatplayer("I'm in search of a man named Avan Fitzharmon."); +~chatnpc("Fitzharmon eh? Hmmm.... If I'm not mistaken that's the family name of a member of the Varrockian nobility. You know, I HAVE seen someone of that"); +~chatnpc("persuasion around here recently... Wearing a poncey yellow cape he was! Came in here all la-di-dah, high and mighty, asking for jewelry made"); +~chatnpc("from 'perfect gold' - whatever that is - like 'normal' golds just not good enough for little lord fancy pants there! I told him to head to the desert"); +~chatnpc("'Cos I know theres gold out there, in them there sand dunes... and if it's not up to his lordships high standards of 'gold perfection'..."); +~chatnpc("Maybe we'll all get lucky and the scorpions will deal with him."); +%crest_progress = ^crest_spoken_gem_trader; \ No newline at end of file diff --git a/data/src/scripts/areas/area_alkharid/scripts/kebab_seller.rs2 b/data/src/scripts/areas/area_alkharid/scripts/kebab_seller.rs2 index b9209193c2..6fac9afaa4 100644 --- a/data/src/scripts/areas/area_alkharid/scripts/kebab_seller.rs2 +++ b/data/src/scripts/areas/area_alkharid/scripts/kebab_seller.rs2 @@ -5,7 +5,12 @@ if(map_members = true & inv_total(inv, trail_clue_medium_anagram_exp006) > 0) { } ~chatnpc("Would you like to buy a nice kebab? Only one gold."); -@multi2("I think I'll give it a miss.", kebab_seller_miss, "Yes please.", kebab_seller_buy); +if (%crest_progress = ^crest_caleb_where) { + @multi3("I think I'll give it a miss.", kebab_seller_miss, "Yes please.", kebab_seller_buy, "I'm in search of a man named Avan Fitzharmon.", kebab_seller_crest); +} +else { + @multi2("I think I'll give it a miss.", kebab_seller_miss, "Yes please.", kebab_seller_buy); +} [label,kebab_seller_miss] ~chatplayer("I think I'll give it a miss."); @@ -28,4 +33,8 @@ if(inv_total(inv, trail_clue_medium_challenge_exp004) > 0) { } ~chatnpc("I've got a little problem for you to solve."); inv_add(inv, trail_clue_medium_challenge_exp004, 1); -~objbox(trail_clue_medium_challenge_exp004, "The salesman has given you a challenge scroll!", 250, 0, 0); \ No newline at end of file +~objbox(trail_clue_medium_challenge_exp004, "The salesman has given you a challenge scroll!", 250, 0, 0); + +[label,kebab_seller_crest] +~chatplayer("I'm in search of a man named Avan Fitzharmon."); +~chatnpc("Can't say as I've seen him... I'm sure if he's been to Al Kharid recently someone around here will have though."); \ No newline at end of file diff --git a/data/src/scripts/areas/area_alkharid/scripts/silk_trader.rs2 b/data/src/scripts/areas/area_alkharid/scripts/silk_trader.rs2 index c7163b547b..36ff3001e6 100644 --- a/data/src/scripts/areas/area_alkharid/scripts/silk_trader.rs2 +++ b/data/src/scripts/areas/area_alkharid/scripts/silk_trader.rs2 @@ -1,11 +1,23 @@ // dialogue taken from osrs [opnpc1,silk_trader] ~chatnpc("Do you want to buy any fine silks?"); -def_int $choice = ~p_choice2("How much are they?", 1, "No. Silk doesn't suit me.", 2); +def_int $choice = 0; +if (%crest_progress = ^crest_caleb_where) { + $choice = ~p_choice3("How much are they?", 1, "No. Silk doesn't suit me.", 2, "I'm in search of a man named Avan Fitzharmon.", 3); +} +else { + $choice = ~p_choice2("How much are they?", 1, "No. Silk doesn't suit me.", 2); +} + if ($choice = 2) { ~chatplayer("No. Silk doesn't suit me."); return; } +if ($choice = 3) { + ~chatplayer("I'm in search of a man named Avan Fitzharmon."); + ~chatnpc("Can't say as I've seen him... I'm sure if he's been to Al Kharid recently someone around here will have though."); + return; +} ~chatplayer("How much are they?"); ~chatnpc("3 gp."); diff --git a/data/src/scripts/areas/area_alkharid/scripts/zeke.rs2 b/data/src/scripts/areas/area_alkharid/scripts/zeke.rs2 index 4900f26908..41eaf4f935 100644 --- a/data/src/scripts/areas/area_alkharid/scripts/zeke.rs2 +++ b/data/src/scripts/areas/area_alkharid/scripts/zeke.rs2 @@ -4,7 +4,13 @@ if(map_members = true & inv_total(inv, trail_clue_easy_simple_exp007) = 1) { @trail_zeke; } ~chatnpc("A thousand greetings, sir."); -def_int $option = ~p_choice2("Do you want to trade?", 1, "Nice cloak.", 2); +def_int $option = 0; +if (%crest_progress = ^crest_caleb_where) { + $option = ~p_choice3("Do you want to trade?", 1, "Nice cloak.", 2, "I'm in search of a man named Avan Fitzharmon.", 3); +} +else { + $option = ~p_choice2("Do you want to trade?", 1, "Nice cloak.", 2); +} if($option = 1) { ~chatplayer("Do you want to trade?"); ~chatnpc("Yes, certainly. I deal in scimitars."); @@ -13,6 +19,10 @@ if($option = 1) { ~chatplayer("Nice cloak."); ~chatnpc("Thank you."); } +else if ($option = 3) { + ~chatplayer("I'm in search of a man named Avan Fitzharmon."); + ~chatnpc("Can't say as I've seen him... I'm sure if he's been to Al Kharid recently someone around here will have though."); +} [label,trail_zeke] // https://youtu.be/klvUCL0XFyw?si=WWWusRMnfJOBl7E_&t=19 diff --git a/data/src/scripts/areas/area_ardougne_east/configs/ardougne_east.npc b/data/src/scripts/areas/area_ardougne_east/configs/ardougne_east.npc index 2fe3aa2b57..e3a173db2d 100644 --- a/data/src/scripts/areas/area_ardougne_east/configs/ardougne_east.npc +++ b/data/src/scripts/areas/area_ardougne_east/configs/ardougne_east.npc @@ -20,22 +20,25 @@ attackrange=10 maxrange=12 respawnrate=50 hitpoints=50 -attack=0 -strength=0 -defence=40 +attack=20 +strength=20 +defence=20 ranged=40 param=attackrate,6 -param=attackbonus,34 -param=stabdefence,39 -param=slashdefence,50 -param=crushdefence,49 -param=magicdefence,18 -param=rangedefence,45 +param=attackbonus,19 +param=strengthbonus,8 +param=rangebonus,8 +param=stabdefence,18 +param=slashdefence,23 +param=crushdefence,27 +param=magicdefence,10 +param=rangedefence,19 param=damagetype,^ranged_style param=attack_anim,human_bow param=rangeattack_sound,arrowlaunch2 param=proj_launch,iron_arrow_launch param=proj_travel,iron_arrow_travel +// Stats match osrs version but our version Vislvl is different. [zoo_keeper] name=Zoo keeper @@ -65,6 +68,12 @@ model10=model_495_npc head1=model_53_idk_head head2=model_82_idk_head head3=model_37_npc_head +hitpoints=20 +attack=10 +strength=10 +defence=10 +ranged=0 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3302 [chuck] name=Chuck @@ -167,6 +176,7 @@ param=attack_sound,mace_crush // param=defend_sound,blade2_mail category=guard // osrs use attack sound warhammer_crush +// osrs stats and Vislvl match 1:1 [brother_kojo] vislevel=hide @@ -258,6 +268,7 @@ strength=2 defence=3 param=damagetype,^crush_style param=retreat,2 +// osrs stats and Vislvl match 1:1 [king_lathas] vislevel=hide @@ -402,8 +413,7 @@ param=shop_sell_multiplier,1000 param=shop_buy_multiplier,800 param=shop_delta,20 param=shop_title,Ardougne Baker's Stall. -wanderrange=0 -moverestrict=nomove +wanderrange=2 [spice_seller] vislevel=hide @@ -722,13 +732,14 @@ model6=model_414_npc model7=model_361_obj_wear head1=model_115_idk_head head2=model_131_npc_head +moverestrict=indoors +param=death_sound,female_death category=shop_keeper param=owned_shop,zenesha_platemail param=shop_sell_multiplier,1000 param=shop_buy_multiplier,600 param=shop_delta,20 param=shop_title,Zenesha's Plate Mail Body Shop. -moverestrict=indoors [caroline] vislevel=hide @@ -752,6 +763,7 @@ model6=model_358_idk model7=model_483_npc head1=model_114_idk_head wanderrange=2 +param=death_sound,female_death [holgart_ardougne] vislevel=hide diff --git a/data/src/scripts/areas/area_ardougne_east/configs/legends_guild/legends_guild.npc b/data/src/scripts/areas/area_ardougne_east/configs/legends_guild/legends_guild.npc index 86b73ff7a2..1585ced230 100644 --- a/data/src/scripts/areas/area_ardougne_east/configs/legends_guild/legends_guild.npc +++ b/data/src/scripts/areas/area_ardougne_east/configs/legends_guild/legends_guild.npc @@ -33,8 +33,9 @@ hitpoints=67 attack=36 strength=33 defence=36 -param=attackrate,4 -param=attackbonus,43 +magic=0 +ranged=0 +param=attackbonus,20 param=strengthbonus,26 param=stabdefence,43 param=slashdefence,31 @@ -44,12 +45,12 @@ param=rangedefence,38 param=damagetype,^slash_style param=attack_anim,human_trans_axe_chop param=defend_anim,human_trans_axe_def -// param=defend_anim,earthwarrior_def param=death_anim,earthwarrior_death param=attack_sound,baxe_slash // param=defend_sound,steel huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [npc_398] vislevel=hide @@ -179,10 +180,10 @@ wanderrange=3 param=death_sound,female_death category=shop_keeper param=owned_shop,legends_guild_general_store -// param=shop_sell_multiplier, -// param=shop_buy_multiplier, -// param=shop_delta, -param=shop_title,Legends' Guild General Store. +param=shop_sell_multiplier,1550 +param=shop_buy_multiplier,550 +param=shop_delta,10 +param=shop_title,Legends Guild General Store. [siegfried_erkle] vislevel=hide @@ -216,7 +217,7 @@ head2=model_82_idk_head wanderrange=3 category=shop_keeper param=owned_shop,legends_guild_shop_of_useful_items -// param=shop_sell_multiplier, -// param=shop_buy_multiplier, -// param=shop_delta, -param=shop_title,Legends' Guild Shop of Useful Items. \ No newline at end of file +param=shop_sell_multiplier,1500 +param=shop_buy_multiplier,500 +param=shop_delta,20 +param=shop_title,Legends Guild Shop of Useful Items. \ No newline at end of file diff --git a/data/src/scripts/areas/area_ardougne_west/configs/man.npc b/data/src/scripts/areas/area_ardougne_west/configs/man.npc index 55d97647df..eea8caeb52 100644 --- a/data/src/scripts/areas/area_ardougne_west/configs/man.npc +++ b/data/src/scripts/areas/area_ardougne_west/configs/man.npc @@ -28,6 +28,75 @@ param=stabdefence,1 param=slashdefence,1 param=crushdefence,1 param=damagetype,^crush_style +// osrs stats and Vislvl match 1:1 + +[npc_359] +vislevel=hide +name=Man +desc=One of RuneScapes' many citizens. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +recol1s=14801 +recol1d=12547 +recol2s=2340 +recol2d=6208 +recol3s=14724 +recol3d=16808 +recol4s=24075 +recol4d=12547 +model1=model_230_idk +model2=model_185_obj_wear +model3=model_250_idk +model4=model_299_npc +model5=model_159_npc +model6=model_179_obj_wear +model7=model_275_idk +head1=model_63_idk_head +head2=model_82_idk_head + +[npc_726] +vislevel=hide +name=Man +desc=One of RuneScapes' many citizens. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=14801 +recol1d=24075 +recol2s=2340 +recol2d=6208 +model1=model_235_idk +model2=model_185_obj_wear +model3=model_250_idk +model4=model_310_idk +model5=model_173_npc +model6=model_176_idk +model7=model_275_idk +head1=model_67_idk_head +head2=model_82_idk_head + +[npc_727] +vislevel=hide +name=Man +desc=One of RuneScapes' many citizens. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=14801 +recol1d=24075 +recol2s=2340 +recol2d=6208 +recol3s=14724 +recol3d=21000 +model1=model_235_idk +model2=model_185_obj_wear +model3=model_250_idk +model4=model_310_idk +model5=model_151_idk +model6=model_179_obj_wear +model7=model_275_idk +head1=model_67_idk_head +head2=model_82_idk_head [npc_728] vislevel=hide @@ -74,3 +143,28 @@ model6=model_179_obj_wear model7=model_275_idk head1=model_52_idk_head head2=model_82_idk_head + +[npc_730] +vislevel=hide +name=Man +desc=One of RuneScapes' many citizens. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=14801 +recol1d=12547 +recol2s=2340 +recol2d=6208 +recol3s=14724 +recol3d=16808 +recol4s=24075 +recol4d=12547 +model1=model_214_idk +model2=model_185_obj_wear +model3=model_250_idk +model4=model_310_idk +model5=model_173_npc +model6=model_179_obj_wear +model7=model_275_idk +head1=model_52_idk_head +head2=model_82_idk_head diff --git a/data/src/scripts/areas/area_ardougne_west/configs/mourner.npc b/data/src/scripts/areas/area_ardougne_west/configs/mourner.npc index e94ab9db73..8af2496b01 100644 --- a/data/src/scripts/areas/area_ardougne_west/configs/mourner.npc +++ b/data/src/scripts/areas/area_ardougne_west/configs/mourner.npc @@ -96,6 +96,7 @@ model6=model_323_obj_wear model7=model_555_npc head1=model_51_obj_wear param=attack_anim,human_staff_spike +param=defend_anim,human_staff_def param=attack_sound,staff_stab // stats based off: https://oldschool.runescape.wiki/w/Mourner?oldid=9768605#Lv_18, 70t respawn on rs3 respawnrate=140 @@ -178,6 +179,7 @@ defence=10 param=stabdefence,3 param=slashdefence,2 param=crushdefence,4 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_9230 (Biohazard boss) [npc_371] name=Mourner diff --git a/data/src/scripts/areas/area_ardougne_west/configs/woman.npc b/data/src/scripts/areas/area_ardougne_west/configs/woman.npc index d1267e92fd..40068f6043 100644 --- a/data/src/scripts/areas/area_ardougne_west/configs/woman.npc +++ b/data/src/scripts/areas/area_ardougne_west/configs/woman.npc @@ -28,6 +28,7 @@ param=crushdefence,1 param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death +// osrs stats and Vislvl match 1:1 [npc_353] name=Woman @@ -57,6 +58,7 @@ param=crushdefence,1 param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death +// osrs stats and Vislvl match 1:1 [npc_354] name=Woman @@ -82,9 +84,13 @@ head1=model_103_idk_head respawnrate=100 hitpoints=10 attack=2 +param=stabdefence,1 +param=slashdefence,1 +param=crushdefence,1 param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death +// osrs stats and Vislvl match 1:1 [npc_360] name=Woman @@ -116,6 +122,38 @@ param=crushdefence,1 param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death +// osrs stats and Vislvl match 1:1 + +[npc_361] +name=Woman +desc=One of RuneScapes' many citizens. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +op2=Attack +vislevel=12 +recol1s=14801 +recol1d=12547 +recol2s=2340 +recol2d=6208 +recol3s=24075 +recol3d=12547 +model1=model_404_npc +model2=model_478_npc +model3=model_351_idk +model4=model_353_idk +model5=model_437_idk +model6=model_358_idk +head1=model_121_npc_head +respawnrate=100 +hitpoints=13 +attack=10 +strength=10 +defence=10 +param=damagetype,^crush_style +param=defend_sound,female_hit +param=death_sound,female_death +// osrs stats and Vislvl match 1:1 [npc_362] name=Woman @@ -142,6 +180,7 @@ attack=2 param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death +// osrs stats and Vislvl match 1:1 [npc_363] name=Woman @@ -170,3 +209,4 @@ defence=10 param=damagetype,^crush_style param=defend_sound,female_hit param=death_sound,female_death +// osrs stats and Vislvl match 1:1 diff --git a/data/src/scripts/areas/area_brimhaven/configs/brimhaven.npc b/data/src/scripts/areas/area_brimhaven/configs/brimhaven.npc index f4a1e89551..27fbf0afe7 100644 --- a/data/src/scripts/areas/area_brimhaven/configs/brimhaven.npc +++ b/data/src/scripts/areas/area_brimhaven/configs/brimhaven.npc @@ -49,12 +49,14 @@ model7=model_176_idk model8=model_320_idk head1=model_67_idk_head head2=model_79_idk_head +hitpoints=7 category=shop_keeper param=owned_shop,shrimp_and_parrot param=shop_sell_multiplier,1300 param=shop_buy_multiplier,750 param=shop_delta,30 param=shop_title,The Shrimp and Parrot +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4920 [bartender_brimhaven] vislevel=hide diff --git a/data/src/scripts/areas/area_combat_training/configs/combat_training_camp.npc b/data/src/scripts/areas/area_combat_training/configs/combat_training_camp.npc index c8c299b7d6..c9e2ee820f 100644 --- a/data/src/scripts/areas/area_combat_training/configs/combat_training_camp.npc +++ b/data/src/scripts/areas/area_combat_training/configs/combat_training_camp.npc @@ -1,3 +1,101 @@ +[npc_344] +vislevel=hide +name=Guard +desc=He tries to keep order around here. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=15855 +recol1d=8420 +model1=model_208_npc +model2=model_185_obj_wear +model3=model_248_idk +model4=model_311_obj_wear +model5=model_151_idk +model6=model_179_obj_wear +model7=model_254_idk +model8=model_276_npc +model9=model_502_obj_wear +model10=model_541_obj_wear +head1=model_48_npc_head +head2=model_80_idk_head +wanderrange=1 + +[npc_345] +vislevel=hide +name=Guard +desc=He tries to keep order around here. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=15855 +recol1d=8420 +model1=model_208_npc +model2=model_185_obj_wear +model3=model_248_idk +model4=model_311_obj_wear +model5=model_151_idk +model6=model_179_obj_wear +model7=model_254_idk +model8=model_276_npc +model9=model_508_obj_wear +head1=model_48_npc_head +head2=model_80_idk_head +wanderrange=1 + +[npc_346] +vislevel=hide +name=Guard +desc=He tries to keep order around here. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=15855 +recol1d=8420 +model1=model_208_npc +model2=model_185_obj_wear +model3=model_248_idk +model4=model_311_obj_wear +model5=model_151_idk +model6=model_179_obj_wear +model7=model_254_idk +model8=model_276_npc +model9=model_508_obj_wear +head1=model_48_npc_head +head2=model_80_idk_head + +[npc_374] +name=Ogre +desc=Big, ugly, and smelly. +size=2 +walkanim=ogre_walk +readyanim=ogre_ready +op2=Attack +vislevel=53 +model1=model_2878_npc +model2=model_2874_npc +respawnrate=100 +hitpoints=60 +attack=54 +strength=54 +defence=54 +param=attackbonus,8 +param=strengthbonus,6 +param=stabdefence,19 +param=slashdefence,23 +param=crushdefence,24 +param=damagetype,^crush_style +param=attack_anim,ogre_attack +param=defend_anim,ogre_block +param=death_anim,ogre_death +param=attack_sound,giant_attack +param=defend_sound,giant_hit +param=death_sound,giant_death +param=death_drop,big_bones +huntmode=cowardly +huntrange=2 +// Stats match osrs version but our version Vislvl is different. + [npc_561] vislevel=hide name=Shop keeper diff --git a/data/src/scripts/areas/area_desert/configs/bedabincamp.npc b/data/src/scripts/areas/area_desert/configs/bedabincamp.npc index fe5d5da315..65b9c61919 100644 --- a/data/src/scripts/areas/area_desert/configs/bedabincamp.npc +++ b/data/src/scripts/areas/area_desert/configs/bedabincamp.npc @@ -107,13 +107,17 @@ head3=model_80_idk_head wanderrange=0 maxrange=4 respawnrate=100 -hitpoints=50 -attack=40 -strength=50 +hitpoints=70 +attack=51 +strength=47 defence=60 +magic=0 +ranged=0 param=attackbonus,9 param=strengthbonus,14 param=damagetype,^slash_style param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +// params taken npc Bedabin nomad fighter. +// stats taken here https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4639 diff --git a/data/src/scripts/areas/area_desert/configs/desert.npc b/data/src/scripts/areas/area_desert/configs/desert.npc index 95b804e838..af0c1cce4e 100644 --- a/data/src/scripts/areas/area_desert/configs/desert.npc +++ b/data/src/scripts/areas/area_desert/configs/desert.npc @@ -27,6 +27,8 @@ hitpoints=34 attack=20 strength=21 defence=22 +magic=0 +ranged=0 param=damagetype,^slash_style param=attack_anim,dog_attack param=defend_anim,dog_block @@ -37,6 +39,7 @@ param=death_sound,wolf_death param=death_drop,wolf_bones huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [npc_840] name=Ugthanki @@ -56,6 +59,8 @@ hitpoints=45 attack=35 strength=35 defence=35 +magic=0 +ranged=0 param=damagetype,^stab_style param=attack_anim,camel_attack param=defend_anim,camel_block @@ -66,3 +71,4 @@ param=death_sound,cow_death param=retreat,5 huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 diff --git a/data/src/scripts/areas/area_draynor/configs/draynor.npc b/data/src/scripts/areas/area_draynor/configs/draynor.npc index f19636307d..b539428f05 100644 --- a/data/src/scripts/areas/area_draynor/configs/draynor.npc +++ b/data/src/scripts/areas/area_draynor/configs/draynor.npc @@ -183,6 +183,7 @@ hitpoints=32 attack=19 strength=23 defence=21 +param=attackrate,5 param=attackbonus,9 param=strengthbonus,5 param=stabdefence,8 @@ -190,7 +191,6 @@ param=slashdefence,9 param=crushdefence,10 param=magicdefence,4 param=rangedefence,9 -param=attackrate,5 param=damagetype,^crush_style param=attack_anim,human_blunt_crush param=defend_anim,human_blunt_defend1 @@ -202,6 +202,7 @@ param=attack_sound,mace_crush huntmode=aggressive_melee // osrs huntrange=5 +// osrs stats and Vislvl match 1:1 [traiborn] vislevel=107 diff --git a/data/src/scripts/areas/area_wilderness/configs/edgeville.inv b/data/src/scripts/areas/area_edgeville/configs/edgeville.inv similarity index 100% rename from data/src/scripts/areas/area_wilderness/configs/edgeville.inv rename to data/src/scripts/areas/area_edgeville/configs/edgeville.inv diff --git a/data/src/scripts/areas/area_edgeville/configs/edgeville.npc b/data/src/scripts/areas/area_edgeville/configs/edgeville.npc index 3bc2b937d9..b2797b6d0e 100644 --- a/data/src/scripts/areas/area_edgeville/configs/edgeville.npc +++ b/data/src/scripts/areas/area_edgeville/configs/edgeville.npc @@ -1,35 +1,70 @@ -[oziach] +[shop_keeper_edgeville] vislevel=hide -name=Oziach -desc=A strange little man. +name=Shop keeper +desc=If he doesn't have it, he can't sell it! walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready op1=Talk-to op3=Trade -recol1s=15855 -recol1d=6542 -recol2s=10570 -recol2d=6476 +recol1s=2340 +recol1d=8354 +recol2s=14724 +recol2d=13539 recol3s=6273 -recol3d=7296 -recol4s=2340 -recol4d=8359 -model1=model_203_idk -model2=model_247_idk -model3=model_312_npc -model4=model_164_obj_wear -model5=model_176_idk -model6=model_254_idk +recol3d=32767 +recol4s=14801 +recol4d=24075 +recol5s=32735 +recol5d=12583 +model1=model_215_idk +model2=model_254_idk +model3=model_246_idk +model4=model_305_obj_wear +model5=model_151_idk +model6=model_176_idk model7=model_181_idk -model8=model_323_obj_wear -head1=model_45_idk_head -head2=model_79_idk_head +head1=model_67_idk_head +category=shop_keeper +param=owned_shop,generalshop6 +param=shop_sell_multiplier,1300 +param=shop_buy_multiplier,400 +param=shop_delta,30 +param=shop_title,Edgeville General Store moverestrict=indoors -param=owned_shop,oziach_shop + +[shop_assistant_edgeville] +vislevel=hide +name=Shop assistant +desc=Is here on work experience. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +op3=Trade +recol1s=2340 +recol1d=8354 +recol2s=14724 +recol2d=13539 +recol3s=24075 +recol3d=15652 +recol4s=14801 +recol4d=15652 +recol5s=32735 +recol5d=12583 +model1=model_390_idk +model2=model_421_idk +model3=model_467_obj_wear +model4=model_332_idk +model5=model_353_idk +model6=model_358_idk +head1=model_113_idk_head +category=shop_keeper +param=owned_shop,generalshop6 param=shop_sell_multiplier,1300 param=shop_buy_multiplier,400 param=shop_delta,30 -param=shop_title,oziach +param=shop_title,Edgeville General Store +moverestrict=indoors +param=death_sound,female_death [oracle] vislevel=hide @@ -58,4 +93,38 @@ model5=model_176_idk model6=model_275_idk model7=model_181_idk model8=model_318_npc -head1=model_64_npc_head \ No newline at end of file +head1=model_64_npc_head + +[oziach] +vislevel=hide +name=Oziach +desc=A strange little man. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +op3=Trade +recol1s=15855 +recol1d=6542 +recol2s=10570 +recol2d=6476 +recol3s=6273 +recol3d=7296 +recol4s=2340 +recol4d=8359 +model1=model_203_idk +model2=model_247_idk +model3=model_312_npc +model4=model_164_obj_wear +model5=model_176_idk +model6=model_254_idk +model7=model_181_idk +model8=model_323_obj_wear +head1=model_45_idk_head +head2=model_79_idk_head +wanderrange=3 +param=owned_shop,oziach_shop +param=shop_sell_multiplier,1300 +param=shop_buy_multiplier,400 +param=shop_delta,30 +param=shop_title,oziach +// not indoors in 2006: https://cdn.discordapp.com/attachments/953326730632904847/1289352714299379803/6cesmgeme9541.webp?ex=6701148a&is=66ffc30a&hm=b19e9846a0f1410a062113e013ab56d0bcec4f51e34b66d1bc255868be88dcf3& \ No newline at end of file diff --git a/data/src/scripts/areas/area_falador/configs/dwarven_mine.npc b/data/src/scripts/areas/area_falador/configs/dwarven_mine.npc index 145a4dc4e3..08095538a6 100644 --- a/data/src/scripts/areas/area_falador/configs/dwarven_mine.npc +++ b/data/src/scripts/areas/area_falador/configs/dwarven_mine.npc @@ -99,4 +99,9 @@ model4=model_2983_npc model5=model_2985_npc model6=model_2990_npc head1=model_1_npc_head -param=death_anim,dwarf_death \ No newline at end of file +hitpoints=16 +attack=8 +strength=8 +defence=7 +param=death_anim,dwarf_death +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4985 \ No newline at end of file diff --git a/data/src/scripts/areas/area_falador/configs/falador.npc b/data/src/scripts/areas/area_falador/configs/falador.npc index f161e12e44..d30ea60fca 100644 --- a/data/src/scripts/areas/area_falador/configs/falador.npc +++ b/data/src/scripts/areas/area_falador/configs/falador.npc @@ -43,6 +43,7 @@ param=defend_sound,sound_218 // Despite the slash attack style they still use the crush anim today // osrs attack anim seq_406 and defend anim seq_410. // osrs use sounds attack - 2H_crush & defend - blade3 +// osrs stats and Vislvl match 1:1 [wyson] name=Wyson the gardener @@ -65,15 +66,16 @@ model8=model_185_obj_wear model9=model_495_npc head1=model_63_idk_head respawnrate=50 -hitpoints=5 +hitpoints=7 attack=2 -strength=3 -defence=2 +defence=5 param=damagetype,^stab_style param=attack_anim,human_farmersfork_stab param=defend_anim,human_farmersfork_defend param=attack_sound,staff_stab // osrs attack sound farmersfork_stab +// stats taken 3lv Gardener (Falador) Vislvl match. +// Also Hitpoints match RSC version. [shop_keeper_falador] vislevel=hide diff --git a/data/src/scripts/areas/area_falador/configs/goblin_village/goblin_village.npc b/data/src/scripts/areas/area_falador/configs/goblin_village/goblin_village.npc index e6e2678927..2b8ecf1f64 100644 --- a/data/src/scripts/areas/area_falador/configs/goblin_village/goblin_village.npc +++ b/data/src/scripts/areas/area_falador/configs/goblin_village/goblin_village.npc @@ -62,9 +62,9 @@ respawnrate=70 hitpoints=12 attack=3 defence=4 +param=attackrate,6 param=attackbonus,12 param=strengthbonus,12 -param=attackrate,6 param=damagetype,^crush_style param=attack_anim,goblin_attack_armed param=defend_anim,goblin_block @@ -72,6 +72,9 @@ param=death_anim,goblin_death param=attack_sound,goblin_attack param=defend_sound,goblin_hit param=death_sound,goblin_death +// https://oldschool.runescape.wiki/w/Goblin_(historical)#Green_(original) +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_677 +// osrs stats and Vislvl match 1:1 [goblin_armed_red] name=Goblin @@ -95,9 +98,9 @@ respawnrate=70 hitpoints=12 attack=3 defence=4 +param=attackrate,6 param=attackbonus,12 param=strengthbonus,12 -param=attackrate,6 param=damagetype,^crush_style param=attack_anim,goblin_attack_armed param=defend_anim,goblin_block @@ -105,3 +108,6 @@ param=death_anim,goblin_death param=attack_sound,goblin_attack param=defend_sound,goblin_hit param=death_sound,goblin_death +// https://oldschool.runescape.wiki/w/Goblin_(historical)#Green_(original) +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_678 +// osrs stats and Vislvl match 1:1 diff --git a/data/src/scripts/areas/area_falador/scripts/guard_crossbow.rs2 b/data/src/scripts/areas/area_falador/scripts/guard_crossbow.rs2 new file mode 100644 index 0000000000..9e7d5a055c --- /dev/null +++ b/data/src/scripts/areas/area_falador/scripts/guard_crossbow.rs2 @@ -0,0 +1,3 @@ +[ai_queue1,guard_crossbow] ~npc_default_retaliate_ap; +[ai_opplayer2,guard_crossbow] npc_setmode(applayer2); +[ai_applayer2,guard_crossbow] ~npc_rangeattack; \ No newline at end of file diff --git a/data/src/scripts/areas/area_gnome/configs/child.obj b/data/src/scripts/areas/area_gnome/configs/child.obj index ab5cf8ce65..542ca16262 100644 --- a/data/src/scripts/areas/area_gnome/configs/child.obj +++ b/data/src/scripts/areas/area_gnome/configs/child.obj @@ -8,4 +8,3 @@ model=model_2362_obj 2dxan=288 weight=3g members=yes -tradeable=yes diff --git a/data/src/scripts/areas/area_gnome/configs/gnome.npc b/data/src/scripts/areas/area_gnome/configs/gnome.npc index 9ec244c151..23b42ea019 100644 --- a/data/src/scripts/areas/area_gnome/configs/gnome.npc +++ b/data/src/scripts/areas/area_gnome/configs/gnome.npc @@ -1,3 +1,205 @@ +[gnome_green] +name=Gnome +desc=Like a mini man! +walkanim=midget_walk +readyanim=midget_ready +op1=Talk-to +op2=Attack +op3=Pickpocket +vislevel=1 +model1=model_2909_npc +model2=model_2890_npc +model3=model_2915_npc +head1=model_21_npc_head +attackrange=6 +respawnrate=120 +hitpoints=3 +param=attackbonus,-42 +param=strengthbonus,-42 +param=rangebonus,2 +param=stabdefence,-42 +param=slashdefence,-42 +param=crushdefence,-42 +param=magicdefence,-42 +param=rangedefence,-42 +param=damagetype,^ranged_style +param=attack_anim,midget_attackbow +param=defend_anim,midget_block +param=death_anim,midget_death +param=rangeattack_sound,arrowlaunch2 +param=defend_sound,gnome_hit +param=death_sound,gnome_death +param=proj_launch,iron_arrow_launch +param=proj_travel,iron_arrow_travel +param=proj_height,48 +// osrs stats and Vislvl match 1:1 + +[gnome_brown] +name=Gnome +desc=Like a mini man! +walkanim=midget_walk +readyanim=midget_ready +op1=Talk-to +op2=Attack +op3=Pickpocket +vislevel=1 +recol1s=352 +recol1d=14625 +model1=model_2909_npc +model2=model_2890_npc +model3=model_2915_npc +head1=model_21_npc_head +attackrange=6 +respawnrate=120 +hitpoints=3 +param=attackbonus,-42 +param=strengthbonus,-42 +param=rangebonus,2 +param=stabdefence,-42 +param=slashdefence,-42 +param=crushdefence,-42 +param=magicdefence,-42 +param=rangedefence,-42 +param=damagetype,^ranged_style +param=attack_anim,midget_attackbow +param=defend_anim,midget_block +param=death_anim,midget_death +param=rangeattack_sound,arrowlaunch2 +param=defend_sound,gnome_hit +param=death_sound,gnome_death +param=proj_launch,iron_arrow_launch +param=proj_travel,iron_arrow_travel +param=proj_height,48 +// osrs stats and Vislvl match 1:1 + +[gnome_black] +name=Gnome +desc=Like a mini man! +walkanim=midget_walk +readyanim=midget_ready +op1=Talk-to +op2=Attack +op3=Pickpocket +vislevel=1 +recol1s=24075 +recol1d=13537 +recol2s=21961 +recol2d=13537 +recol3s=20904 +recol3d=13537 +model1=model_2909_npc +model2=model_2890_npc +model3=model_2915_npc +head1=model_21_npc_head +attackrange=6 +respawnrate=120 +hitpoints=3 +param=attackbonus,-42 +param=strengthbonus,-42 +param=rangebonus,2 +param=stabdefence,-42 +param=slashdefence,-42 +param=crushdefence,-42 +param=magicdefence,-42 +param=rangedefence,-42 +param=damagetype,^ranged_style +param=attack_anim,midget_attackbow +param=defend_anim,midget_block +param=death_anim,midget_death +param=rangeattack_sound,arrowlaunch2 +param=defend_sound,gnome_hit +param=death_sound,gnome_death +param=proj_launch,iron_arrow_launch +param=proj_travel,iron_arrow_travel +param=proj_height,48 +// osrs stats and Vislvl match 1:1 + +[terrorbird] +name=Terrorbird +desc=A giant raptor. +size=2 +walkanim=terrorbird_walk +readyanim=terrorbird_ready +op2=Attack +vislevel=28 +model1=model_3011_npc +wanderrange=12 +maxrange=14 +respawnrate=60 +hitpoints=34 +attack=23 +strength=23 +defence=19 +param=damagetype,^stab_style +param=attack_anim,terrorbird_attack +param=defend_anim,terrorbird_block +param=death_anim,terrorbird_death +param=attack_sound,terrorbird_attack +param=defend_sound,terrorbird_hit +param=death_sound,terrorbird_death +// osrs stats and Vislvl match 1:1 + +[npc_137] +name=Mounted terrorbird gnome +desc=These gnomes know how to get around! +size=2 +walkanim=mounted_terrorbird_walk +readyanim=mounted_terrorbird_ready +op2=Attack +vislevel=29 +model1=model_3012_npc +wanderrange=12 +maxrange=14 +respawnrate=60 +hitpoints=36 +attack=25 +strength=25 +defence=25 +param=stabdefence,16 +param=slashdefence,16 +param=crushdefence,18 +param=magicdefence,15 +param=rangedefence,10 +param=damagetype,^stab_style +param=attack_anim,mounted_terrorbird_attack +param=defend_anim,mounted_terrorbird_defend +param=death_anim,mounted_terrorbird_death +param=attack_sound,terrorbird_attack +param=defend_sound,terrorbird_hit +param=death_sound,terrorbird_death +// Stats match osrs version but our version Vislvl is different. + +[npc_138] +name=Mounted terrorbird gnome +desc=These gnomes know how to get around! +size=2 +walkanim=mounted_terrorbird_walk +readyanim=mounted_terrorbird_ready +op2=Attack +vislevel=46 +model1=model_3013_npc +wanderrange=12 +maxrange=14 +respawnrate=60 +hitpoints=55 +attack=40 +strength=40 +defence=40 +param=rangebonus,2 +param=stabdefence,16 +param=slashdefence,16 +param=crushdefence,18 +param=magicdefence,15 +param=rangedefence,10 +param=damagetype,^stab_style +param=attack_anim,mounted_terrorbird_gnome_hands_over_food +param=defend_anim,mounted_terrorbird_defend +param=death_anim,mounted_terrorbird_death +param=attack_sound,terrorbird_attack +param=defend_sound,terrorbird_hit +param=death_sound,terrorbird_death +// Stats match osrs version but our version Vislvl is different. + [gnome_trainer] name=Gnome trainer desc=He can advise on training. @@ -11,7 +213,6 @@ model1=model_2909_npc model2=model_2890_npc model3=model_2922_npc head1=model_21_npc_head -wanderrange=3 param=death_anim,midget_death param=death_sound,gnome_death @@ -134,6 +335,7 @@ param=death_anim,midget_death param=attack_sound,gnome_attack param=defend_sound,gnome_hit param=death_sound,gnome_death +// osrs stats and Vislvl match 1:1 [gnome_child_blue] name=Gnome child @@ -168,6 +370,7 @@ param=death_anim,midget_death param=attack_sound,gnome_attack param=defend_sound,gnome_hit param=death_sound,gnome_death +// osrs stats and Vislvl match 1:1 [gnome_child_green] name=Gnome child @@ -200,6 +403,7 @@ param=death_anim,midget_death param=attack_sound,gnome_attack param=defend_sound,gnome_hit param=death_sound,gnome_death +// osrs stats and Vislvl match 1:1 [gnome_guard_halberd] name=Gnome guard @@ -230,6 +434,7 @@ param=attack_sound,scythe_slash param=defend_sound,gnome_hit param=death_sound,gnome_death // osrs attack_sound,gnome_attack & defend_sound,scythe_slash +// Stats match osrs version but our version Vislvl is different. [gnome_guard_sword] name=Gnome guard @@ -262,6 +467,7 @@ param=death_anim,midget_death param=attack_sound,hacksword_slash // param=attack_sound,brassclash param=death_sound,gnome_death +// Stats match osrs version but our version Vislvl is different. [npc_165] name=Gnome shop keeper @@ -327,7 +533,7 @@ model1=model_2911_npc model2=model_2907_npc model3=model_2917_npc head1=model_21_npc_head -attackrange=6 +attackrange=1 respawnrate=100 hitpoints=2 param=attackbonus,-42 @@ -337,16 +543,17 @@ param=slashdefence,-42 param=crushdefence,-42 param=magicdefence,-42 param=rangedefence,-42 +param=damagetype,^ranged_style param=attack_anim,midget_attackbow param=defend_anim,midget_block param=death_anim,midget_death -param=damagetype,^ranged_style param=rangeattack_sound,arrowlaunch2 -param=proj_launch,iron_arrow_launch -param=proj_height,48 -param=proj_travel,iron_arrow_travel param=defend_sound,gnome_hit param=death_sound,gnome_death +param=proj_launch,iron_arrow_launch +param=proj_travel,iron_arrow_travel +param=proj_height,48 +// osrs stats and Vislvl match 1:1 [gnome_woman_black] name=Gnome woman @@ -371,7 +578,7 @@ model1=model_2911_npc model2=model_2907_npc model3=model_2917_npc head1=model_21_npc_head -attackrange=6 +attackrange=1 respawnrate=100 hitpoints=2 param=attackbonus,-42 @@ -381,16 +588,17 @@ param=slashdefence,-42 param=crushdefence,-42 param=magicdefence,-42 param=rangedefence,-42 +param=damagetype,^ranged_style param=attack_anim,midget_attackbow param=defend_anim,midget_block param=death_anim,midget_death -param=damagetype,^ranged_style param=rangeattack_sound,arrowlaunch2 -param=proj_launch,iron_arrow_launch -param=proj_height,48 -param=proj_travel,iron_arrow_travel param=defend_sound,gnome_hit param=death_sound,gnome_death +param=proj_launch,iron_arrow_launch +param=proj_travel,iron_arrow_travel +param=proj_height,48 +// osrs stats and Vislvl match 1:1 [gnome_pilot] name=Gnome pilot @@ -671,8 +879,13 @@ model3=model_2917_npc head1=model_21_npc_head wanderrange=0 moverestrict=nomove +hitpoints=3 +attack=3 +strength=3 +defence=3 param=death_anim,midget_death param=death_sound,gnome_death +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4978 [local_gnome] vislevel=hide @@ -687,8 +900,13 @@ model3=model_2917_npc head1=model_21_npc_head wanderrange=0 moverestrict=nomove +hitpoints=3 +attack=3 +strength=3 +defence=3 param=death_anim,midget_death param=death_sound,gnome_death +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4979 [kalron] vislevel=hide @@ -701,8 +919,13 @@ model1=model_2909_npc model2=model_2890_npc model3=model_2917_npc head1=model_21_npc_head +hitpoints=3 +attack=3 +strength=3 +defence=3 param=death_anim,midget_death param=death_sound,gnome_death +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4980 [gnome_troop_white] name=Gnome troop @@ -721,23 +944,24 @@ respawnrate=60 hitpoints=3 param=attackbonus,2 param=strengthbonus,3 +param=rangebonus,2 param=stabdefence,3 param=slashdefence,4 param=crushdefence,5 param=magicdefence,2 param=rangedefence,4 +param=damagetype,^ranged_style param=attack_anim,midget_attackbow param=defend_anim,midget_block param=death_anim,midget_death -param=damagetype,^ranged_style param=rangeattack_sound,arrowlaunch2 -param=proj_launch,iron_arrow_launch -param=proj_height,48 -param=proj_travel,iron_arrow_travel param=defend_sound,gnome_hit param=death_sound,gnome_death +param=proj_launch,iron_arrow_launch +param=proj_travel,iron_arrow_travel +param=proj_height,48 category=gnome_troop -// attack style is missing +// osrs stats and Vislvl match 1:1 [gnome_troop_black] name=Gnome troop @@ -764,20 +988,21 @@ respawnrate=60 hitpoints=3 param=attackbonus,2 param=strengthbonus,3 +param=rangebonus,2 param=stabdefence,3 param=slashdefence,4 param=crushdefence,5 param=magicdefence,2 param=rangedefence,4 +param=damagetype,^ranged_style param=attack_anim,midget_attackbow param=defend_anim,midget_block param=death_anim,midget_death -param=damagetype,^ranged_style param=rangeattack_sound,arrowlaunch2 -param=proj_launch,iron_arrow_launch -param=proj_height,48 -param=proj_travel,iron_arrow_travel param=defend_sound,gnome_hit param=death_sound,gnome_death +param=proj_launch,iron_arrow_launch +param=proj_travel,iron_arrow_travel +param=proj_height,48 category=gnome_troop -// attack style is missing \ No newline at end of file +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/areas/area_gnome/configs/rometti.obj b/data/src/scripts/areas/area_gnome/configs/rometti.obj index de952f9e97..7d40edd086 100644 --- a/data/src/scripts/areas/area_gnome/configs/rometti.obj +++ b/data/src/scripts/areas/area_gnome/configs/rometti.obj @@ -16,7 +16,6 @@ cost=200 2dxan=152 weight=12oz members=yes -tradeable=yes param=slashdefence,1 param=crushdefence,1 @@ -38,7 +37,6 @@ cost=200 2dxan=152 weight=12oz members=yes -tradeable=yes param=slashdefence,1 param=crushdefence,1 @@ -60,7 +58,6 @@ cost=200 2dxan=152 weight=12oz members=yes -tradeable=yes param=slashdefence,1 param=crushdefence,1 @@ -82,7 +79,6 @@ cost=200 2dxan=152 weight=12oz members=yes -tradeable=yes param=slashdefence,1 param=crushdefence,1 @@ -104,7 +100,6 @@ cost=200 2dxan=152 weight=12oz members=yes -tradeable=yes param=slashdefence,1 param=crushdefence,1 @@ -127,7 +122,6 @@ cost=180 2dxan=536 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -150,7 +144,6 @@ cost=180 2dxan=536 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -173,7 +166,6 @@ cost=180 2dxan=536 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -196,7 +188,6 @@ cost=180 2dxan=536 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -219,7 +210,6 @@ cost=180 2dxan=536 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -239,7 +229,6 @@ cost=180 2dxan=572 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -259,7 +248,6 @@ cost=180 2dxan=572 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -279,7 +267,6 @@ cost=180 2dxan=572 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -299,7 +286,6 @@ cost=180 2dxan=572 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -319,7 +305,6 @@ cost=180 2dxan=572 weight=2lb members=yes -tradeable=yes param=slashdefence,2 param=crushdefence,2 @@ -343,7 +328,6 @@ iop2=Wear 2dxan=152 weight=1lb members=yes -tradeable=yes param=magicattack,3 param=magicdefence,3 @@ -367,7 +351,6 @@ iop2=Wear 2dxan=152 weight=1lb members=yes -tradeable=yes param=magicattack,3 param=magicdefence,3 @@ -391,7 +374,6 @@ iop2=Wear 2dxan=152 weight=1lb members=yes -tradeable=yes param=magicattack,3 param=magicdefence,3 @@ -415,7 +397,6 @@ iop2=Wear 2dxan=152 weight=1lb members=yes -tradeable=yes param=magicattack,3 param=magicdefence,3 @@ -439,6 +420,5 @@ iop2=Wear 2dxan=152 weight=1lb members=yes -tradeable=yes param=magicattack,3 param=magicdefence,3 diff --git a/data/src/scripts/areas/area_gnome/scripts/gnome_troop.rs2 b/data/src/scripts/areas/area_gnome/scripts/gnome_troop.rs2 index ec191b445f..ea286c6352 100644 --- a/data/src/scripts/areas/area_gnome/scripts/gnome_troop.rs2 +++ b/data/src/scripts/areas/area_gnome/scripts/gnome_troop.rs2 @@ -11,14 +11,10 @@ switch_int(random(3)) { ~chatnpc("I can't talk now,|can't you see we're trying|to win a battle here."); } -[ai_queue1,_gnome_troop] ~npc_default_retaliate_ap; -[ai_opplayer2,_gnome_troop] npc_setmode(applayer2); -[ai_applayer2,_gnome_troop] ~npc_rangeattack; +[ai_queue1,gnome_troop_white] ~npc_default_retaliate_ap; +[ai_opplayer2,gnome_troop_white] npc_setmode(applayer2); +[ai_applayer2,gnome_troop_white] ~npc_rangeattack; -[ai_queue1,gnome_woman_white] ~npc_default_retaliate_ap; -[ai_opplayer2,gnome_woman_white] npc_setmode(applayer2); -[ai_applayer2,gnome_woman_white] ~npc_rangeattack; - -[ai_queue1,gnome_woman_black] ~npc_default_retaliate_ap; -[ai_opplayer2,gnome_woman_black] npc_setmode(applayer2); -[ai_applayer2,gnome_woman_black] ~npc_rangeattack; \ No newline at end of file +[ai_queue1,gnome_troop_black] ~npc_default_retaliate_ap; +[ai_opplayer2,gnome_troop_black] npc_setmode(applayer2); +[ai_applayer2,gnome_troop_black] ~npc_rangeattack; \ No newline at end of file diff --git a/data/src/scripts/areas/area_gnome/scripts/gnomes.rs2 b/data/src/scripts/areas/area_gnome/scripts/gnomes.rs2 index e63efefc22..61ceccf6e9 100644 --- a/data/src/scripts/areas/area_gnome/scripts/gnomes.rs2 +++ b/data/src/scripts/areas/area_gnome/scripts/gnomes.rs2 @@ -4,6 +4,26 @@ [opnpc1,gnome_woman_white] @talk_to_gnome_woman; [opnpc1,gnome_woman_black] @talk_to_gnome_woman; +[ai_queue1,gnome_green] ~npc_default_retaliate_ap; +[ai_opplayer2,gnome_green] npc_setmode(applayer2); +[ai_applayer2,gnome_green] ~npc_rangeattack; + +[ai_queue1,gnome_brown] ~npc_default_retaliate_ap; +[ai_opplayer2,gnome_brown] npc_setmode(applayer2); +[ai_applayer2,gnome_brown] ~npc_rangeattack; + +[ai_queue1,gnome_black] ~npc_default_retaliate_ap; +[ai_opplayer2,gnome_black] npc_setmode(applayer2); +[ai_applayer2,gnome_black] ~npc_rangeattack; + +[ai_queue1,gnome_woman_white] ~npc_default_retaliate_ap; +[ai_opplayer2,gnome_woman_white] npc_setmode(applayer2); +[ai_applayer2,gnome_woman_white] ~npc_rangeattack; + +[ai_queue1,gnome_woman_black] ~npc_default_retaliate_ap; +[ai_opplayer2,gnome_woman_black] npc_setmode(applayer2); +[ai_applayer2,gnome_woman_black] ~npc_rangeattack; + [label,talk_to_gnome] def_int $rand = random(5); ~chatplayer("Hello."); diff --git a/data/src/scripts/areas/area_mage_arena/configs/mage_arena.hunt b/data/src/scripts/areas/area_mage_arena/configs/mage_arena.hunt new file mode 100644 index 0000000000..bc60d5c9f9 --- /dev/null +++ b/data/src/scripts/areas/area_mage_arena/configs/mage_arena.hunt @@ -0,0 +1,10 @@ +[battle_mage_hunt] +type=player +check_vis=lineofsight +check_nottoostrong=off +check_notcombat=%lastcombat +check_notcombat_self=%npc_lastcombat +extracheck_var=%magearena,>5 +check_notbusy=off +find_keephunting=off +find_newmode=applayer2 \ No newline at end of file diff --git a/data/src/scripts/areas/area_mage_arena/configs/mage_arena.npc b/data/src/scripts/areas/area_mage_arena/configs/mage_arena.npc index fdaa89ecb2..ff59a859a4 100644 --- a/data/src/scripts/areas/area_mage_arena/configs/mage_arena.npc +++ b/data/src/scripts/areas/area_mage_arena/configs/mage_arena.npc @@ -173,10 +173,17 @@ model9=model_290_obj_wear head1=model_48_npc_head head2=model_82_idk_head head3=model_68_obj_wear -// TODO -hitpoints=3 attackrange=3 +// TODO respawnrate? recheck attackrange +hitpoints=3 +attack=15 +defence=20 +strength=10 +magic=15 +param=death_drop,null category=kolodion +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1605 +// TODO monster examine spell [kolodion_ogre_form] vislevel=hide @@ -199,9 +206,13 @@ recol6s=15649 recol6d=5283 model1=model_2863_npc model2=model_2871_npc -// TODO -hitpoints=65 attackrange=5 +// TODO respawnrate? +hitpoints=65 +attack=55 +strength=70 +defence=72 +magic=50 param=attack_anim,giant_attack param=magicattack_anim,giant_casting param=defend_anim,giant_block @@ -210,7 +221,10 @@ param=spawn_anim,giant_teleport param=attack_sound,giant_attack param=defend_sound,giant_hit param=death_sound,giant_death +param=death_drop,null category=kolodion +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1606 +// TODO monster examine spell [kolodion_arachnid_form] vislevel=hide @@ -225,9 +239,13 @@ op2=Attack recol1s=31393 recol1d=12690 model1=model_2884_npc -// TODO -hitpoints=65 attackrange=5 +// TODO respawnrate? +hitpoints=78 +attack=69 +strength=78 +defence=47 +magic=70 param=attack_anim,giantspider_attack param=defend_anim,giantspider_block param=death_anim,giantspider_death @@ -238,6 +256,8 @@ param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null category=kolodion +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1607 +// TODO monster examine spell [kolodion_ethereal_form] vislevel=hide @@ -271,9 +291,17 @@ model7=model_181_idk param=defend_anim,earthwarrior_def param=death_anim,earthwarrior_death param=spawn_anim,human_castteleport_reverse -hitpoints=78 +// TODO respawnrate? attackrange=5 +hitpoints=78 +attack=28 +strength=23 +defence=58 +magic=30 +param=death_drop,null category=kolodion +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1608 +// TODO monster examine spell [kolodion_demon_form] size=3 @@ -291,13 +319,13 @@ recol2d=1057 recol3s=0 recol3d=16417 model1=model_2942_npc -// TODO respawnrate? +attackrange=5 +// TODO respawnrate? confirm demonbae effect?.. hitpoints=107 attack=85 strength=98 defence=105 magic=80 -attackrange=5 param=attack_anim,demon_attack param=magicattack_anim,demon_casting param=defend_anim,demon_block @@ -307,8 +335,10 @@ param=demonbane_vulnerable,yes param=attack_sound,black_demon_attack param=defend_sound,black_demon_hit param=death_sound,black_demon_death -param=death_drop,ashes +param=death_drop,null category=kolodion +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1609 +// TODO monster examine spell [battle_mage_zamorak] name=Battle mage @@ -339,12 +369,19 @@ model7=model_260_npc model8=model_323_obj_wear model9=model_185_obj_wear model10=model_544_obj_wear -attackrange=10 +// https://youtu.be/sJflCm4c-ns +// https://youtu.be/TrxuRyogdEo&t=296 +huntmode=battle_mage_hunt +huntrange=3 +// https://youtu.be/cX7x62vqRV0&t=144 +attackrange=5 +maxrange=10 respawnrate=300 hitpoints=120 magic=50 +param=defend_anim,human_staff_def category=battle_mage -// osrs defend seq_415 +// osrs stats and Vislvl match 1:1 [battle_mage_saradomin] name=Battle mage @@ -374,12 +411,16 @@ model6=model_265_obj_wear model7=model_323_obj_wear model8=model_185_obj_wear model9=model_554_obj_wear -attackrange=10 +huntmode=battle_mage_hunt +huntrange=3 +attackrange=5 +maxrange=10 respawnrate=300 hitpoints=120 magic=50 +param=defend_anim,human_staff_def category=battle_mage -// osrs defend seq_415 +// osrs stats and Vislvl match 1:1 [battle_mage_guthix] name=Battle mage @@ -395,7 +436,10 @@ recol2d=416 model1=model_2909_npc model2=model_2898_npc model3=model_2920_npc -attackrange=10 +huntmode=battle_mage_hunt +huntrange=3 +attackrange=5 +maxrange=10 respawnrate=300 hitpoints=120 magic=50 @@ -405,4 +449,5 @@ param=defend_sound,gnome_hit param=death_sound,gnome_death param=magicattack_anim,midget_chanting param=defend_anim,midget_block -category=battle_mage \ No newline at end of file +category=battle_mage +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/areas/area_mage_arena/configs/mage_arena.obj b/data/src/scripts/areas/area_mage_arena/configs/mage_arena.obj index 137ee92062..2e01c63942 100644 --- a/data/src/scripts/areas/area_mage_arena/configs/mage_arena.obj +++ b/data/src/scripts/areas/area_mage_arena/configs/mage_arena.obj @@ -29,6 +29,7 @@ param=slashdefence,1 param=crushdefence,2 param=magicdefence,10 param=lose_cape_message,Saradomin reclaims the cape as it touches the ground. +tradeable=no [guthixcape] cost=100 @@ -61,6 +62,7 @@ param=slashdefence,1 param=crushdefence,2 param=magicdefence,10 param=lose_cape_message,Guthix reclaims the cape as it touches the ground. +tradeable=no [zamorakcape] cost=100 @@ -93,6 +95,7 @@ param=slashdefence,1 param=crushdefence,2 param=magicdefence,10 param=lose_cape_message,Zamorak reclaims the cape as it touches the ground. +tradeable=no [saradominstaff] name=Staff of saradomin @@ -122,9 +125,8 @@ param=strengthbonus,2 param=attackrate,5 param=crushattack_anim,human_blunt_crush param=defend_anim,human_blunt_defend1 -// param=crushattack_anim,human_trans_axe_chop param=crush_sound,staff_hit -// osrs use animations attack seq_401 and defend seq_403 +tradeable=no [guthixstaff] name=Staff of guthix @@ -154,9 +156,8 @@ param=strengthbonus,2 param=attackrate,5 param=crushattack_anim,human_blunt_crush param=defend_anim,human_blunt_defend1 -// param=crushattack_anim,human_trans_axe_chop param=crush_sound,staff_hit -// osrs use animations attack seq_401 and defend seq_403 +tradeable=no [zamorakstaff] name=Staff of zamorak @@ -187,6 +188,5 @@ param=strengthbonus,2 param=attackrate,5 param=crushattack_anim,human_blunt_crush param=defend_anim,human_blunt_defend1 -// param=crushattack_anim,human_trans_axe_chop param=crush_sound,staff_hit -// osrs use animations attack seq_401 and defend seq_403 +tradeable=no diff --git a/data/src/scripts/areas/area_mage_arena/scripts/battle_mage.rs2 b/data/src/scripts/areas/area_mage_arena/scripts/battle_mage.rs2 index 8e10249563..f15e8ad472 100644 --- a/data/src/scripts/areas/area_mage_arena/scripts/battle_mage.rs2 +++ b/data/src/scripts/areas/area_mage_arena/scripts/battle_mage.rs2 @@ -5,19 +5,19 @@ if (~inzone_coord_pair_table(mage_arena, coord) = true) { // some people say you cant. I assume you could autocast, // but only if you cast a manual spell first (and have autocast on). // Some guides say you cant click on npc's with autocast. - if (%magearena_progress < ^mage_arena_complete) { + if (%magearena < ^mage_arena_complete) { mes("You are not ready to fight the battle mages."); // for some reason this message appears before the singles combat messages, if you're not casting spells + return; } - return; } @player_combat_start; [apnpc2,_battle_mage] if (~inzone_coord_pair_table(mage_arena, coord) = true) { - if (%magearena_progress < ^mage_arena_complete) { + if (%magearena < ^mage_arena_complete) { mes("You are not ready to fight the battle mages."); // for some reason this message appears before the singles combat messages, if you're not casting spells + return; } - return; } @player_combat_start_ap; @@ -25,52 +25,42 @@ if (~inzone_coord_pair_table(mage_arena, coord) = true) { [ai_queue1,battle_mage_saradomin] ~npc_default_retaliate_ap; [ai_queue1,battle_mage_guthix] ~npc_default_retaliate_ap; -// todo: have mages agro the player after they defeat the boss -[ai_applayer2,battle_mage_zamorak] -if (inv_total(worn, zamorakstaff) > 0 & inv_total(worn, zamorakcape) > 0 & %npc_aggressive_player ! uid) { - npc_say("Hail Zamorak!"); - return; -} -npc_say("Feel the wrath of Zamorak."); -~npc_cast_spell(^flames_of_zamorak, 5); +[ai_applayer2,battle_mage_saradomin] @battle_mage_saradomin_attack; +[ai_applayer2,battle_mage_guthix] @battle_mage_guthix_attack; +[ai_applayer2,battle_mage_zamorak] @battle_mage_zamorak_attack; + +[ai_opplayer2,battle_mage_saradomin] @battle_mage_saradomin_attack; +[ai_opplayer2,battle_mage_guthix] @battle_mage_guthix_attack; +[ai_opplayer2,battle_mage_zamorak] @battle_mage_zamorak_attack; -[ai_applayer2,battle_mage_saradomin] -if (inv_total(worn, saradominstaff) > 0 & inv_total(worn, saradomincape) > 0 & %npc_aggressive_player ! uid) { +[label,battle_mage_saradomin_attack] +// this video shows a random chance https://youtu.be/sJflCm4c-ns?list=PLn23LiLYLb1Y4vxMPWXM-CVEvOUfuAP_o&t=130 +// the zamorak battle mage says 'Hail Zamorak!' 12 times in ~150 ticks. Im guessing a 1/10 chance +if (random(10) = 0 & inv_total(worn, saradominstaff) > 0 & inv_total(worn, saradomincape) > 0 & %npc_aggressive_player ! uid) { npc_say("Hail Saradomin!"); return; } -npc_say("Feel the wrath of Saradomin."); ~npc_cast_spell(^saradomin_strike, 5); +if (~npc_can_attack_player = true) { + npc_say("Feel the wrath of Saradomin."); +} -[ai_applayer2,battle_mage_guthix] -if (inv_total(worn, guthixstaff) > 0 & inv_total(worn, guthixcape) > 0 & %npc_aggressive_player ! uid) { +[label,battle_mage_guthix_attack] +if (random(10) = 0 & inv_total(worn, guthixstaff) > 0 & inv_total(worn, guthixcape) > 0 & %npc_aggressive_player ! uid) { npc_say("Hail Guthix!"); return; } -npc_say("Feel the wrath of Guthix."); ~npc_cast_spell(^claws_of_guthix, 5); +if (~npc_can_attack_player = true) { + npc_say("Feel the wrath of Guthix."); +} - -[ai_opplayer2,battle_mage_zamorak] -if (inv_total(worn, zamorakstaff) > 0 & inv_total(worn, zamorakcape) > 0 & %npc_aggressive_player ! uid) { +[label,battle_mage_zamorak_attack] +if (random(10) = 0 & inv_total(worn, zamorakstaff) > 0 & inv_total(worn, zamorakcape) > 0 & %npc_aggressive_player ! uid) { npc_say("Hail Zamorak!"); return; } -npc_say("Feel the wrath of Zamorak."); ~npc_cast_spell(^flames_of_zamorak, 5); - -[ai_opplayer2,battle_mage_saradomin] -if (inv_total(worn, saradominstaff) > 0 & inv_total(worn, saradomincape) > 0 & %npc_aggressive_player ! uid) { - npc_say("Hail Saradomin!"); - return; -} -npc_say("Feel the wrath of Saradomin."); -~npc_cast_spell(^saradomin_strike, 5); - -[ai_opplayer2,battle_mage_guthix] -if (inv_total(worn, guthixstaff) > 0 & inv_total(worn, guthixcape) > 0 & %npc_aggressive_player ! uid) { - npc_say("Hail Guthix!"); - return; -} -npc_say("Feel the wrath of Guthix."); -~npc_cast_spell(^claws_of_guthix, 5); \ No newline at end of file +if (~npc_can_attack_player = true) { + npc_say("Feel the wrath of Zamorak."); +} \ No newline at end of file diff --git a/data/src/scripts/areas/area_mage_arena/scripts/chamber.rs2 b/data/src/scripts/areas/area_mage_arena/scripts/chamber.rs2 index 49c608d34d..08e1ba6155 100644 --- a/data/src/scripts/areas/area_mage_arena/scripts/chamber.rs2 +++ b/data/src/scripts/areas/area_mage_arena/scripts/chamber.rs2 @@ -5,8 +5,8 @@ [label,pray_at_statue](string $name, namedobj $cape, int $stage) ~forcewalk2(movecoord(loc_coord, 0, 0, -2)); facesquare(loc_coord); -if (%magearena_progress <= ^mage_arena_prayed_at_statue) { // first time - %magearena_progress = $stage; +if (%magearena <= ^mage_arena_prayed_at_statue) { // first time + %magearena = $stage; ~mesbox("You kneel and begin to chant to <$name>..."); if_close; anim(human_pray, 10); diff --git a/data/src/scripts/areas/area_mage_arena/scripts/chamber_guardian.rs2 b/data/src/scripts/areas/area_mage_arena/scripts/chamber_guardian.rs2 index 6bc1d23f4a..efd07a2d86 100644 --- a/data/src/scripts/areas/area_mage_arena/scripts/chamber_guardian.rs2 +++ b/data/src/scripts/areas/area_mage_arena/scripts/chamber_guardian.rs2 @@ -1,5 +1,5 @@ [opnpc1,chamber_guardian] -if (%magearena_progress <= ^mage_arena_complete) { +if (%magearena <= ^mage_arena_complete) { ~chatplayer("Hello my friend, Kolodion sent me down."); ~chatnpc("Sssshhh... the gods are talking. I can hear their|whispers."); ~chatnpc("Can you hear them adventurer, they're calling you."); @@ -7,7 +7,7 @@ if (%magearena_progress <= ^mage_arena_complete) { ~chatnpc("Go chant at the statue of the god you most wish to|represent in this world, you will be rewarded."); ~chatnpc("Once you are done, come back to me. I shall supply|you with a mage staff ready for battle."); return; -} else if (%magearena_progress > ^mage_arena_prayed_at_statue & %magearena_progress < ^mage_arena_staff_given) { +} else if (%magearena > ^mage_arena_prayed_at_statue & %magearena < ^mage_arena_staff_given) { // after praying at the statue: ~chatplayer("Hi."); ~chatnpc("Hello adventurer, have you made your choice?"); @@ -15,14 +15,14 @@ if (%magearena_progress <= ^mage_arena_complete) { ~chatnpc("Good, good, I hope you have chosen well. I will now|present you with a magic staff. This, along with the|cape awarded to you by your chosen god, are all the|weapons and armour you will need here."); // check staff type def_namedobj $staff = saradominstaff; - switch_int(%magearena_progress) { + switch_int(%magearena) { case ^mage_arena_saradomin : $staff = saradominstaff; case ^mage_arena_zamorak : $staff = zamorakstaff; case ^mage_arena_guthix : $staff = guthixstaff; } inv_add(inv, $staff, 1); // drops on ground on full inv ~objbox($staff, "The guardian hands you an ornate magic staff.", 250, 0, 0); - %magearena_progress = ^mage_arena_staff_given; + %magearena = ^mage_arena_staff_given; return; } @@ -43,7 +43,7 @@ if ($choice = 1) { } [opnpc3,chamber_guardian] -if (%magearena_progress < ^mage_arena_staff_given) { +if (%magearena < ^mage_arena_staff_given) { mes("The guardian is deep in concentration."); return; } diff --git a/data/src/scripts/areas/area_mage_arena/scripts/kolodion.rs2 b/data/src/scripts/areas/area_mage_arena/scripts/kolodion.rs2 index 42da409ae5..f502cbe83e 100644 --- a/data/src/scripts/areas/area_mage_arena/scripts/kolodion.rs2 +++ b/data/src/scripts/areas/area_mage_arena/scripts/kolodion.rs2 @@ -1,5 +1,5 @@ [opnpc1,kolodion] -if (%magearena_progress < ^mage_arena_started) { +if (%magearena < ^mage_arena_started) { ~chatplayer("Hello there. What is this place?"); // https://web.archive.org/web/20050306051554/http://runevillage.com/rs2specialMageArena.php // "You must have level 60 Magic or higher, (Wizard’s Mind Bomb doesn't work in the Arena)" @@ -9,14 +9,14 @@ if (%magearena_progress < ^mage_arena_started) { ~chatnpc("Hah! A wizard of your level? Don't be absurd."); return; } - ~chatnpc("I am the great Kolodion, master of battle magic, and|this is my battle arena. Top wizards travel from all over|Gielinor to fight here."); + ~chatnpc("I am the great Kolodion, master of battle magic, and|this is my battle arena. Top wizards travel from all over|RuneScape to fight here."); @multi3("Can I fight here?", kolodion_can_i_fight_here, "What's the point of that?", kolodion_whats_the_point, "That's barbaric!", kolodion_barbaric); } if (~mage_arena_in_progress = true) { @kolodion_return; -} else if (%magearena_progress = ^mage_arena_started) { +} else if (%magearena = ^mage_arena_started) { @kolodion_lets_fight; -} else if (%magearena_progress = ^mage_arena_complete) { +} else if (%magearena = ^mage_arena_complete) { ~chatplayer("Hello, Kolodion."); ~chatnpc("Hello, young mage. You're a tough one."); @kolodion_what_now; @@ -33,7 +33,7 @@ if ($choice = 1) { return; } else if ($choice = 2) { ~chatplayer("How can I use my new spells outside of the arena?"); - ~chatnpc("Experience, my friend, experience. Once you've used|the spell enough times in the arena, you'll be able to use|them in the rest of Gielinor."); + ~chatnpc("Experience, my friend, experience. Once you've used|the spell enough times in the arena, you'll be able to use|them in the rest of RuneScape."); ~chatplayer("Good stuff."); ~chatnpc("Not so good for the citizens; they won't stand a chance."); ~chatplayer("How am I doing so far?"); @@ -84,10 +84,10 @@ if ($choice = 1) { [label,kolodion_yes_indeedy] ~chatplayer("Yes indeedy."); -~chatnpc("Good, good. You have a healthy sense of competition."); -~chatnpc("Remember, traveller - in my arena, hand-to-hand|combat is useless. Your strength will diminish as you|enter the arena, but the spells you can learn are|amongst the most powerful in all of Gielinor."); +~chatnpc("Good, good, you have a healthy sense of competition."); +~chatnpc("Remember traveller, in my arena hand to hand combat|is useless. Your strength will diminish as you enter the|arena, but the spells you can learn are amongst the most powerful in RuneScape."); ~chatnpc("Before I can accept you in, we must duel.|You may not take armour or weapons into the arena."); // second sentence is rsc -@multi2("Okay, let's fight.", kolodion_lets_fight, "No thanks.", exit); +@multi2("Ok, let's fight.", kolodion_lets_fight, "No thanks.", exit); [label,kolodion_no_i_dont] ~chatplayer("No I don't."); @@ -101,8 +101,8 @@ if (~can_enter_mage_arena = false) { return; } ~chatplayer("You don't need to worry about that."); -~chatnpc("Not just any magician can enter - only the most|powerful and most feared. Before you can use the|power of this arena, you must prove yourself against|me."); -%magearena_progress = 1; +~chatnpc("Not just any magician can enter, only the most|powerful, the most feared. Before you can use the|power of this arena, you must prove yourself against|me."); +%magearena = 1; @kolodion_teleport; @@ -138,14 +138,14 @@ def_coord $spawn_coord = movecoord(^mage_arena_start_coord, sub(coordx(npc_coord p_delay(3); p_teleport(^mage_arena_start_coord); anim(null, 0); -def_npc $boss = enum(int, npc, mage_arena_bosses, %magearena_progress); +def_npc $boss = enum(int, npc, mage_arena_bosses, %magearena); npc_huntall(^mage_arena_start_coord, 20, 0); while (npc_huntnext = true) { if (npc_type = $boss & add(%npc_lastcombat, 8) <= map_clock) { npc_del; } } -switch_int (%magearena_progress) { +switch_int (%magearena) { case ^mage_arena_started : // looks like the smoke appears 1t sooner than osrs (no 34 client tick delay as well) // https://youtu.be/Tte53ezNIP4?list=PLn23LiLYLb1Y4vxMPWXM-CVEvOUfuAP_o&t=23 diff --git a/data/src/scripts/areas/area_mage_arena/scripts/kolodion_fight.rs2 b/data/src/scripts/areas/area_mage_arena/scripts/kolodion_fight.rs2 index da43a0f419..5e8f19a5db 100644 --- a/data/src/scripts/areas/area_mage_arena/scripts/kolodion_fight.rs2 +++ b/data/src/scripts/areas/area_mage_arena/scripts/kolodion_fight.rs2 @@ -27,7 +27,7 @@ if (npc_findhero = false) { gosub(npc_death); return; } -%magearena_progress = 2; +%magearena = 2; npc_setmode(none); npc_anim(human_castteleport, 30); npc_delay(2); @@ -50,7 +50,7 @@ if (npc_findhero = false) { gosub(npc_death); return; } -%magearena_progress = 3; +%magearena = 3; npc_setmode(none); npc_anim(giant_teleport_reverse, 30); npc_delay(2); @@ -73,7 +73,7 @@ if (npc_findhero = false) { gosub(npc_death); return; } -%magearena_progress = 4; +%magearena = 4; npc_setmode(none); npc_anim(giantspider_teleport_reverse, 30); npc_delay(2); @@ -96,7 +96,7 @@ if (npc_findhero = false) { gosub(npc_death); return; } -%magearena_progress = 5; +%magearena = 5; npc_setmode(none); npc_anim(human_castteleport, 30); npc_delay(2); @@ -121,7 +121,7 @@ if (npc_findhero = false) { } queue(finish_mage_arena, 0); npc_delay(0); -%magearena_progress = ^mage_arena_complete; +%magearena = ^mage_arena_complete; npc_delay(1); npc_setmode(none); npc_anim(delrith_banish, 30); diff --git a/data/src/scripts/areas/area_mage_arena/scripts/lundail.rs2 b/data/src/scripts/areas/area_mage_arena/scripts/lundail.rs2 index bf2a4fe886..b75cc16c67 100644 --- a/data/src/scripts/areas/area_mage_arena/scripts/lundail.rs2 +++ b/data/src/scripts/areas/area_mage_arena/scripts/lundail.rs2 @@ -10,7 +10,7 @@ if ($choice = 1) { } ~chatplayer("What's that big old building above us?"); -~chatnpc("That, my friend, is the mage battle arena. Top mages come from all over Gielinor to compete in the arena."); +~chatnpc("That, my friend, is the mage battle arena. Top mages come from all over RuneScape to compete in the arena."); ~chatplayer("Wow."); ~chatnpc("Few return, most get fried, hence the smell."); ~chatplayer("Hmmm.. I did notice."); diff --git a/data/src/scripts/areas/area_mage_arena/scripts/mage_arena.rs2 b/data/src/scripts/areas/area_mage_arena/scripts/mage_arena.rs2 index f23f632eb2..0ced3950fc 100644 --- a/data/src/scripts/areas/area_mage_arena/scripts/mage_arena.rs2 +++ b/data/src/scripts/areas/area_mage_arena/scripts/mage_arena.rs2 @@ -43,7 +43,7 @@ if ($x > 0) { $dir = ^exact_west; } -if (%magearena_progress >= ^mage_arena_complete) { +if (%magearena >= ^mage_arena_complete) { ~mesbox("You step into the pool of sparkling water. You feel energy rush through your veins."); if_close; } @@ -55,7 +55,7 @@ facesquare($inside_edge); mes("You step into the pool."); p_delay(0); -if (%magearena_progress < ^mage_arena_complete) { +if (%magearena < ^mage_arena_complete) { anim(human_walk_f, 0); p_locmerge(0, 60, movecoord(loc_coord, -1, 0, -1), movecoord(loc_coord, 3, 0, 3)); p_exactmove($inside_edge, $outside_edge, 20, 40, $dir); @@ -81,7 +81,7 @@ anim(null, 0); [oploc1,loc_2880] // if north of the loc if (coordz(coord) > coordz(loc_coord)) { - if (%magearena_progress < ^mage_arena_complete) { + if (%magearena < ^mage_arena_complete) { ~mesbox("You cannot enter without the permission of Kolodion."); // rsc, might be mes return; } @@ -136,7 +136,7 @@ if ((inv_totalcat(inv, armour_hands) > 0 | inv_totalcat(worn, armour_hands) > 0) return (true); [proc,mage_arena_in_progress]()(boolean) -if (%magearena_progress < ^mage_arena_complete & %magearena_progress > ^mage_arena_started) { +if (%magearena < ^mage_arena_complete & %magearena > ^mage_arena_started) { return (true); } return (false); @@ -187,4 +187,9 @@ npc_anim(npc_param(spawn_anim), 0); npc_setmode(null); %npc_action_delay = add(map_clock, $action_delay); %npc_aggressive_player = uid; -%npc_lastcombat = add(map_clock, 8); \ No newline at end of file +%npc_lastcombat = add(map_clock, 8); + +[debugproc,ma] +if (p_finduid(uid) = true) { + p_teleport(0_48_61_20_30); +} \ No newline at end of file diff --git a/data/src/scripts/areas/area_port_sarim/configs/port_sarim.npc b/data/src/scripts/areas/area_port_sarim/configs/port_sarim.npc index 649130ad76..ed779136ef 100644 --- a/data/src/scripts/areas/area_port_sarim/configs/port_sarim.npc +++ b/data/src/scripts/areas/area_port_sarim/configs/port_sarim.npc @@ -20,7 +20,6 @@ model4=model_151_idk model5=model_176_idk model6=model_259_npc head1=model_55_idk_head -wanderrange=3 [thurgo] vislevel=hide @@ -358,13 +357,14 @@ wanderrange=2 maxrange=4 // TODO respawnrate hitpoints=5 -param=damagetype,2 +param=damagetype,^crush_style param=attack_anim,goblin_attack_unarmed param=defend_anim,goblin_block param=death_anim,goblin_death param=attack_sound,goblin_attack param=defend_sound,goblin_hit param=death_sound,goblin_death +// osrs stats and Vislvl match 1:1 [klarense] vislevel=hide diff --git a/data/src/scripts/areas/area_seers/configs/bees.obj b/data/src/scripts/areas/area_seers/configs/bees.obj index 6672d6e167..0f8545563d 100644 --- a/data/src/scripts/areas/area_seers/configs/bees.obj +++ b/data/src/scripts/areas/area_seers/configs/bees.obj @@ -9,7 +9,6 @@ members=yes 2dyan=1836 2dxan=124 weight=1oz -tradeable=yes [bucket_wax] name=Bucket of wax @@ -24,4 +23,3 @@ members=yes 2dyan=1688 2dxan=204 weight=2500g -tradeable=yes diff --git a/data/src/scripts/areas/area_seers/configs/stankers.obj b/data/src/scripts/areas/area_seers/configs/stankers.obj index aba3d486b2..79c10896a0 100644 --- a/data/src/scripts/areas/area_seers/configs/stankers.obj +++ b/data/src/scripts/areas/area_seers/configs/stankers.obj @@ -13,4 +13,3 @@ weight=2oz members=yes cost=20 category=category_69 -tradeable=yes diff --git a/data/src/scripts/areas/area_shilo/configs/shilo.obj b/data/src/scripts/areas/area_shilo/configs/shilo.obj index 034d050b6a..de91eee429 100644 --- a/data/src/scripts/areas/area_shilo/configs/shilo.obj +++ b/data/src/scripts/areas/area_shilo/configs/shilo.obj @@ -10,7 +10,6 @@ model=model_2560_obj 2dxan=320 weight=4g members=yes -tradeable=yes [ship_ticket] name=Ship ticket @@ -24,4 +23,3 @@ model=model_2560_obj 2dxan=320 weight=4g members=yes -tradeable=yes diff --git a/data/src/scripts/areas/area_taverly/configs/taverly.npc b/data/src/scripts/areas/area_taverly/configs/taverly.npc index 967b88da31..c6f442e2b9 100644 --- a/data/src/scripts/areas/area_taverly/configs/taverly.npc +++ b/data/src/scripts/areas/area_taverly/configs/taverly.npc @@ -182,12 +182,12 @@ model4=model_292_idk model5=model_170_idk model6=model_176_idk model7=model_260_npc -// osrs attackrange=8 -wanderrange=5 respawnrate=50 hitpoints=30 attack=28 strength=28 defence=32 magic=25 +// osrs stats and Vislvl match 1:1 +// TODO: recheck attackrange diff --git a/data/src/scripts/areas/area_varrock/configs/apothecary.obj b/data/src/scripts/areas/area_varrock/configs/apothecary.obj index 3955f63036..8cd4f56416 100644 --- a/data/src/scripts/areas/area_varrock/configs/apothecary.obj +++ b/data/src/scripts/areas/area_varrock/configs/apothecary.obj @@ -10,4 +10,3 @@ recol1d=9965 2dxan=84 weight=25g category=category_69 -tradeable=yes diff --git a/data/src/scripts/areas/area_varrock/configs/champions_guild.npc b/data/src/scripts/areas/area_varrock/configs/champions_guild.npc index 29d3f76330..5d5007702c 100644 --- a/data/src/scripts/areas/area_varrock/configs/champions_guild.npc +++ b/data/src/scripts/areas/area_varrock/configs/champions_guild.npc @@ -28,7 +28,6 @@ param=shop_buy_multiplier,400 param=shop_delta,30 param=shop_title,Valaine's Shop of Champions. moverestrict=indoors -param=defend_sound,female_hit param=death_sound,female_death [scavvo] diff --git a/data/src/scripts/areas/area_varrock/configs/varrock.npc b/data/src/scripts/areas/area_varrock/configs/varrock.npc index e6f58a740b..6cabb7b2d0 100644 --- a/data/src/scripts/areas/area_varrock/configs/varrock.npc +++ b/data/src/scripts/areas/area_varrock/configs/varrock.npc @@ -109,8 +109,7 @@ model4=model_353_idk model5=model_431_idk model6=model_358_idk head1=model_103_idk_head -wanderrange=2 -param=defend_sound,female_hit +moverestrict=indoors param=death_sound,female_death [sir_prysin] @@ -131,7 +130,7 @@ model4=model_176_idk model5=model_254_idk model6=model_185_obj_wear head1=model_56_obj_wear -wanderrange=4 +moverestrict=indoors [captain_rovin] vislevel=52 @@ -162,7 +161,7 @@ model8=model_519_obj_wear model9=model_323_obj_wear head1=model_63_idk_head head2=model_79_idk_head -wanderrange=4 +moverestrict=indoors [shop_keeper_varrock_generalshop] vislevel=hide @@ -291,7 +290,6 @@ param=shop_buy_multiplier,550 param=shop_delta,10 param=shop_title,Thessalia Fine Clothes. moverestrict=indoors -param=defend_sound,female_hit param=death_sound,female_death [horvik] @@ -542,7 +540,6 @@ model7=model_483_npc model8=model_533_obj_wear head1=model_115_idk_head head2=model_131_npc_head -param=defend_sound,female_hit param=death_sound,female_death [curator] @@ -622,6 +619,7 @@ hitpoints=20 attack=21 strength=21 defence=21 +param=attackrate,5 param=attackbonus,8 param=strengthbonus,10 param=stabdefence,21 @@ -629,14 +627,11 @@ param=slashdefence,23 param=crushdefence,21 param=magicdefence,-6 param=rangedefence,20 -param=attackrate,5 param=damagetype,^crush_style -param=attack_anim,human_sword_stab -param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_slash // param=defend,sound,blade3 -// osrs uses these seqs attack seq_422 defend seq_425 -// for some strange reason the attack animations are missing +// osrs weaponsmater uses the unarmed punch animation even though +// Stats match osrs version but our version Vislvl is different. [straven] name=Straven @@ -660,8 +655,15 @@ model7=model_181_idk model8=model_322_idk head1=model_53_idk_head wanderrange=1 +// maxrange= +// TODO respawnrate= hitpoints=20 -// TODO +attack=21 +strength=21 +defence=21 +param=damagetype,^crush_style +// TODO param stats +// guess stats taken from weaponmaster. [jonny_the_beard] name=Jonny the beard @@ -691,6 +693,7 @@ maxrange=6 respawnrate=74 hitpoints=8 param=damagetype,^crush_style +// Stats match osrs version but our version Vislvl is different. [king_roald] vislevel=hide @@ -740,7 +743,6 @@ model4=model_353_idk model5=model_428_idk model6=model_358_idk head1=model_118_idk_head -param=defend_sound,female_hit param=death_sound,female_death [apothecary] diff --git a/data/src/scripts/areas/area_varrock/scripts/baraek.rs2 b/data/src/scripts/areas/area_varrock/scripts/baraek.rs2 index 0b14980524..fe7ad96b63 100644 --- a/data/src/scripts/areas/area_varrock/scripts/baraek.rs2 +++ b/data/src/scripts/areas/area_varrock/scripts/baraek.rs2 @@ -35,14 +35,16 @@ switch_int(~p_choice2("Yeah, Okay, here you go.", 1, "20 gold coins? That's an o ~chatnpc("Well, I can't go any cheaper than that mate.|I have a family to feed."); return; } + inv_del(inv, coins, 18); inv_add(inv, bear_fur, 1); - ~objbox(bear_fur, "Baraek sells you a fur.", 250, 0, 0); + ~objbox(bear_fur, "Baraek sells you a fur.", 250, 0, divide(^objbox_height, 2)); } else if($option = 2) { ~chatplayer("No thanks, I'll leave it."); ~chatnpc("It's your loss mate."); } return; } + inv_del(inv, coins, 20); inv_add(inv, bear_fur, 1); ~objbox(bear_fur, "Baraek sells you a fur.", 250, 0, divide(^objbox_height, 2)); case 2 : diff --git a/data/src/scripts/areas/area_varrock/scripts/curator.rs2 b/data/src/scripts/areas/area_varrock/scripts/curator.rs2 index b3c6a4df2c..8ad29c5738 100644 --- a/data/src/scripts/areas/area_varrock/scripts/curator.rs2 +++ b/data/src/scripts/areas/area_varrock/scripts/curator.rs2 @@ -1,5 +1,32 @@ [opnpc1,curator] ~chatnpc("Welcome to the museum of Varrock."); +if (inv_total(inv, unstamped_letter) > 0) { + ~chatplayer("I have been given this letter by an examiner at the Dig Site. Can you stamp this for me?"); + ~chatnpc("What we have here? A letter of recommendation indeed..."); + // TODO: I'm not sure if this variance was available in the original 2004 port or not (likely not based on the rsc video) + if (%phoenixgang_progress = ^phoenixgang_complete | %blackarmgang_progress = ^blackarmgang_complete) { + ~chatnpc("The letter here says your name is . Well, , I wouldn't normally do this for just anyone, but as you did such a great service with the Shielf of Arrav I don't see why not. Run this letter back to the Examiner to begin your adventure into the world of Earth Sciences. Enjoy your studies, Student!"); + } else if (%romeojuliet_progress = ^romeojuliet_spoken_father) { + ~chatnpc("The letter here says your name is . Well, , I wouldn't normally do this for just anyone, but I heard what you did for Romeo and Juliet so I don't see why not. Run this letter back to the Examiner to begin your adventure into the world of Earth Sciences. Enjoy your studies, Student!"); + } else { + ~chatnpc("The letter here says your name is . Well, , I wouldn't normally do this for just anyone, but in this instance I don't see why not. Run this letter back to the Examiner to begin your adventure into the world of Earth Sciences. Enjoy your studies, Student!"); + } + // osrs sets varbit 2552 (varp 135, bit 9) to 1 signifying we've already stamped once, if we bring another letter to stamp the curator will instead say + // player: I have another letter here; could you stamp it for me again? + // curator : You've already given me one of those! But... ok, give it here... + // player: Thanks! + + // another fun fact is that osrs clears this varbit after quest completion, meaning we can go back to the curator and get the initial dialogue again + + // there's also this if we loose all the stamped letters and are still in the %itexam_progress = ^itexam_stamping quest stage + // player : I seem to have lost the letter of recommendation that you stamped for me. + // curator: Yes, I saw you drop it as you walked off last time. Here it is. + // player: Thanks! + inv_del(inv, unstamped_letter, 1); + inv_add(inv, stamped_letter, 1); + ~chatnpc("There you go, good luck student... Be sure to come back and show me your certificates. I would like to see how you get on."); + ~chatplayer("Ok, I will. Thanks, see you later."); +} if(%phoenixgang_progress = ^phoenixgang_joined | %blackarmgang_progress = ^blackarmgang_joined) { if(inv_total(inv, arravshield1) > 0 & inv_total(inv, arravshield2) > 0) { // mostly 1-1 with RSC ~chatplayer("I have retrieved the shield of Arrav|and I would like to claim my reward."); diff --git a/data/src/scripts/areas/area_wilderness/configs/bandit_camp.npc b/data/src/scripts/areas/area_wilderness/configs/bandit_camp.npc index adfd904491..6d3651d8f6 100644 --- a/data/src/scripts/areas/area_wilderness/configs/bandit_camp.npc +++ b/data/src/scripts/areas/area_wilderness/configs/bandit_camp.npc @@ -97,15 +97,16 @@ defence=27 param=attackbonus,9 param=strengthbonus,9 param=stabdefence,9 -param=slashdefence,9 +param=slashdefence,8 param=crushdefence,10 param=damagetype,^slash_style param=defend_sound,female_hit param=death_sound,female_death -category=bandit_camp_leader param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +category=bandit_camp_leader +// osrs stats and Vislvl match 1:1 [donny_the_lad] name=Donny the lad @@ -144,10 +145,11 @@ param=stabdefence,9 param=slashdefence,8 param=crushdefence,10 param=damagetype,^slash_style -category=bandit_camp_leader param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +category=bandit_camp_leader +// osrs stats and Vislvl match 1:1 [speedy_keith] name=Speedy Keith @@ -186,7 +188,8 @@ param=stabdefence,9 param=slashdefence,8 param=crushdefence,10 param=damagetype,^slash_style -category=bandit_camp_leader param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_slash +category=bandit_camp_leader +// osrs stats and Vislvl match 1:1 diff --git a/data/src/scripts/areas/area_wilderness/configs/edgeville.npc b/data/src/scripts/areas/area_wilderness/configs/edgeville.npc deleted file mode 100644 index a1a33fc23f..0000000000 --- a/data/src/scripts/areas/area_wilderness/configs/edgeville.npc +++ /dev/null @@ -1,67 +0,0 @@ -[shop_keeper_edgeville] -vislevel=hide -name=Shop keeper -desc=If he doesn't have it, he can't sell it! -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -op3=Trade -recol1s=2340 -recol1d=8354 -recol2s=14724 -recol2d=13539 -recol3s=6273 -recol3d=32767 -recol4s=14801 -recol4d=24075 -recol5s=32735 -recol5d=12583 -model1=model_215_idk -model2=model_254_idk -model3=model_246_idk -model4=model_305_obj_wear -model5=model_151_idk -model6=model_176_idk -model7=model_181_idk -head1=model_67_idk_head -category=shop_keeper -param=owned_shop,generalshop6 -param=shop_sell_multiplier,1300 -param=shop_buy_multiplier,400 -param=shop_delta,30 -param=shop_title,Edgeville General Store -moverestrict=indoors - -[shop_assistant_edgeville] -vislevel=hide -name=Shop assistant -desc=Is here on work experience. -walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r -readyanim=human_ready -op1=Talk-to -op3=Trade -recol1s=2340 -recol1d=8354 -recol2s=14724 -recol2d=13539 -recol3s=24075 -recol3d=15652 -recol4s=14801 -recol4d=15652 -recol5s=32735 -recol5d=12583 -model1=model_390_idk -model2=model_421_idk -model3=model_467_obj_wear -model4=model_332_idk -model5=model_353_idk -model6=model_358_idk -head1=model_113_idk_head -category=shop_keeper -param=owned_shop,generalshop6 -param=shop_sell_multiplier,1300 -param=shop_buy_multiplier,400 -param=shop_delta,30 -param=shop_title,Edgeville General Store -moverestrict=indoors -param=death_sound,female_death \ No newline at end of file diff --git a/data/src/scripts/areas/area_wilderness/configs/king_black_dragon.npc b/data/src/scripts/areas/area_wilderness/configs/king_black_dragon.npc index 02fd1992fa..a56a92d34d 100644 --- a/data/src/scripts/areas/area_wilderness/configs/king_black_dragon.npc +++ b/data/src/scripts/areas/area_wilderness/configs/king_black_dragon.npc @@ -46,4 +46,5 @@ param=attack_sound,dragon_attack param=defend_sound,dragon_hit param=death_sound,dragon_death param=death_drop,dragon_bones -huntmode=king_black_dragon \ No newline at end of file +huntmode=king_black_dragon +// Stats match osrs version but our version Vislvl is different. \ No newline at end of file diff --git a/data/src/scripts/areas/area_wizard_tower/configs/wizard_tower.npc b/data/src/scripts/areas/area_wizard_tower/configs/wizard_tower.npc index 79020453d7..a3a3008097 100644 --- a/data/src/scripts/areas/area_wizard_tower/configs/wizard_tower.npc +++ b/data/src/scripts/areas/area_wizard_tower/configs/wizard_tower.npc @@ -24,6 +24,11 @@ model8=model_202_obj_wear head1=model_53_idk_head head2=model_44_obj_wear head3=model_81_idk_head +hitpoints=3 +attack=20 +strength=10 +defence=15 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_7746 [wizard_grayzag] name=Wizard Grayzag @@ -48,7 +53,7 @@ model5=model_170_idk model6=model_176_idk model7=model_265_obj_wear model8=model_202_obj_wear -param=damagetype,2 +param=damagetype,^crush_style respawnrate=60 // hitpoints from: https://web.archive.org/web/20050306000545/http://www.tip.it/runescape/index.php?rs2monster_id=379 hitpoints=34 diff --git a/data/src/scripts/areas/area_yanille/configs/magic_guild/magic_guild.npc b/data/src/scripts/areas/area_yanille/configs/magic_guild/magic_guild.npc index 5312f94e31..a3274fc479 100644 --- a/data/src/scripts/areas/area_yanille/configs/magic_guild/magic_guild.npc +++ b/data/src/scripts/areas/area_yanille/configs/magic_guild/magic_guild.npc @@ -22,6 +22,11 @@ model8=model_202_obj_wear head1=model_52_idk_head head2=model_44_obj_wear head3=model_81_idk_head +hitpoints=14 +attack=8 +strength=8 +defence=5 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3246 [magic_store_owner] name=Magic Store owner @@ -47,12 +52,17 @@ model7=model_265_obj_wear model8=model_202_obj_wear head1=model_53_idk_head head2=model_44_obj_wear +hitpoints=14 +attack=8 +strength=8 +defence=5 category=shop_keeper param=owned_shop,magic_guild_store param=shop_sell_multiplier,1000 param=shop_buy_multiplier,600 param=shop_delta,100 param=shop_title,Magic Guild Store +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3247 [wizard_disentor] vislevel=hide diff --git a/data/src/scripts/areas/area_yanille/configs/yanille.npc b/data/src/scripts/areas/area_yanille/configs/yanille.npc index 880b321739..15497d9749 100644 --- a/data/src/scripts/areas/area_yanille/configs/yanille.npc +++ b/data/src/scripts/areas/area_yanille/configs/yanille.npc @@ -37,6 +37,7 @@ param=attack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_stab // param=defend_sound,big_bar_mail +// Stats match osrs version but our version Vislvl is different. [colonel_radick] name=Colonel Radick @@ -82,7 +83,7 @@ param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend1 param=attack_sound,baxe_slash // param=defend_sound,blade2 -// TODO defend sound, npc hit speeds do not match the osrs version +// Stats match osrs version but our version Vislvl is different. [sigbert_the_adventurer] vislevel=hide @@ -166,4 +167,78 @@ param=shop_sell_multiplier,1000 param=shop_buy_multiplier,550 param=shop_delta,10 param=shop_title,Frenita's Cookery Shop. -param=death_sound,female_death \ No newline at end of file +param=death_sound,female_death + +[chaos_druid_warrior] +name=Chaos druid warrior +desc=A crazy evil druid. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op2=Attack +vislevel=37 +recol1s=14724 +recol1d=19588 +recol2s=2340 +recol2d=19588 +recol3s=6273 +recol3d=21140 +model1=model_206_idk +model2=model_181_idk +model3=model_246_idk +model4=model_294_obj_wear +model5=model_170_idk +model6=model_176_idk +model7=model_260_npc +model8=model_502_obj_wear +respawnrate=100 +hitpoints=40 +attack=32 +strength=34 +defence=25 +param=attackrate,5 +param=attackbonus,9 +param=strengthbonus,5 +param=stabdefence,13 +param=slashdefence,17 +param=crushdefence,14 +param=magicdefence,-4 +param=rangedefence,14 +param=damagetype,^crush_style +param=attack_anim,human_blunt_crush +param=defend_anim,human_blunt_defend1 +param=attack_sound,mace_crush +// param=defend_sound,steel_mail +// osrs attack sound warhammer_crush +huntmode=cowardly +huntrange=1 +// osrs stats and Vislvl match 1:1 + +[salarin_the_twisted] +name=Salarin the twisted +desc=Twisted by name, twisted by nature. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +desc=A crazy evil druid +op2=Attack +vislevel=70 +recol1s=2340 +recol1d=19588 +recol2s=14724 +recol2d=19588 +recol3s=6273 +recol3d=22850 +model1=model_203_idk +model2=model_181_idk +model3=model_250_idk +model4=model_292_idk +model5=model_170_idk +model6=model_176_idk +model7=model_260_npc +respawnrate=100 +hitpoints=70 +attack=58 +strength=58 +defence=62 +param=damagetype,^crush_style +param=max_dealt,0 +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.inv b/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.inv index 29e3ec263d..030de5f28c 100644 --- a/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.inv +++ b/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.inv @@ -6,4 +6,10 @@ stackall=yes allstock=no stock1=dragon_battleaxe,2,500 stock2=dragon_mace,2,500 -// second stocks variations both items 1x \ No newline at end of file +// https://discord.com/channels/953326730632904844/1126857544523063367/1278446787681845259 +// 2004 +// https://web.archive.org/web/20050212165608/http://www.tip.it/runescape/index.php?page=rs2gld_heroes.htm +// 2004 launch? - 2006 +// https://web.archive.org/web/20060710190735/http://tip.it/runescape/?page=heros_guild.htm +// late 2006 - osrs 2024. +// http://web.archive.org/web/20061012140532/http://tip.it/runescape/?page=heros_guild.htm \ No newline at end of file diff --git a/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.npc b/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.npc index e3ec5c5ab0..660be44ca1 100644 --- a/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.npc +++ b/data/src/scripts/areas/areas_heroes_guild/configs/heroes_guild.npc @@ -24,7 +24,12 @@ model10=model_518_obj_wear head1=model_115_idk_head head2=model_136_npc_head head3=model_101_obj_wear +hitpoints=42 +attack=35 +strength=38 +defence=40 param=death_sound,female_death +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4923 [helemos] vislevel=hide @@ -61,5 +66,4 @@ param=shop_sell_multiplier,1000 param=shop_buy_multiplier,550 param=shop_delta,30 param=shop_title,Happy Heroes' Hemporium. -// we have 3 different pictures of the store in question with 3 different store names and 2 different product quantities. // Happy Heroes Hemporium. / Happy Heroes' Hemporium. / Happy Heroes' H'emporium. \ No newline at end of file diff --git a/data/src/scripts/areas/monastery/configs/prayer_guild.npc b/data/src/scripts/areas/monastery/configs/prayer_guild.npc index c2a1bddca3..d1e3af5581 100644 --- a/data/src/scripts/areas/monastery/configs/prayer_guild.npc +++ b/data/src/scripts/areas/monastery/configs/prayer_guild.npc @@ -23,6 +23,11 @@ model9=model_284_obj_wear head1=model_59_idk_head head2=model_80_idk_head wanderrange=3 +hitpoints=15 +attack=2 +strength=2 +defence=3 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_2577 [brother_jered] vislevel=hide @@ -48,6 +53,11 @@ model8=model_280_obj_wear model9=model_284_obj_wear head1=model_59_idk_head wanderrange=3 +hitpoints=15 +attack=2 +strength=2 +defence=3 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_2578 [monk] name=Monk @@ -77,4 +87,5 @@ attack=2 strength=2 defence=3 param=damagetype,^crush_style -param=retreat,7 \ No newline at end of file +param=retreat,7 +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/drop tables/scripts/mugger.rs2 b/data/src/scripts/drop tables/scripts/mugger.rs2 index 0394c2884d..feab4fe811 100644 --- a/data/src/scripts/drop tables/scripts/mugger.rs2 +++ b/data/src/scripts/drop tables/scripts/mugger.rs2 @@ -1,4 +1,4 @@ -[ai_queue3,npc_175] +[ai_queue3,mugger] gosub(npc_death); if (npc_findhero = false) { return; diff --git a/data/src/scripts/engine.constant b/data/src/scripts/engine.constant index 12f89ff3e1..fa94bb504d 100644 --- a/data/src/scripts/engine.constant +++ b/data/src/scripts/engine.constant @@ -23,3 +23,7 @@ ^loc_south = 3 ^string_empty = + +// for gettimespent +^millis = 0 +^micros = 1 diff --git a/data/src/scripts/engine.rs2 b/data/src/scripts/engine.rs2 index bbaf6871ca..f03874b901 100644 --- a/data/src/scripts/engine.rs2 +++ b/data/src/scripts/engine.rs2 @@ -1,435 +1,718 @@ // Core language ops (0-99) +// Call a proc and return to this point after. You cannot pass any arguments to it. [command,gosub](proc $proc) +// Jump to a label and continue the script there. You cannot pass any arguments it. [command,jump](label $label) // Server ops (1000-1999) +// Get the world's current cycle count [command,map_clock]()(int) +// Returns true if the world is configured as a members world [command,map_members]()(boolean) +// Get the number of players in a given area [command,map_playercount](coord $coord1, coord $coord2)(int) +// Search (hunt) for players in a given area [command,huntall](coord $source, int $distance, int $checkvis) +// Use the next result from huntall [command,huntnext]()(boolean) [command,.huntnext]()(boolean) +// Search (hunt) for npcs in a given area [command,npc_huntall](coord $source, int $distance, int $checkvis) +// Use the next result from npc_huntall [command,npc_huntnext]()(boolean) [command,.npc_huntnext]()(boolean) +// Returns true if $pos is in the area between $from and $to [command,inzone](coord $from, coord $to, coord $pos)(boolean) -[command,.inzone](coord $from, coord $to, coord $pos)(boolean) +[command,.inzone](coord $from, coord $to, coord $pos)(boolean) // todo: replace all instances of this with inzone, should not have secondary +// Returns true if $from has an unbroken line-of-walk to $to [command,lineofwalk](coord $from, coord $to)(boolean) +// Roll a skill success check [command,stat_random](int $level, int $low, int $high)(boolean) +// Play a spotanim on a tile [command,spotanim_map](spotanim $anim, coord $coord, int $height, int $delay) +// [command,map_anim](coord $coord, spotanim $spotanim, int $height, int $delay) // this is the name for the packet +// Get the distance between two coords [command,distance](coord $coord1, coord $coord2)(int) +// Move a coord across each axis [command,movecoord](coord $coord, int $x, int $y, int $z)(coord) +// Get how long a seq takes to play on the client [command,seqlength](seq $seq)(int) +// Initialize the split text system [command,split_init](string $text, int $width, int $lines, fontmetrics $font) +// Get how many pages split_init has calculated [command,split_pagecount]()(int) +// Get the split text on a given $page and $line [command,split_get](int $page, int $line)(string) +// Get the number of lines in a given $page [command,split_linecount](int $page)(int) +// Get the anim for a given $page [command,split_getanim](int $page)(seq) +// Get a param on a struct [command,struct_param]/*(struct $struct, param $param)(dynamic)*/ +// Get the x axis of a coord [command,coordx](coord $coord)(int) +// Get the y axis (level) of a coord [command,coordy](coord $coord)(int) +// Get the z axis (NOT level) of a coord [command,coordz](coord $coord)(int) +// Get how many players are currently in the world [command,playercount]()(int) +// Returns true if the map tile at $coord is blocked [command,map_blocked](coord $coord)(boolean) +// Returns true if the map tile at $coord is indoors [command,map_indoors](coord $coord)(boolean) +// Returns true if $from has an unbroken line-of-walk to $to [command,lineofsight](coord $from, coord $to)(boolean) +// Delay this script for $delay ticks on the world, not tied to any player/npc [command,world_delay](int $delay) -[command,map_anim](coord $coord, spotanim $spotanim, int $height, int $delay) +// Cast a projectile targeting a player [command,projanim_pl](coord $from, player_uid $to, spotanim $spotanim, int $fromHeight, int $toHeight, int $delay, int $duration, int $peak, int $arc) +// Cast a projectile targeting a npc [command,projanim_npc](coord $from, npc_uid $to, spotanim $spotanim, int $fromHeight, int $toHeight, int $delay, int $duration, int $peak, int $arc) +// Cast a projectile targeting a coord [command,projanim_map](coord $from, coord $to, spotanim $spotanim, int $fromHeight, int $toHeight, int $delay, int $duration, int $peak, int $arc) +// Returns true if it's unsafe to spawn a loc on this tile [command,map_locaddunsafe](coord $coord)(boolean) -[command,npccount]()(int) -[command,zonecount]()(int) -[command,loccount]()(int) -[command,objcount]()(int) +// Get the number of npcs in the world +[command,npccount]()(int) // todo: move this to debug ops +// Get the number of zones in the world +[command,zonecount]()(int) // todo: move this to debug ops +// Get the number of objects in the world +[command,loccount]()(int) // todo: move this to debug ops +// Get the number of locs in the world +[command,objcount]()(int) // todo: move this to debug ops +// Get a random coord centered on $coord within $minradius and $maxradius, using ^map_findsquare_ constants for $type [command,map_findsquare](coord $coord, int $minradius, int $maxradius, int $type)(coord) -[command,map_multi](coord $coord)(boolean) +// Returns true if the map tile at $coord is in a multi-way combat area +[command,map_multiway](coord $coord)(boolean) // Player ops (2000-2499) +// Get access to $player if they are in the world [command,finduid](player_uid $player)(boolean) [command,.finduid](player_uid $player)(boolean) +// Get protected access to $player if they are in the world and accessible [command,p_finduid](player_uid $player)(boolean) [command,.p_finduid](player_uid $player)(boolean) +// Strong-queue a script on a player (do not use in early 2004) [command,strongqueue](queue $queue, int $delay) +// Weak-queue a script on a player (do not use in early 2004) [command,weakqueue](queue $queue, int $delay) +// Play an animation on a player [command,anim](seq $anim, int $delay) [command,.anim](seq $anim, int $delay) +// Returns true if the player's packet buffer is full for this cycle [command,buffer_full]()(int) +// Refresh the player's appearance [command,buildappearance](inv $inv) [command,.buildappearance](inv $inv) +// Move the camera [command,cam_moveto](coord $sourceCoord, int $sourceHeight, int $moveSpeed, int $moveMultiplier) +// Make the camera look at a coord [command,cam_lookat](coord $destCoord, int $destHeight, int $rotationSpeed, int $rotationMultiplier) +// Shake the camera [command,cam_shake](int $type, int $jitter, int $amplitude, int $frequency) +// Reset the camera back to the player [command,cam_reset] [command,.cam_reset] +// Get the player's coord [command,coord]()(coord) [command,.coord]()(coord) +// Get the player's formatted display name [command,displayname]()(string) [command,.displayname]()(string) +// Make the player face a coord [command,facesquare](coord $coord) [command,.facesquare](coord $coord) +// Restore the player's run energy [command,healenergy](int $amount) [command,.healenergy](int $amount) +// Close open interfaces [command,if_close] [command,.if_close] +// Get the last component that was clicked [command,last_com]()(component) +// Get the last int (number) that was input [command,last_int]()(int) +// Get the last item that was selected [command,last_item]()(obj) // unconfirmed, inferred from useitem and useslot +// Get the last item's slot [command,last_slot]()(int) +// Get the last used item (useitem on item) [command,last_useitem]()(obj) +// Get the last used item's slot [command,last_useslot]()(int) +// Send a message to the chatbox [command,mes](string $text) [command,.mes](string $text) +// Get the player's internally stored name - lowercased, underscores [command,name]()(string) +// Requires protected access - set [command,p_aprange](int $range) +// Requires protected access - if the player moved this cycle, wait a tick before continuing [command,p_arrivedelay] +// Requires protected access - open a number input dialog [command,p_countdialog] +// Requires protected access - delay this script/the player for $delay cycles [command,p_delay](int $delay) [command,.p_delay](int $delay) +// Requires protected access - run the opheld $op trigger for the item at $slot in $inv [command,p_opheld](int $op, int $inv, int $slot) +// Requires protected access - set the player's interaction to oploc $op on the active_loc [command,p_oploc](int $op) +// Requires protected access - set the player's interaction to opnpc $op on the active_npc [command,p_opnpc](int $op) +// Requires protected access - cast a spell on the active_npc [command,p_opnpct](component $spell) +// Requires protected access - open a "Click here to continue" dialog [command,p_pausebutton] [command,.p_pausebutton] +// Requires protected access - clear the current interaction and walk queue [command,p_stopaction] [command,.p_stopaction] +// Requires protected access - teleport the player to $coord, forcing a visual teleport [command,p_telejump](coord $coord) [command,.p_telejump](coord $coord) +// Requires protected access - walk the player to $dest [command,p_walk](coord $dest) [command,.p_walk](coord $dest) +// Make the player say $text overhead [command,say](string $text) [command,.say](string $text) +// Play a $sound [command,sound_synth](synth $sound, int $loops, int $delay) [command,.sound_synth](synth $sound, int $loops, int $delay) +// Get the permissions level the player has [command,staffmodlevel]()(int) [command,.staffmodlevel]()(int) +// Get the current level of $stat (different than base) [command,stat](stat $stat)(int) [command,.stat](stat $stat)(int) +// Get the base level of $stat [command,stat_base](stat $stat)(int) [command,.stat_base](stat $stat)(int) +// Boost $stat [command,stat_add](stat $stat, int $constant, int $percent) [command,.stat_add](stat $stat, int $constant, int $percent) +// Drain $stat [command,stat_sub](stat $stat, int $constant, int $percent) [command,.stat_sub](stat $stat, int $constant, int $percent) +// Heal $stat back to base [command,stat_heal](stat $stat, int $constant, int $percent) [command,.stat_heal](stat $stat, int $constant, int $percent) +// Get the player's UID to use in finduid/p_finduid later [command,uid]()(player_uid) [command,.uid]()(player_uid) +// Requires protected access - request the player to log out [command,p_logout] +// Set a component's colour [command,if_setcolour](component $component, int $colour) +// Open a modal in the chat box [command,if_openchat](interface $interface) [command,.if_openchat](interface $interface) +// Open two modals, one in the main viewport and one on the side tab [command,if_openmain_side](interface $interface1, interface $interface2) [command,.if_openmain_side](interface $interface1, interface $interface2) +// Hide a component [command,if_sethide](component $component, boolean $hide) [command,.if_sethide](component $component, boolean $hide) +// Set a component's model to an object [command,if_setobject](component $component, obj $obj, int $scale) [command,.if_setobject](component $component, obj $obj, int $scale) +// Set a component's model [command,if_setmodel](component $component, int $model) +// Recolor a component's model [command,if_setrecol](component $component, int $src, int $dest) +// Open the tutorial modal mode ("sticky" interface) [command,tut_open](interface $interface) +// Close the tutorial modal mode (back to normal gameplay) [command,tut_close] +// Flash a side tab icon [command,tut_flash](int $tab) -[command,if_setanim](component $component,seq $anim) +// Set a component's model animation +[command,if_setanim](component $component, seq $anim) +// Set a side tab to a specific interface [command,if_settab](interface $interface, int $tab) [command,.if_settab](interface $interface, int $tab) +// Change the player's open side tab [command,if_settabactive](int $tab) [command,.if_settabactive](int $tab) +// Open a modal in the main viewport [command,if_openmain](interface $interface) [command,.if_openmain](interface $interface) // later // [command,if_openoverlay](interface $interface) // [command,.if_openoverlay](interface $interface) +// Open a modal in the side tab [command,if_openside](interface $interface) +// Set a component's model to the local player's chat head [command,if_setplayerhead](component $component) +// Set a component's text [command,if_settext](component $component, string $text) [command,.if_settext](component $component, string $text) +// Set a component's model to a npc's chat head [command,if_setnpchead](component $component, npc $npc) +// Reposition a component [command,if_setposition](component $component, int $x, int $y); +// Give xp in a stat [command,stat_advance](stat $stat, int $exp) +// Hurt a player [command,damage](player_uid $uid, int $type, int $amount) [command,.damage](player_uid $uid, int $type, int $amount) +// internal- set which buttons can re-trigger the suspended script [command,if_setresumebuttons](component $component1, component $component2, component $component3, component $component4, component $component5) +// Choose a text string based on the player's gender [command,text_gender](string $male_text, string $female_text)(string) [command,.text_gender](string $male_text, string $female_text)(string) +// Play a song [command,midi_song](string $song) +// Play a jingle (advancing levels, completing quests, ...) [command,midi_jingle](string $jingle, int $length) [command,.midi_jingle](string $jingle, int $length) +// Show the hint arrow at $coord [command,hint_coord](int $offset, coord $coord, int $height) +// Start a softtimer on the active_player [command,softtimer]/*(softtimer $timer, int $interval, ...)*/ [command,.softtimer]/*(softtimer $timer, int $interval, ...)*/ +// Clear a softtimer from the active_player [command,clearsofttimer](softtimer $timer) [command,.clearsofttimer](softtimer $timer) +// Start a timer on the active_player [command,settimer]/*(timer $timer, int $interval, ...)*/ [command,.settimer]/*(timer $timer, int $interval, ...)*/ +// Clear a timer from the active_player [command,cleartimer](timer $timer) [command,.cleartimer](timer $timer) -[command,gettimer](timer $timer)(int)// guess +// Return ^true if the active_player has $timer running +[command,gettimer](timer $timer)(int) // confirmed +// Play a spotanim on the active_player [command,spotanim_pl](spotanim $spotanim, int $height, int $delay) [command,.spotanim_pl](spotanim $spotanim, int $height, int $delay) +// Clear the hint arrow [command,hint_stop] [command,.hint_stop] +// Requires protected access - move the player from $startCoord to $endCoord with a finer ability to control speed [command,p_exactmove](coord $startCoord, coord $endCoord, int $startCycle, int $endCycle, int $direction) +// Queue a script on a player [command,queue](queue $queue, int $delay) // , $arg) [command,.queue](queue $queue, int $delay) // , $arg) +// Returns true if the player has an open modal or is delayed [command,busy]()(boolean) [command,.busy]()(boolean) +// Returns true if the player has an interaction or waypoints to walk to [command,busy2]()(boolean) [command,.busy2]()(boolean) +// Get the number of queued scripts that are specifically $queue [command,getqueue](queue $queue)(int) [command,.getqueue](queue $queue)(int) +// Requires protected access - merge the player's visual model with a loc so render priorities are correct [command,p_locmerge](int $startCycle, int $endCycle, coord $southEast, coord $northWest); +// Show the welcome screen [command,last_login_info] +// Requires protected access - teleport the player to $coord, short distances (1-2 tiles) will visually walk/run [command,p_teleport](coord $coord) [command,.p_teleport](coord $coord) +// Set the player's base ready animation [command,bas_readyanim](seq $seq) -[command,bas_turnonspot](seq $seq) -[command,bas_walk_f](seq $seq) -[command,bas_walk_b](seq $seq) -[command,bas_walk_l](seq $seq) -[command,bas_walk_r](seq $seq) -[command,bas_running](seq $seq) [command,.bas_readyanim](seq $seq) +// Set the player's base turn-on-spot animation +[command,bas_turnonspot](seq $seq) [command,.bas_turnonspot](seq $seq) +// Set the player's base walking forward animation +[command,bas_walk_f](seq $seq) [command,.bas_walk_f](seq $seq) +// Set the player's base walking backwards animation +[command,bas_walk_b](seq $seq) [command,.bas_walk_b](seq $seq) +// Set the player's base turn-left animation +[command,bas_walk_l](seq $seq) [command,.bas_walk_l](seq $seq) +// Set the player's base turn-right animation +[command,bas_walk_r](seq $seq) [command,.bas_walk_r](seq $seq) +// Set the player's base running animation +[command,bas_running](seq $seq) [command,.bas_running](seq $seq) +// Get the player's current gender (0 = male, 1 = female) [command,gender]()(int) [command,.gender]()(int) +// Show the hint arrow on $npc [command,hint_npc](npc_uid $npc) +// Show the hint arrow on $player [command,hint_player](player_uid $player) [command,.hint_player](player_uid $player) +// Get the currently set headicons [command,headicons_get]()(int) [command,.headicons_get]()(int) +// Set the player's headicons [command,headicons_set](int $icons) [command,.headicons_set](int $icons) +// Requires protected access - set the player's interaction to opobj $op on the active_player [command,p_opobj](int $op) +// Requires protected access - set the player's interaction to opplayer $op on the active_player [command,p_opplayer](int $op) [command,.p_opplayer](int $op) +// Requires protected access - cast a spell on the active_player [command,p_opplayert](component $spell) +// Find all players around $coord (limited to the nearest 8x8 zone area) [command,player_findallzone](coord $coord) +// Use the next result from player_findallzone [command,player_findnext]()(boolean) +// Allow the player to redesign their appearance (the packet is sent to the server) [command,allowdesign](boolean $allow) +// Used in inv_buttond, similar to last_useslot, this is the other item in scope [command,last_targetslot]()(int) +// Set the player's walktrigger [command,walktrigger](walktrigger $trigger) [command,.walktrigger](walktrigger $trigger) +// Get the player's current walktrigger [command,getwalktrigger]()(walktrigger) [command,.getwalktrigger]()(walktrigger) +// Clear the player's script queue [command,clearqueue](queue $queue) [command,.clearqueue](queue $queue) +// Returns ^true if the player is ready for another AFK event [command,afk_event]()(int) +// Get the player's low memory mode [command,lowmemory]()(boolean) +// Set the player's identity kit [command,setidkit](idkit $kit, int $color) +// Set the active_player to the hero that's done the most damage to the current active_player [command,findhero]()(boolean) [command,.findhero]()(boolean) +// Track damage dealt to the active_player from .active_player [command,both_heropoints](int $damage) +// Set the player's gender [command,setgender](int $gender) +// Set the player's skin [command,setskincolour](int $skin_colour) +// Requires protected access - allow or deny animations to be played [command,p_animprotect](int $toggle) [command,.p_animprotect](int $toggle) +// Get the player's curernt run energy [command,runenergy]()(int) +// Get the player's current run weight [command,weight]()(int) +// Requires protected access - clear the current interaction, but leave the walk queue intact [command,p_clearpendingaction] // Npc ops (2500-2999) +// Get access to the npc if they are in the world [command,npc_finduid](npc_uid $uid)(boolean) [command,.npc_finduid](npc_uid $uid)(boolean) +// Spawn a new NPC in the world [command,npc_add](coord $coord, npc $npc, int $duration) [command,.npc_add](coord $coord, npc $npc, int $duration) +// Play an animation on a npc [command,npc_anim](seq $seq, int $delay) [command,.npc_anim](seq $seq, int $delay) +// Get the current npc's category [command,npc_category]()(category) [command,.npc_category]()(category) +// Get the current npc's coord [command,npc_coord]()(coord) [command,.npc_coord]()(coord) +// Delete the current npc [command,npc_del] [command,.npc_del] +// Delay this script/npc for $delay cycles [command,npc_delay](int $delay) [command,.npc_delay](int $delay) +// Make the npc face a coord [command,npc_facesquare](coord $coord) [command,.npc_facesquare](coord $coord) +// Return true if a specific npc exists at $coord and passes a visibility check [command,npc_find](coord $coord, npc $npc, int $distance, int $checkvis)(boolean) [command,.npc_find](coord $coord, npc $npc, int $distance, int $checkvis)(boolean) +// Search for npcs in a given area [command,npc_findall](coord $coord, npc $npc, int $distance, int $checkvis) [command,.npc_findall](coord $coord, npc $npc, int $distance, int $checkvis) +// Search for any npc in a given area [command,npc_findallany](coord $coord, int $distance, int $checkvis) [command,.npc_findallany](coord $coord, int $distance, int $checkvis) +// Return true if a specific npc exists at $coord [command,npc_findexact](coord $coord, npc $npc)(boolean) +// Return true if the player that has dealt the most damage to this npc is in the world [command,npc_findhero]()(boolean) +// Get a param on the current npc [command,npc_param]/*(param $param)(dynamic)*/ +// Queue a script on a npc [command,npc_queue](int $ai_queue, int $arg, int $delay) [command,.npc_queue](int $ai_queue, int $arg, int $delay) +// Get the distance between the npc and a coord [command,npc_range](coord $coord)(int) +// Make the npc say $text overhead [command,npc_say](string $text) [command,.npc_say](string $text) +// Set the npc's hunt distance [command,npc_sethunt](int $distance) +// Set the npc's hunt mode [command,npc_sethuntmode](hunt $hunt) +// Set the npc's ai mode [command,npc_setmode](npc_mode $mode) [command,.npc_setmode](npc_mode $mode) +// Get the base level of $stat [command,npc_basestat](npc_stat $stat)(int) +// Get the current level of $stat [command,npc_stat](npc_stat $stat)(int) +// Boost $stat [command,npc_statadd](npc_stat $stat, int $constant, int $percent) +// Heal $stat back to base [command,npc_statheal](npc_stat $stat, int $amount_to_heal, int $percent_to_heal) +// Drain $stat [command,npc_statsub](npc_stat $stat, int $constant, int $percent) +// Get the current npc's type [command,npc_type]()(npc) [command,.npc_type]()(npc) +// Hurt the current npc [command,npc_damage](int $type, int $amount) +// Get the current npc's display name [command,npc_name]()(string) [command,.npc_name]()(string) +// Get the npc's UID to use in npc_finduid later [command,npc_uid]()(npc_uid) [command,.npc_uid]()(npc_uid) +// Start the npc's timer to run on each $interval cycle [command,npc_settimer](int $interval) [command,.npc_settimer](int $interval) +// Play a spotanim on the npc [command,spotanim_npc](spotanim $spotanim, int $height, int $delay) [command,.spotanim_npc](spotanim $spotanim, int $height, int $delay) +// Find all NPCs around $coord (limited to the nearest 8x8 zone area) [command,npc_findallzone](coord $coord) +// Use the next result from npc_findallzone [command,npc_findnext]()(boolean) [command,.npc_findnext]()(boolean) +// Teleport the npc to $coord, short distances (1-2 tiles) will visually walk/run [command,npc_tele](coord $coord) [command,.npc_tele](coord $coord) +// Change the npc's current type - new npc properties will be inherited [command,npc_changetype](npc $type) +// Return the current npc's ai mode [command,npc_getmode]()(npc_mode) [command,.npc_getmode]()(npc_mode) +// Track damage dealt to the active_npc from active_player [command,npc_heropoints](int $damage) +// Set the npc's walktrigger [command,npc_walktrigger](int $ai_queue, int $arg) [command,.npc_walktrigger](int $ai_queue, int $arg) +// Walk the npc to $coord [command,npc_walk](coord $coord) [command,.npc_walk](coord $coord) +// Get the npc's attack range [command,npc_attackrange]()(int) [command,.npc_attackrange]()(int) +// If the NPC moved this cycle, wait a tick before continuing [command,npc_arrivedelay] +// Return true if the npc has the specified op [command,npc_hasop](int $op)(boolean) [command,.npc_hasop](int $op)(boolean) // Loc ops (3000-3499) +// Spawn a loc at $coord [command,loc_add](coord $coord, loc $loc, int $angle, locshape $shape, int $duration) [command,.loc_add](coord $coord, loc $loc, int $angle, locshape $shape, int $duration) +// Get the current loc's angle [command,loc_angle]()(int) +// Play an animation on the loc [command,loc_anim](seq $anim) +// Get the current loc's category [command,loc_category]()(category) +// Change the loc into a new loc for $duration cycles [command,loc_change](loc $new_loc, int $duration) [command,.loc_change](loc $new_loc, int $duration) +// Get the current loc's coord [command,loc_coord]()(coord) [command,.loc_coord]()(coord) +// Delete the current loc, it will respawn in $duration cycles if it's a permanent loc [command,loc_del](int $duration) [command,.loc_del](int $duration) +// Return true if a specific loc exists at $coord [command,loc_find](coord $coord, loc $loc)(boolean) [command,.loc_find](coord $coord, loc $loc)(boolean) +// Find all locs around $coord (limited to the nearest 8x8 zone area) [command,loc_findallzone](coord $coord) +// Use the next result from loc_findallzone [command,loc_findnext]()(boolean) +// Get a param on the current loc [command,loc_param]/*(param $param)(dynamic)*/ +// Get the current loc's type [command,loc_type]()(loc) [command,.loc_type]()(loc) +// Get the current loc's display name [command,loc_name]()(string) +// Get the current loc's shape [command,loc_shape]()(locshape) [command,.loc_shape]()(locshape) // Obj ops (3500-4000) +// Spawn an object at $coord for the current player [command,obj_add](coord $coord, namedobj $obj, int $count, int $duration) [command,.obj_add](coord $coord, namedobj $obj, int $count, int $duration) +// Spawn an object at $coord for all players [command,obj_addall](coord $coord, namedobj $obj, int $count, int $duration) +// Get a param on the current object [command,obj_param]/*(param $param)(dynamic)*/ +// Get the current object's display anme [command,obj_name]()(string) +// Despawn the current object [command,obj_del] +// Get how many of the current object there are [command,obj_count]()(int) +// Get the current object's type [command,obj_type]()(namedobj) +// Pick up the current object and place it in $inv [command,obj_takeitem](inv $inv) +// Get the current object's coord [command,obj_coord]()(coord) +// Return true if a specific object exists at $coord [command,obj_find](coord $coord, obj $obj)(boolean) // Npc config ops (4000-4099) +// Get the name from a npc config [command,nc_name](npc $npc)(string) +// Get a param from a npc config [command,nc_param]/*(npc $npc, param $param)(dynamic)*/ +// Get the category from a npc config [command,nc_category](npc $npc)(category) +// Get the description text from a npc config [command,nc_desc](npc $npc)(string) +// Get the internal debug name from a npc config [command,nc_debugname](npc $npc)(string) +// Get the display name from a npc config [command,nc_op](npc $npc, int $op)(string) // Loc config ops (4100-4199) +// Get the name from a loc config [command,lc_name](loc $loc)(string) +// Get a param from a loc config [command,lc_param]/*(loc $loc, param $param)(dynamic)*/ +// Get the category from a loc config [command,lc_category](loc $loc)(category) +// Get the description text from a loc config [command,lc_desc](loc $loc)(string) +// Get the internal debug name from a loc config [command,lc_debugname](loc $loc)(string) +// Get the width from a loc config [command,lc_width](loc $loc)(int) +// Get the length from a loc config [command,lc_length](loc $loc)(int) // Obj config ops (4200-4299) +// Get the obj config's name [command,oc_name](obj $obj)(string) +// Get a param from an obj config [command,oc_param]/*(obj $obj, param $param)(dynamic)*/ +// Get the category from an obj config [command,oc_category](obj $obj)(category) +// Get the description text from an obj config [command,oc_desc](obj $obj)(string) +// Get the members requirement from an obj config [command,oc_members](obj $obj)(boolean) +// Get the weight from an obj config [command,oc_weight](obj $obj)(int) +// Get the first "wearpos" - wear position - worn slot from an obj config [command,oc_wearpos](obj $obj)(int) +// Get the second "wearpos" - wear position - worn slot from an obj config [command,oc_wearpos2](obj $obj)(int) +// Get the third "wearpos" - wear position - worn slot from an obj config [command,oc_wearpos3](obj $obj)(int) +// Get the cost from an obj config [command,oc_cost](obj $obj)(int) +// Return true if an obj is tradeable [command,oc_tradeable](obj $obj)(boolean) +// Get the internal debug name from an obj config [command,oc_debugname](obj $obj)(string) +// Get the certed version of an obj [command,oc_cert](obj $obj)(obj) +// Get the uncerted version of an obj [command,oc_uncert](obj $obj)(obj) +// Return true if an obj is stackable [command,oc_stackable](obj $obj)(boolean) // Inventory ops (4300-4399) +// Get the inv config's allstock state [command,inv_allstock](inv $inv)(boolean) +// Get the inv config's size [command,inv_size](inv $inv)(int) -[command,.inv_size](inv $inv)(int) +[command,.inv_size](inv $inv)(int) // todo: remove this +// Get the base stock of $obj in the inv config [command,inv_stockbase](inv $inv, obj $obj)(int) +// Add an object to an inventory [command,inv_add](inv $inv, namedobj $obj, int $count) [command,.inv_add](inv $inv, namedobj $obj, int $count) +// Replace an object in an inventory [command,inv_changeslot](inv $inv, namedobj $find, namedobj $replace, int $replace_count) // Unconfirmed arguments, inferred from comment in a released script [command,.inv_changeslot](inv $inv, namedobj $find, namedobj $replace, int $replace_count) +// Clear all objects from an inventory [command,inv_clear](inv $inv) [command,.inv_clear](inv $inv) +// Delete an $count of an object from an inventory [command,inv_del](inv $inv, obj $obj, int $count) [command,.inv_del](inv $inv, obj $obj, int $count) +// Delete everything in $slot from an inventory [command,inv_delslot](inv $inv, int $slot) [command,.inv_delslot](inv $inv, int $slot) +// Drop an object from an inventory [command,inv_dropitem](inv $inv, coord $coord, obj $obj, int $count, int $duration) [command,.inv_dropitem](inv $inv, coord $coord, obj $obj, int $count, int $duration) +// Drop everything in $slot from an inventory [command,inv_dropslot](inv $inv, coord $coord, int $slot, int $duration) [command,.inv_dropslot](inv $inv, coord $coord, int $slot, int $duration) +// Get the number of free slots in an inventory [command,inv_freespace](inv $inv)(int) [command,.inv_freespace](inv $inv)(int) +// Get the number of objects in $slot [command,inv_getnum](inv $inv, int $slot)(int) [command,.inv_getnum](inv $inv, int $slot)(int) +// Get the object in $slot [command,inv_getobj](inv $inv, int $slot)(obj) [command,.inv_getobj](inv $inv, int $slot)(obj) +// Check if an object fits in an inventory [command,inv_itemspace](inv $inv, obj $obj, int $count, int $size)(boolean) [command,.inv_itemspace](inv $inv, obj $obj, int $count, int $size)(boolean) +// Check if an object fits in an inventory, returning the overflowed amount, if any [command,inv_itemspace2](inv $inv, obj $obj, int $count, int $size)(int) [command,.inv_itemspace2](inv $inv, obj $obj, int $count, int $size)(int) +// Move an object to another slot [command,inv_movefromslot](inv $from_inv, inv $to_inv, int $from_slot) [command,.inv_movefromslot](inv $from_inv, inv $to_inv, int $from_slot) +// Move an object from one slot to another slot [command,inv_movetoslot](inv $from_inv, inv $to_inv, int $from_slot, int $to_slot) [command,.inv_movetoslot](inv $from_inv, inv $to_inv, int $from_slot, int $to_slot) +// Move all items from one player's inventory to another [command,both_moveinv](inv $from_inv, inv $to_inv) [command,.both_moveinv](inv $from_inv, inv $to_inv) +// Move an object from one inventory to another (first free slot) [command,inv_moveitem](inv $from_inv, inv $to_inv, obj $obj, int $count) [command,.inv_moveitem](inv $from_inv, inv $to_inv, obj $obj, int $count) +// Move an object from one inventory to another (first free slot) and cert it [command,inv_moveitem_cert](inv $from_inv, inv $to_inv, obj $obj, int $count) [command,.inv_moveitem_cert](inv $from_inv, inv $to_inv, obj $obj, int $count) +// Move an object from one inventory to another (first free slot) and uncert it [command,inv_moveitem_uncert](inv $from_inv, inv $to_inv, obj $obj, int $count) [command,.inv_moveitem_uncert](inv $from_inv, inv $to_inv, obj $obj, int $count) +// Set the $slot in $inv to $object x $count [command,inv_setslot](inv $inv, int $slot, namedobj $obj, int $count) [command,.inv_setslot](inv $inv, int $slot, namedobj $obj, int $count) +// Return the total number of $obj in $inv [command,inv_total](inv $inv, obj $obj)(int) [command,.inv_total](inv $inv, obj $obj)(int) +// Return the total number of objects that match $category in $inv [command,inv_totalcat](inv $inv, category $category)(int) [command,.inv_totalcat](inv $inv, category $category)(int) +// Populate an inventory on a component [command,inv_transmit](inv $inv, component $component) [command,.inv_transmit](inv $inv, component $component) +// Transmit an inventory from one player to another player [command,invother_transmit](player_uid $player, inv $inv, component $component) [command,.invother_transmit](player_uid $player, inv $inv, component $component) +// Stop transmitting an inventory on a component [command,inv_stoptransmit](component $component) [command,.inv_stoptransmit](component $component) +// Drop an object from an inventory, visible to the other active player [command,both_dropslot](inv $inv, coord $coord, int $slot, int $duration) [command,.both_dropslot](inv $inv, coord $coord, int $slot, int $duration) +// Drop all items from an inventory [command,inv_dropall](inv $inv, coord $coord, int $duration) [command,.inv_dropall](inv $inv, coord $coord, int $duration) // todo: compiler update @@ -439,43 +722,71 @@ // [command,.inv_totalparam_stack]/*(inv $inv, param $param)(int)*/ // Enum ops (4400-4499) +// Get a value from an enum - type $input, type $output, enum $enum, any $key [command,enum] // (type $input, type $output, enum $enum, dynamic $key)(dynamic) +// Get how many values are in an enum [command,enum_getoutputcount](enum $enum)(int) // String ops (4500-4599) [command,append_num](string $text, int $num)(string) +// Concatenate two strings [command,append](string $text1, string $text2)(string) [command,append_signnum](string $text, int $num)(string) +// Convert a string to lowercase [command,lowercase](string $text)(string) +// Convert a number to a string [command,tostring](int $int0)(string) [command,compare](string $text1, string $text2)(int) +// Append a char to a string [command,append_char](string $text, char $char)(string) +// Get the length of a string [command,string_length](string $text)(int) +// Take a substring of $text [command,substring](string $text, int $start, int $end)(string) [command,string_indexof_char](string $text, char $char)(int) [command,string_indexof_string](string $text1, string $text2)(int) // Number ops (4600-4699) +// Add two numbers together [command,add](int $n1, int $n2)(int) +// Subtract two numbers [command,sub](int $n1, int $n2)(int) +// Multiply two numbers [command,multiply](int $n1, int $n2)(int) +// Divide two numbers [command,divide](int $n1, int $n2)(int) +// Get a random number - within the range of 0 to $num - 1 [command,random](int $num)(int) +// Get a random-inclusive number - within the range of 0 to $num [command,randominc](int $num)(int) +// Linearly interpolate between two points [command,interpolate](int $y0, int $y1, int $x0, int $x1, int $x)(int) +// Add a percentage of $num to $num [command,addpercent](int $num, int $percent)(int) +// Set a bit of a number [command,setbit](int $value, int $bit)(int) +// Return true if a bit is set [command,testbit](int $value, int $bit)(boolean) +// Get the remainder of $n1 / $n2 [command,modulo](int $n1, int $n2)(int) +// Raise $n1 to the power of $n2 [command,pow](int $n1, int $n2)(int) [command,invpow](int $n1, int $n2)(int) +// Bitwise AND of $n1 and $n2 [command,and](int $n1, int $n2)(int) +// Bitwise OR of $n1 and $n2 [command,or](int $n1, int $n2)(int) +// Return whichever number is greater [command,max](int $a, int $b)(int) +// Return whichever number is lesser [command,min](int $a, int $b)(int) +// ($int0 * $int2) / $int1 [command,scale](int $int0, int $int1, int $int2)(int) +// Count the number of set bits [command,bitcount](int $num)(int) +// Flip a specific bit of a number [command,togglebit](int $num, int $bit)(int) +// Clear a specific bit of a number [command,clearbit](int $num, int $bit)(int) [command,setbit_range](int $num, int $start_bit, int $end_bit)(int) [command,clearbit_range](int $num, int $start_bit, int $end_bit)(int) @@ -500,20 +811,38 @@ [command,db_listall](dbtable $dbtable0)() // Debug ops (10000-11000) +// Raise a script error on the server [command,error](string $text) +// Return true if the world is in a production environment [command,map_production]()(boolean) +// Server debug stats [command,map_lastclock]()(int) +// Server debug stats [command,map_lastworld]()(int) +// Server debug stats [command,map_lastclientin]()(int) +// Server debug stats [command,map_lastnpc]()(int) +// Server debug stats [command,map_lastplayer]()(int) +// Server debug stats [command,map_lastlogin]()(int) +// Server debug stats [command,map_lastlogout]()(int) +// Server debug stats [command,map_lastzone]()(int) +// Server debug stats [command,map_lastclientout]()(int) +// Server debug stats [command,map_lastcleanup]()(int) +// Server debug stats [command,map_lastbandwidthin]()(int) +// Server debug stats [command,map_lastbandwidthout]()(int) +// Start tracking time +[command,timespent] +// Get the time spent since the timespent command was ran. This can be ^micros or ^millis +[command,gettimespent](int $unit)(int) // [command,inv_setvar](inv $inv, int $slot, obj $obj, int $value) // [command,inv_getvar](inv $inv, int $slot, obj $obj)(int) diff --git a/data/src/scripts/general/configs/quest.constant b/data/src/scripts/general/configs/quest.constant index 58322fd4b5..4de41f1a25 100644 --- a/data/src/scripts/general/configs/quest.constant +++ b/data/src/scripts/general/configs/quest.constant @@ -88,4 +88,5 @@ ^grandtree_questpoints = 5 ^chompybird_questpoints = 2 ^upass_questpoints = 5 -^zombiequeen_questpoints = 2 \ No newline at end of file +^zombiequeen_questpoints = 2 +^crest_questpoints = 1 \ No newline at end of file diff --git a/data/src/scripts/general/configs/xplamp.obj b/data/src/scripts/general/configs/xplamp.obj index 98e36b66f3..f81477b938 100644 --- a/data/src/scripts/general/configs/xplamp.obj +++ b/data/src/scripts/general/configs/xplamp.obj @@ -9,3 +9,4 @@ model=model_3348_obj 2dxan=28 weight=100g iop1=Rub +tradeable=no diff --git a/data/src/scripts/general/scripts/book.rs2 b/data/src/scripts/general/scripts/book.rs2 index 522e755c70..2c66005839 100644 --- a/data/src/scripts/general/scripts/book.rs2 +++ b/data/src/scripts/general/scripts/book.rs2 @@ -12,6 +12,7 @@ switch_obj (%open_book) { case history_of_iban : @book_flip_page(^book_direction_backward, 0, 2, ibanhistory); case ibans_shadow : @book_flip_page(^book_direction_backward, 0, 1, ibanshadow); case ibans_dove : @book_flip_page(^book_direction_backward, 0, 2, ibanconscience); + case book_on_chemicals : @book_flip_page(^book_direction_backward, 0, 1, book_on_chemicals); } p_delay(0); @@ -29,6 +30,7 @@ switch_obj (%open_book) { case history_of_iban : @book_flip_page(^book_direction_forward, 0, 2, ibanhistory); case ibans_shadow : @book_flip_page(^book_direction_forward, 0, 1, ibanshadow); case ibans_dove : @book_flip_page(^book_direction_forward, 0, 2, ibanconscience); + case book_on_chemicals : @book_flip_page(^book_direction_forward, 0, 1, book_on_chemicals); } p_delay(0); diff --git a/data/src/scripts/general/scripts/invs.rs2 b/data/src/scripts/general/scripts/invs.rs2 index ec1fd06748..1f180945c4 100644 --- a/data/src/scripts/general/scripts/invs.rs2 +++ b/data/src/scripts/general/scripts/invs.rs2 @@ -22,4 +22,10 @@ while ($i < enum_getoutputcount($slots)) { } $i = add($i, 1); } -return(true); \ No newline at end of file +return(true); + +[proc,del_all_if_exists](inv $inv, namedobj $obj) +def_int $total = inv_total($inv, $obj); +if ($total > 0) { + inv_del($inv, $obj, $total); +} \ No newline at end of file diff --git a/data/src/scripts/general/scripts/quests.rs2 b/data/src/scripts/general/scripts/quests.rs2 index d6f0405005..c71feb5923 100644 --- a/data/src/scripts/general/scripts/quests.rs2 +++ b/data/src/scripts/general/scripts/quests.rs2 @@ -228,6 +228,10 @@ if (%zombiequeen_progress >= ^zombiequeen_complete) { $questpoints = add($questpoints, ^zombiequeen_questpoints); } +if (%crest_progress = ^crest_complete) { + $questpoints = add($questpoints, ^crest_questpoints); +} + %questpoints = $questpoints; ~send_quest_progress_colour(questlist:runemysteries, %runemysteries_progress, ^runemysteries_complete); @@ -268,6 +272,7 @@ if(%phoenixgang_progress > 0 & %blackarmgang_progress ! ^blackarmgang_complete) ~send_quest_progress_colour(questlist:grail, %grail_progress, ^grail_complete); ~send_quest_progress_colour(questlist:ball, %ball_progress, ^ball_complete); ~send_quest_progress_colour(questlist:murder, %murder_progress, ^murder_complete); +~send_quest_progress_colour(questlist:itexam, ~itexam_progress, ^itexam_complete); ~send_quest_progress_colour(questlist:hazeelcult, %hazeelcult_progress, ^hazeelcult_complete); ~send_quest_progress_colour(questlist:hero, %hero_progress, ^hero_complete); ~send_quest_progress_colour(questlist:itgronigen, %itgronigen_progress, ^itgronigen_complete); @@ -285,6 +290,7 @@ if (testbit(%upass_map_mechanisms, ^upass_started_bit) = true & %upass_progress ~send_quest_progress_colour(questlist:upass, %upass_progress, ^upass_complete); } ~send_quest_progress_colour(questlist:zombiequeen, %zombiequeen_progress, ^zombiequeen_complete); +~send_quest_progress_colour(questlist:crest, %crest_progress, ^crest_complete); if_settab(questlist, ^tab_quest_journal); if (%drunkmonk_progress >= ^drunkmonk_spoken_to_omad) { diff --git a/data/src/scripts/general_use/configs/flowers.obj b/data/src/scripts/general_use/configs/flowers.obj index 5a06a3d435..41a39152fe 100644 --- a/data/src/scripts/general_use/configs/flowers.obj +++ b/data/src/scripts/general_use/configs/flowers.obj @@ -14,7 +14,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -44,7 +43,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -74,7 +72,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -104,7 +101,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -134,7 +130,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -164,7 +159,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -194,7 +188,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -224,7 +217,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 @@ -254,7 +246,6 @@ category=flowers 2dzoom=840 2dyan=816 2dxan=612 -tradeable=yes param=stabattack,-100 param=slashattack,-100 param=crushattack,-50 diff --git a/data/src/scripts/general_use/configs/holiday.obj b/data/src/scripts/general_use/configs/holiday.obj index b941e9098b..3a0f863d0d 100644 --- a/data/src/scripts/general_use/configs/holiday.obj +++ b/data/src/scripts/general_use/configs/holiday.obj @@ -10,6 +10,7 @@ model=model_3065_obj 2dzoom=710 2dyan=1832 2dxan=60 +tradeable=no [bunny_ears] name=Bunny ears @@ -25,6 +26,7 @@ womanwear=model_3353_obj_wear,0 manhead=model_33_obj_wear womanhead=model_91_obj_wear weight=8oz +tradeable=no [red_partyhat] name=Red partyhat @@ -42,7 +44,6 @@ womanwear=model_363_obj_wear,0 manhead=model_29_obj_wear womanhead=model_87_obj_wear weight=2oz -tradeable=yes [yellow_partyhat] name=Yellow partyhat @@ -62,7 +63,6 @@ womanwear=model_363_obj_wear,0 manhead=model_29_obj_wear womanhead=model_87_obj_wear weight=2oz -tradeable=yes [blue_partyhat] name=Blue partyhat @@ -82,7 +82,6 @@ womanwear=model_363_obj_wear,0 manhead=model_29_obj_wear womanhead=model_87_obj_wear weight=2oz -tradeable=yes [green_partyhat] name=Green partyhat @@ -102,7 +101,6 @@ womanwear=model_363_obj_wear,0 manhead=model_29_obj_wear womanhead=model_87_obj_wear weight=2oz -tradeable=yes [purple_partyhat] name=Purple partyhat @@ -122,7 +120,6 @@ womanwear=model_363_obj_wear,0 manhead=model_29_obj_wear womanhead=model_87_obj_wear weight=2oz -tradeable=yes [white_partyhat] name=White partyhat @@ -142,7 +139,6 @@ womanwear=model_363_obj_wear,0 manhead=model_29_obj_wear womanhead=model_87_obj_wear weight=2oz -tradeable=yes [santa_hat] name=Santa hat @@ -160,7 +156,6 @@ manhead=model_69_obj_wear womanhead=model_127_obj_wear iop2=Wear weight=4oz -tradeable=yes [green_halloween_mask] name=Halloween mask @@ -181,7 +176,6 @@ womanhead=model_3187_obj_wear 2dzoom=730 2dxan=516 iop2=Wear -tradeable=yes [blue_halloween_mask] name=Halloween mask @@ -202,7 +196,6 @@ womanhead=model_3187_obj_wear 2dzoom=730 2dxan=516 iop2=Wear -tradeable=yes [red_halloween_mask] name=Halloween mask @@ -221,4 +214,3 @@ womanhead=model_3187_obj_wear 2dzoom=730 2dxan=516 iop2=Wear -tradeable=yes diff --git a/data/src/scripts/general_use/configs/newcomer_map.obj b/data/src/scripts/general_use/configs/newcomer_map.obj index 3f5a5a0804..055d3b3cae 100644 --- a/data/src/scripts/general_use/configs/newcomer_map.obj +++ b/data/src/scripts/general_use/configs/newcomer_map.obj @@ -10,4 +10,3 @@ model=model_2774_obj iop1=Read weight=18oz cost=1 -tradeable=yes diff --git a/data/src/scripts/general_use/configs/water_sources.obj b/data/src/scripts/general_use/configs/water_sources.obj index df4e6c2d2c..7f32d8d870 100644 --- a/data/src/scripts/general_use/configs/water_sources.obj +++ b/data/src/scripts/general_use/configs/water_sources.obj @@ -11,7 +11,6 @@ recol1d=15855 2dxan=260 cost=1 weight=1lb -tradeable=yes param=changesto,jug_of_water [jug_of_water] @@ -27,7 +26,6 @@ recol1d=15871 2dxan=260 cost=1 weight=1kg -tradeable=yes param=is_water_source,^true param=changesto,jug_empty @@ -43,7 +41,6 @@ womanwear=model_543_obj_wear,6 2dyan=1688 2dxan=204 weight=1kg -tradeable=yes param=changesto,bucket_water [bucket_water] @@ -56,7 +53,6 @@ model=model_2504_obj 2dyan=1688 2dxan=204 weight=3kg -tradeable=yes param=is_water_source,^true param=changesto,bucket_empty @@ -69,7 +65,6 @@ model=model_2367_obj 2dyan=1856 2dxan=204 weight=2lb -tradeable=yes param=is_water_source,^true param=changesto,bowl_empty @@ -82,5 +77,4 @@ model=model_2807_obj 2dyan=1856 2dxan=204 weight=1lb -tradeable=yes param=changesto,bowl_water \ No newline at end of file diff --git a/data/src/scripts/general_use/scripts/bookcases.rs2 b/data/src/scripts/general_use/scripts/bookcases.rs2 index e16dc1f7b6..8213ea451c 100644 --- a/data/src/scripts/general_use/scripts/bookcases.rs2 +++ b/data/src/scripts/general_use/scripts/bookcases.rs2 @@ -2,6 +2,13 @@ // https://youtu.be/YT_tGdVMjGs?t=259 // todo: confirm for other bookcase loc's p_arrivedelay; +//mes(~coord_tostring(loc_coord)); +switch_coord (loc_coord) { + case 0_52_52_38_4, 0_52_52_36_4, 0_52_52_36_6, 0_52_52_38_7, 0_52_52_36_7, 0_52_52_39_8 : @exam_centre_bookcase; // exam centre bookcases + case default : @search_bookcase; +} + +[label,search_bookcase] mes("You search the bookcase..."); p_delay(1); def_int $rand = random(4); @@ -13,4 +20,4 @@ if($rand = 0) { mes("You don't find anything that you'd ever want to read."); } else { mes("It's full of books, but none of them look very interesting."); -} +} \ No newline at end of file diff --git a/data/src/scripts/general_use/scripts/cupboards.rs2 b/data/src/scripts/general_use/scripts/cupboards.rs2 index 22c646cb9c..6d8c8eb5c4 100644 --- a/data/src/scripts/general_use/scripts/cupboards.rs2 +++ b/data/src/scripts/general_use/scripts/cupboards.rs2 @@ -33,6 +33,7 @@ switch_coord (loc_coord) { ~mesbox("There is just a load of junk in here."); case 1_48_51_24_4 : @cupboard_take_garlic; // draynor morgans house level 1 case 0_40_52_14_6 : @elena_search_cupboard; // alrenas house for plague city + case 0_52_52_26_4 : @exam_centre_cupboard_jar; // exam centre specimen jar cupboard case 0_42_53_10_12, 0_40_49_29_46, 0_41_53_36_34 : mes("You search the cupboard but find nothing."); // sorcerers tower, fight arena, ranging guild case default : mes("The cupboard is empty."); } diff --git a/data/src/scripts/general_use/scripts/spade.rs2 b/data/src/scripts/general_use/scripts/spade.rs2 index 387abe8587..e8b417f310 100644 --- a/data/src/scripts/general_use/scripts/spade.rs2 +++ b/data/src/scripts/general_use/scripts/spade.rs2 @@ -17,6 +17,11 @@ p_arrivedelay; p_stopaction; anim(human_dig, 0); +// itexam - digsite area, workmen get angry if you dig around the whole mapsquare +if (inzone(0_52_53_0_0, 0_52_53_63_63, coord) = true) { + @digsite_workman_intervene; +} + // Treasure Trails if(map_members = true & ~trail_hasclue_inv = true) { def_obj $clue = ~trail_getclue_inv; diff --git a/data/src/scripts/interface_chat/scripts/chat.rs2 b/data/src/scripts/interface_chat/scripts/chat.rs2 index 24327764b1..c3406e60d4 100644 --- a/data/src/scripts/interface_chat/scripts/chat.rs2 +++ b/data/src/scripts/interface_chat/scripts/chat.rs2 @@ -563,12 +563,12 @@ if ($lines = 0) { } if_openchat($interface); -[proc,doubleobjbox](obj $obj_1, obj $obj_2, string $string) +[proc,doubleobjbox](obj $obj_1, obj $obj_2, string $string, int $scale) split_init($string, 350, 4, q8); def_int $page = 0; def_int $pagetotal = split_pagecount; while ($page < $pagetotal) { - ~doubleobjbox_page($obj_1, $obj_2, 150, $page); + ~doubleobjbox_page($obj_1, $obj_2, $scale, $page); p_pausebutton; $page = calc($page + 1); } diff --git a/data/src/scripts/levelup/scripts/levelup_unlocks_cooking.rs2 b/data/src/scripts/levelup/scripts/levelup_unlocks_cooking.rs2 index a581b7aaf6..d63ec186e1 100644 --- a/data/src/scripts/levelup/scripts/levelup_unlocks_cooking.rs2 +++ b/data/src/scripts/levelup/scripts/levelup_unlocks_cooking.rs2 @@ -4,34 +4,34 @@ switch_int(stat_base(cooking)) { case 5 : ~objbox(herring,"You can now cook @dbl@Herring@bla@.", 250, 0, 0); case 6 : ~objbox(fruit_blast,"Members can now make @dbl@Fruit Blasts@bla@.", 250, 0, ^objbox_height); case 8 : ~objbox(pineapple_punch,"Members can now make @dbl@Pineapple Punches@bla@.", 250, 0, ^objbox_height); - case 10 : ~doubleobjbox(mackerel,redberry_pie,"You can now cook @dbl@Redberry Pies@bla@. Members can cook|@dbl@Mackerel@bla@ and also make @dbl@Toad Crunchies"); + case 10 : ~doubleobjbox(mackerel,redberry_pie,"You can now cook @dbl@Redberry Pies@bla@. Members can cook|@dbl@Mackerel@bla@ and also make @dbl@Toad Crunchies", 150); case 12 : ~objbox(spicy_crunchies,"Members can now cook @dbl@Spicy Crunchies@bla@.", 250, 0, 0); case 14 : ~objbox(worm_crunchies,"Members can now make @dbl@Worm Crunchies@bla@.", 250, 0, 0); case 15 : ~objbox(trout,"You can now cook @dbl@Trout@bla@.", 250, 0, 0); case 16 : ~objbox(choc_chip_crunchies,"Members can now make @dbl@Chocolate Chip Crunchies@bla@.", 250, 0, 0); - case 18 : ~doubleobjbox(cod,wizard_blizzard,"Members can now cook @dbl@Cod@bla@ and make @dbl@Wizard|@dbl@Blizzards@bla@."); - case 20 : ~doubleobjbox(pike,meat_pie,"You can now cook @dbl@Meat Pies@bla@ and @dbl@Pike@bla@. Members can|also make @dbl@Short Green Guys@bla@."); - case 25 : ~doubleobjbox(salmon,stew,"You can now cook @dbl@Stews@bla@ and @dbl@Salmon@bla@. Members may| also create @dbl@Fruit Battas@bla@."); + case 18 : ~doubleobjbox(cod,wizard_blizzard,"Members can now cook @dbl@Cod@bla@ and make @dbl@Wizard|@dbl@Blizzards@bla@.", 150); + case 20 : ~doubleobjbox(pike,meat_pie,"You can now cook @dbl@Meat Pies@bla@ and @dbl@Pike@bla@. Members can|also make @dbl@Short Green Guys@bla@.", 150); + case 25 : ~doubleobjbox(salmon,stew,"You can now cook @dbl@Stews@bla@ and @dbl@Salmon@bla@. Members may| also create @dbl@Fruit Battas@bla@.", 150); case 26 : ~objbox(toad_batta,"Members can now cook @dbl@Toad Battas@bla@.", 250, 0, divide(^objbox_height, 2)); case 27 : ~objbox(worm_batta,"Members can now cook @dbl@Worm Battas@bla@.", 250, 0, divide(^objbox_height, 2)); case 28 : ~objbox(vegetable_batta,"Members can now cook @dbl@Vegetable Battas@bla@.", 250, 0, divide(^objbox_height, 2)); case 29 : ~objbox(cheese_tom_batta,"Members can now make @dbl@Cheese and Tomato Battas@bla@.", 250, 0, divide(^objbox_height, 2)); // guessed - case 30 : ~doubleobjbox(tuna,apple_pie,"You can now cook @dbl@Apple Pies@bla@ and @dbl@Tuna@bla@. Members can now cook @dbl@Worm Holes@bla@."); + case 30 : ~doubleobjbox(tuna,apple_pie,"You can now cook @dbl@Apple Pies@bla@ and @dbl@Tuna@bla@. Members can now cook @dbl@Worm Holes@bla@.", 150); case 32 : ~objbox(chefshat,"You are now qualified to enter the prestigious @dbl@Chefs'|@dbl@Guild@bla@. Members may also create @dbl@Drunk Dragons@bla@.", 250, 0, 0); case 33 : ~objbox(chocolate_saturday,"Members can now make @dbl@Chocolate Saturdays@bla@.", 250, 0, ^objbox_height); - case 35 : ~doubleobjbox(plain_pizza,jug_wine,"You can now cook @dbl@Pizzas@bla@ and @dbl@Wine@bla@. Members can|now cook @dbl@Vegetable Balls@bla@."); + case 35 : ~doubleobjbox(plain_pizza,jug_wine,"You can now cook @dbl@Pizzas@bla@ and @dbl@Wine@bla@. Members can|now cook @dbl@Vegetable Balls@bla@.", 150); case 37 : ~objbox(blurberry_special,"Members can now create @dbl@Blurberry Specials@bla@.", 250, 0, ^objbox_height); - case 40 : ~doubleobjbox(lobster,cake,"You can now cook @dbl@Cakes@bla@ and @dbl@Lobsters@bla@. Members may|create @dbl@Tangled Toad Legs@bla@."); + case 40 : ~doubleobjbox(lobster,cake,"You can now cook @dbl@Cakes@bla@ and @dbl@Lobsters@bla@. Members may|create @dbl@Tangled Toad Legs@bla@.", 150); case 42 : ~objbox(chocolate_bomb,"Members can now cook @dbl@Chocolate Bombs@bla@.", 250, 0, divide(^objbox_height, 2)); case 43 : ~objbox(bass,"Members can now cook @dbl@Bass@bla@.", 250, 0, 0); - case 45 : ~doubleobjbox(swordfish,meat_pizza,"You can now cook @dbl@Meat Pizzas@bla@ and @dbl@Swordfish@bla@."); + case 45 : ~doubleobjbox(swordfish,meat_pizza,"You can now cook @dbl@Meat Pizzas@bla@ and @dbl@Swordfish@bla@.", 150); case 48 : ~objbox(cheese,"Members can now churn @dbl@Cheese@bla@.", 250, 0, divide(^objbox_height, 2)); case 50 : ~objbox(chocolate_cake,"You can now cook @dbl@Chocolate Cakes@bla@.", 250, 0, divide(^objbox_height, 2)); case 53 : ~objbox(lava_eel,"Members can now cook @dbl@Lava Eel@bla@.", 250, 0, 0); case 55 : ~objbox(anchovy_pizza,"You can now cook @dbl@Anchovy Pizza@bla@.", 250, 0, 0); case 58 : ~objbox(pitta_bread,"Members can now cook @dbl@Pitta Bread@bla@.", 250, 0, 0); case 60 : ~objbox(curry,"Members can now cook @dbl@Curry@bla@.", 250, 0, divide(^objbox_height, 2)); - case 65 : ~doubleobjbox(pineapple_pizza,wine_of_zamorak,"Members can now cook @dbl@Pineapple Pizzas@bla@ and make @dbl@Wine|@dbl@of Zamorak@bla@"); + case 65 : ~doubleobjbox(pineapple_pizza,wine_of_zamorak,"Members can now cook @dbl@Pineapple Pizzas@bla@ and make @dbl@Wine|@dbl@of Zamorak@bla@", 150); case 80 : ~objbox(raw_shark,"Members can now cook @dbl@Shark@bla@.", 250, 0, 0); case 82 : ~objbox(raw_sea_turtle,"Members can now cook @dbl@Sea Turtle@bla@.", 250, 0, 0); case 91 : ~objbox(raw_manta_ray,"Members can now cook @dbl@Manta Rays@bla@.", 250, 0, 0); diff --git a/data/src/scripts/levelup/scripts/levelup_unlocks_crafting.rs2 b/data/src/scripts/levelup/scripts/levelup_unlocks_crafting.rs2 index de5dcdbc10..97bc6ddff1 100644 --- a/data/src/scripts/levelup/scripts/levelup_unlocks_crafting.rs2 +++ b/data/src/scripts/levelup/scripts/levelup_unlocks_crafting.rs2 @@ -3,40 +3,40 @@ switch_int(stat_base(crafting)) { case 5 : ~objbox(gold_ring,"You can now craft @dbl@Gold Rings@bla@.", 250, 0, 0); case 6 : ~objbox(gold_necklace,"You can now craft @dbl@Gold Necklaces@bla@.", 250, 0, 0); - case 7 : ~doubleobjbox(leather_boots,piedish,"You can now craft @dbl@Boots@bla@ and @dbl@Pie Dishes@bla@."); - case 8 : ~doubleobjbox(bowl_empty,gold_amulet,"You can now craft @dbl@Bowls@bla@ and @dbl@Gold Amulets@bla@."); + case 7 : ~doubleobjbox(leather_boots,piedish,"You can now craft @dbl@Boots@bla@ and @dbl@Pie Dishes@bla@.", 150); + case 8 : ~doubleobjbox(bowl_empty,gold_amulet,"You can now craft @dbl@Bowls@bla@ and @dbl@Gold Amulets@bla@.", 150); case 9 : ~objbox(leather_cowl,"You can now craft @dbl@Leather Cowls@bla@.", 250, 0, ^objbox_height); case 10 : ~objbox(bow_string,"Members can now craft @dbl@Bow Strings@bla@.", 250, 0, 0); case 11 : ~objbox(leather_vambraces,"You can now craft @dbl@Leather Vambraces@bla@.", 250, 0, 0); case 13 : ~objbox(jade,"Members can now cut @dbl@Jade@bla@.", 250, 0, divide(^objbox_height, 2)); case 14 : ~objbox(leather_body,"You can now make @dbl@Leather Armour@bla@.", 250, 0, 0); - case 16 : ~doubleobjbox(blessedstar,red_topaz,"You can now craft @dbl@Holy Symbols of Saradomin@bla@ and members can cut @dbl@Red Topaz@bla@."); + case 16 : ~doubleobjbox(blessedstar,red_topaz,"You can now craft @dbl@Holy Symbols of Saradomin@bla@ and members can cut @dbl@Red Topaz@bla@.", 150); case 18 : ~objbox(leather_chaps,"You can now craft @dbl@Leather Chaps@bla@.", 250, 0, 0); - case 20 : ~doubleobjbox(sapphire,sapphire_ring,"You can now cut @dbl@Sapphires@bla@ and craft @dbl@Sapphire Rings@bla@."); + case 20 : ~doubleobjbox(sapphire,sapphire_ring,"You can now cut @dbl@Sapphires@bla@ and craft @dbl@Sapphire Rings@bla@.", 150); case 22 : ~objbox(sapphire_necklace,"You can now craft @dbl@Sapphire Necklaces@bla@.", 250, 0, 0); case 24 : ~objbox(sapphire_amulet,"You can now craft @dbl@Sapphire Amulets@bla@.", 250, 0, 0); - case 27 : ~doubleobjbox(emerald,emerald_ring,"You can now cut @dbl@Emeralds@bla@ and craft @dbl@Emerald Rings@bla@."); + case 27 : ~doubleobjbox(emerald,emerald_ring,"You can now cut @dbl@Emeralds@bla@ and craft @dbl@Emerald Rings@bla@.", 150); case 28 : ~objbox(hardleather_body,"You can now craft @dbl@Hard Leather Armour@bla@.", 250, 0, 0); case 29 : ~objbox(emerald_necklace,"You can now craft @dbl@Emerald Necklaces@bla@.", 250, 0, 0); case 31 : ~objbox(emerald_amulet,"You can now craft @dbl@Emerald Amulets@bla@.", 250, 0, 0); case 33 : ~objbox(vial_empty,"Members can now craft @dbl@Vials@bla@.", 250, 0, ^objbox_height); - case 34 : ~doubleobjbox(ruby,ruby_ring,"You can now cut @dbl@Rubies@bla@ and craft @dbl@Ruby Rings@bla@."); + case 34 : ~doubleobjbox(ruby,ruby_ring,"You can now cut @dbl@Rubies@bla@ and craft @dbl@Ruby Rings@bla@.", 150); case 38 : ~objbox(coif,"Members can now craft @dbl@Leather Coifs@bla@.", 250, 0, ^objbox_height); - case 40 : ~doubleobjbox(chisel,hammer,"You can now enter the @dbl@Crafting Guild@bla@|and make @dbl@Ruby Necklaces@bla@."); + case 40 : ~doubleobjbox(chisel,hammer,"You can now enter the @dbl@Crafting Guild@bla@|and make @dbl@Ruby Necklaces@bla@.", 150); case 41 : ~objbox(studded_body,"Members can now craft @dbl@Studded Leather Body Armour@bla@.", 250, 0, 0); - case 43 : ~doubleobjbox(diamond,diamond_ring,"You can now cut @dbl@Diamonds@bla@ and craft @dbl@Diamond Rings@bla@."); + case 43 : ~doubleobjbox(diamond,diamond_ring,"You can now cut @dbl@Diamonds@bla@ and craft @dbl@Diamond Rings@bla@.", 150); case 44 : ~objbox(studded_chaps,"Members can now craft @dbl@Studded Leather Chaps@bla@.", 250, 0, 0); case 46 : ~objbox(stafforb,"Members can now craft @dbl@Orbs@bla@.", 250, 0, 0); case 50 : ~objbox(ruby_amulet,"You can now craft @dbl@Ruby Amulets@bla@.", 250, 0, 0); case 54 : ~objbox(water_battlestaff,"Members can now craft @dbl@Water Battlestaves@bla@.", 250, 0, 0); - case 55 : ~doubleobjbox(dragonstone,dragonstone_ring,"Members can now cut @dbl@Dragonstones|@bla@and craft @dbl@Dragonstone Rings."); // https://imgur.com/m9Jq0hU + case 55 : ~doubleobjbox(dragonstone,dragonstone_ring,"Members can now cut @dbl@Dragonstones|@bla@and craft @dbl@Dragonstone Rings.", 200); // imgur.com/m9Jq0hU case 56 : ~objbox(diamond_necklace,"You can now craft @dbl@Diamond Necklaces@bla@.", 250, 0, 0); case 57 : ~objbox(dragonhide_vamb,"Members can now craft @dbl@Green Dragonhide Vambraces@bla@.", 250, 0, 0); case 58 : ~objbox(earth_battlestaff,"Members can now craft @dbl@Earth Battlestaves@bla@.", 250, 0, 0); case 60 : ~objbox(dragonhide_chaps,"Members can now craft @dbl@Green Dragonhide Chaps@bla@.", 250, 0, 0); case 62 : ~objbox(fire_battlestaff,"Members can now craft @dbl@Fire Battlestaves@bla@.", 250, 0, 0); case 63 : ~objbox(dragonhide_body,"Members can now craft @dbl@Green Dragonhide Armour@bla@.", 250, 0, divide(^objbox_height, 2)); - case 66 : ~doubleobjbox(air_battlestaff,blue_dragonhide_vambraces,"Members can now craft @dbl@Air Battlestaves@bla@ and @dbl@Blue|@dbl@Dragonhide Vambraces@bla@."); + case 66 : ~doubleobjbox(air_battlestaff,blue_dragonhide_vambraces,"Members can now craft @dbl@Air Battlestaves@bla@ and @dbl@Blue|@dbl@Dragonhide Vambraces@bla@.", 150); case 68 : ~objbox(blue_dragonhide_chaps,"Members can now craft @dbl@Blue Dragonhide Chaps@bla@.", 250, 0, 0); case 70 : ~objbox(diamond_amulet,"You can now craft @dbl@Diamond Amulets@bla@.", 250, 0, 0); case 71 : ~objbox(blue_dragonhide_body,"Members can now craft @dbl@Blue Dragonhide Armour@bla@.", 250, 0, divide(^objbox_height, 2)); diff --git a/data/src/scripts/levelup/scripts/levelup_unlocks_fishing.rs2 b/data/src/scripts/levelup/scripts/levelup_unlocks_fishing.rs2 index 8908d47e05..516b2d4cad 100644 --- a/data/src/scripts/levelup/scripts/levelup_unlocks_fishing.rs2 +++ b/data/src/scripts/levelup/scripts/levelup_unlocks_fishing.rs2 @@ -3,19 +3,19 @@ switch_int(stat_base(fishing)) { case 5 : ~objbox(raw_sardine,"You can now try fishing for @dbl@Sardines.", 250, 0, 0); case 10 : ~objbox(raw_herring,"You can now try fishing for @dbl@Herring.", 250, 0, 0); - case 15 : ~doubleobjbox(raw_anchovies,net,"You can now try to net @dbl@Anchovies."); - case 16 : ~doubleobjbox(raw_mackerel,casket,"You can now try fishing for @dbl@Mackerel@bla@,|@dbl@Oysters@bla@ and @bdl@Caskets@bla@ with a large net."); - case 20 : ~doubleobjbox(raw_trout,fly_fishing_rod,"You can now try fishing for @dbl@Trout."); - case 23 : ~doubleobjbox(raw_cod,net,"Members can now try fishing for @dbl@Cod with a large net."); - case 25 : ~doubleobjbox(raw_pike,fishing_rod,"You can now try fishing for @dbl@Pike."); - case 30 : ~doubleobjbox(raw_salmon,fly_fishing_rod,"You can now try fishing for @dbl@Salmon."); - case 35 : ~doubleobjbox(raw_tuna,harpoon,"You can now try harpooning @dbl@Tuna."); - case 40 : ~doubleobjbox(raw_lobster,lobster_pot,"You can now try to catch @dbl@Lobsters."); - case 46 : ~doubleobjbox(raw_bass,net_big,"Members can now try fishing for @dbl@Sea Bass with a large net."); - case 50 : ~doubleobjbox(raw_swordfish,harpoon,"You can now try harpooning @dbl@Swordfish."); - case 53 : ~doubleobjbox(raw_lava_eel,fishing_rod,"Members can now try catching @dbl@Lava Eels."); + case 15 : ~doubleobjbox(raw_anchovies,net,"You can now try to net @dbl@Anchovies.", 150); + case 16 : ~doubleobjbox(raw_mackerel,casket,"You can now try fishing for @dbl@Mackerel@bla@,|@dbl@Oysters@bla@ and @bdl@Caskets@bla@ with a large net.", 150); + case 20 : ~doubleobjbox(raw_trout,fly_fishing_rod,"You can now try fishing for @dbl@Trout.", 150); + case 23 : ~doubleobjbox(raw_cod,net,"Members can now try fishing for @dbl@Cod with a large net.", 150); + case 25 : ~doubleobjbox(raw_pike,fishing_rod,"You can now try fishing for @dbl@Pike.", 150); + case 30 : ~doubleobjbox(raw_salmon,fly_fishing_rod,"You can now try fishing for @dbl@Salmon.", 150); + case 35 : ~doubleobjbox(raw_tuna,harpoon,"You can now try harpooning @dbl@Tuna.", 150); + case 40 : ~doubleobjbox(raw_lobster,lobster_pot,"You can now try to catch @dbl@Lobsters.", 150); + case 46 : ~doubleobjbox(raw_bass,net_big,"Members can now try fishing for @dbl@Sea Bass with a large net.", 150); + case 50 : ~doubleobjbox(raw_swordfish,harpoon,"You can now try harpooning @dbl@Swordfish.", 150); + case 53 : ~doubleobjbox(raw_lava_eel,fishing_rod,"Members can now try catching @dbl@Lava Eels.", 150); case 68 : ~mesbox("Members are now qualified to enter the @dbl@Fishing Guild."); - case 76 : ~doubleobjbox(raw_shark,harpoon,"Members can now try harpooning @dbl@Sharks."); //imgur.com/SvV4b4p - case 79 : ~doubleobjbox(raw_sea_turtle,bucket_empty,"Members can now catch @dbl@Sea Turtles on the Trawler."); //imgur.com/T0raUc4 - case 81 : ~doubleobjbox(raw_manta_ray,bucket_empty,"Members can now catch @dbl@Manta Rays on the Trawler."); + case 76 : ~doubleobjbox(raw_shark,harpoon,"Members can now try harpooning @dbl@Sharks.", 150); //imgur.com/SvV4b4p + case 79 : ~doubleobjbox(raw_sea_turtle,bucket_empty,"Members can now catch @dbl@Sea Turtles on the Trawler.|", 200); //imgur.com/T0raUc4 + case 81 : ~doubleobjbox(raw_manta_ray,bucket_empty,"Members can now catch @dbl@Manta Rays on the Trawler.|", 200); //imgur.com/DVv0WDM } diff --git a/data/src/scripts/levelup/scripts/levelup_unlocks_mining.rs2 b/data/src/scripts/levelup/scripts/levelup_unlocks_mining.rs2 index a7ecb8e98c..0fd87c2a9a 100644 --- a/data/src/scripts/levelup/scripts/levelup_unlocks_mining.rs2 +++ b/data/src/scripts/levelup/scripts/levelup_unlocks_mining.rs2 @@ -7,7 +7,7 @@ switch_int(stat_base(mining)) { case 21 : ~objbox(mithril_pickaxe,"You can now mine with @dbl@Mithril Pickaxes.", 250, 0, 0); case 30 : ~objbox(coal,"You can now mine @dbl@Coal.", 250, 0, 0); case 31 : ~objbox(adamant_pickaxe,"You can now mine with @dbl@Adamant Pickaxes.", 250, 0, 0); - case 40 : ~doubleobjbox(gold_ore,red_topaz,"You can now mine @dbl@Gold@bla@. Members can mine @dbl@Gem|@dbl@rocks@bla@."); + case 40 : ~doubleobjbox(gold_ore,red_topaz,"You can now mine @dbl@Gold@bla@. Members can mine @dbl@Gem|@dbl@rocks@bla@.", 150); case 41 : ~objbox(rune_pickaxe,"You can now mine with @dbl@Rune Pickaxes.", 250, 0, 0); //imgur.com/UvfRKuk case 55 : ~objbox(mithril_ore,"You can now mine @dbl@Mithril.", 250, 0, 0); case 70 : ~objbox(adamantite_ore,"You can now mine @dbl@Adamantite.", 250, 0, 0); diff --git a/data/src/scripts/levelup/scripts/levelup_unlocks_ranged.rs2 b/data/src/scripts/levelup/scripts/levelup_unlocks_ranged.rs2 index fa8e64aa77..e21d9ad2a0 100644 --- a/data/src/scripts/levelup/scripts/levelup_unlocks_ranged.rs2 +++ b/data/src/scripts/levelup/scripts/levelup_unlocks_ranged.rs2 @@ -1,12 +1,12 @@ [label,levelup_ranged] //Ranged level up unlock messages switch_int(stat_base(ranged)) { - case 5 : ~doubleobjbox(oak_shortbow,steel_knife,"You can now wield @dbl@Oak Bows@bla@ and members can wield|@dbl@Steel Throwing Weapons@bla@."); + case 5 : ~doubleobjbox(oak_shortbow,steel_knife,"You can now wield @dbl@Oak Bows@bla@ and members can wield|@dbl@Steel Throwing Weapons@bla@.", 150); case 10 : ~objbox(black_knife,"Members can now wield @dbl@Black Throwing Weapons@bla@.", 250, 0, 0); - case 20 : ~doubleobjbox(willow_shortbow,mithril_knife,"You can now wield @dbl@Willow Bows@bla@ and wear @dbl@Studded|@dbl@Armour@bla@ and @dbl@Coifs@bla@, and members can now wield @dbl@Mithril|@dbl@Throwing Weapons@bla@."); - case 30 : ~doubleobjbox(maple_shortbow,adamant_knife,"You can now wield @dbl@Maple Bows@bla@ and members can wield|@dbl@Adamant Throwing Weapons@bla@."); - case 40 : ~doubleobjbox(yew_shortbow,dragonhide_body,"You can now wear @dbl@Green Dragonhide armour@bla@.|Members can wield @dbl@Yew Bows@bla@ & @dbl@Rune Throwing|@dbl@Weapons @bla@and wear @dbl@ranger boots@bla@ and the @dbl@Robin Hood hat@bla@."); - case 50 : ~doubleobjbox(magic_shortbow,blue_dragonhide_body,"Members can now wield @dbl@Magic Bows@bla@ and can wear|@dbl@Blue Dragonhide armour@bla@."); + case 20 : ~doubleobjbox(willow_shortbow,mithril_knife,"You can now wield @dbl@Willow Bows@bla@ and wear @dbl@Studded|@dbl@Armour@bla@ and @dbl@Coifs@bla@, and members can now wield @dbl@Mithril|@dbl@Throwing Weapons@bla@.", 150); + case 30 : ~doubleobjbox(maple_shortbow,adamant_knife,"You can now wield @dbl@Maple Bows@bla@ and members can wield|@dbl@Adamant Throwing Weapons@bla@.", 150); + case 40 : ~doubleobjbox(yew_shortbow,dragonhide_body,"You can now wear @dbl@Green Dragonhide armour@bla@.|Members can wield @dbl@Yew Bows@bla@ & @dbl@Rune Throwing|@dbl@Weapons @bla@and wear @dbl@ranger boots@bla@ and the @dbl@Robin Hood hat@bla@.", 150); + case 50 : ~doubleobjbox(magic_shortbow,blue_dragonhide_body,"Members can now wield @dbl@Magic Bows@bla@ and can wear|@dbl@Blue Dragonhide armour@bla@.", 150); case 60 : ~objbox(red_dragonhide_body,"Members can now wear @dbl@Red Dragonhide armour@bla@.", 250, 0, divide(^objbox_height, 2)); case 70 : ~objbox(black_dragonhide_body,"Members can now wear @dbl@Black Dragonhide armour@bla@.", 250, 0, 0); } diff --git a/data/src/scripts/levelup/scripts/levelup_unlocks_runecrafting.rs2 b/data/src/scripts/levelup/scripts/levelup_unlocks_runecrafting.rs2 index f1d1f61698..407a30d976 100644 --- a/data/src/scripts/levelup/scripts/levelup_unlocks_runecrafting.rs2 +++ b/data/src/scripts/levelup/scripts/levelup_unlocks_runecrafting.rs2 @@ -1,22 +1,22 @@ [label,levelup_runecraft] //Runecraft level up unlock messages switch_int(stat_base(runecraft)) { - case 2 : ~objbox(mindrune,"You can now craft @dbl@Mind Runes@bla@.", 250, 0, 0); - case 5 : ~objbox(waterrune,"You can now craft @dbl@Water Runes@bla@.", 250, 0, 0); - case 9 : ~objbox(earthrune,"You can now craft @dbl@Earth Runes@bla@.", 250, 0, 0); + case 2 : ~objbox(mindrune,"You can now craft @dbl@Mind Runes.", 250, 0, 0); + case 5 : ~objbox(waterrune,"You can now craft @dbl@Water Runes.", 250, 0, 0); + case 9 : ~objbox(earthrune,"You can now craft @dbl@Earth Runes.", 250, 0, 0); // case 11 : ~objbox(airrune,"You can now receive 2 @dbl@Air Runes@bla@.", 250, 0, 0); - case 14 : ~objbox(firerune,"You can now craft @dbl@Fire Runes@bla@.", 250, 0, 0); + case 14 : ~objbox(firerune,"You can now craft @dbl@Fire Runes.", 250, 0, 0); // case 19 : ~objbox(waterrune,"You can now receive 2 @dbl@Water Runes@bla@.", 250, 0, 0); - case 20 : ~objbox(bodyrune,"You can now craft @dbl@Body Runes@bla@.", 250, 0, 0); + case 20 : ~objbox(bodyrune,"You can now craft @dbl@Body Runes.", 250, 0, 0); // case 22 : ~objbox(airrune,"You can now receive 3 @dbl@Air Runes@bla@.", 250, 0, 0); // case 26 : ~objbox(earthrune,"You can now receive 2 @dbl@Earth Runes@bla@.", 250, 0, 0); - case 27 : ~objbox(cosmicrune,"You can now craft @dbl@Cosmic Runes@bla@.", 250, 0, 0); + case 27 : ~objbox(cosmicrune,"You can now craft @dbl@Cosmic Runes.", 250, 0, 0); // case 28 : ~objbox(mindrune,"You can now receive 3 @dbl@Mind Runes@bla@.", 250, 0, 0); // case 33 : ~objbox(airrune,"You can now receive 4 @dbl@Air Runes@bla@.", 250, 0, 0); - case 35 : ~objbox(chaosrune,"You can now craft @dbl@Chaos Runes@bla@.", 250, 0, 0); + case 35 : ~objbox(chaosrune,"You can now craft @dbl@Chaos Runes.", 250, 0, 0); // case 38 : ~objbox(waterrune,"You can now receive 3 @dbl@Water Runes@bla@.", 250, 0, 0); // case 42 : ~objbox(mindrune,"You can now receive 4 @dbl@Mind Runes@bla@.", 250, 0, 0); - case 44 : ~objbox(naturerune,"You can now craft @dbl@Nature Runes@bla@.", 250, 0, 0); // confirmed + case 44 : ~objbox(naturerune,"You can now craft @dbl@Nature Runes.", 250, 0, 0); // imgur.com/bz6j0wl // case 46 : ~objbox(bodyrune,"You can now receive 2 @dbl@Body Runes@bla@.", 250, 0, 0); // case 52 : ~objbox(earthrune,"You can now receive 3 @dbl@Earth Runes@bla@.", 250, 0, 0); // https://oldschool.runescape.wiki/w/Law_Altar diff --git a/data/src/scripts/levelup/scripts/levelup_unlocks_smithing.rs2 b/data/src/scripts/levelup/scripts/levelup_unlocks_smithing.rs2 index 95c9a758c0..16bf9e5af2 100644 --- a/data/src/scripts/levelup/scripts/levelup_unlocks_smithing.rs2 +++ b/data/src/scripts/levelup/scripts/levelup_unlocks_smithing.rs2 @@ -3,70 +3,70 @@ switch_int(stat_base(smithing)) { case 2 : ~objbox(bronze_mace,"You can now make @dbl@Bronze Maces@bla@.", 250, 0, divide(^objbox_height, 2)); case 3 : ~objbox(bronze_med_helm,"You can now make @dbl@Bronze Medium Helms@bla@.", 250, 0, ^objbox_height); - case 4 : ~doubleobjbox(bronze_sword,bronze_dart_tip,"You can now make @dbl@Bronze Short Swords@bla@ and members|can make @dbl@Bronze Dart Tips@bla@ and @dbl@Bronze Wire@bla@."); - case 5 : ~doubleobjbox(bronze_scimitar,bronze_spear,"You can now make @dbl@Bronze Scimitars@bla@ and members|can make @dbl@Bronze Arrow Heads@bla@ and @dbl@Bronze|@dbl@Spears@bla@."); + case 4 : ~doubleobjbox(bronze_sword,bronze_dart_tip,"You can now make @dbl@Bronze Short Swords@bla@ and members|can make @dbl@Bronze Dart Tips@bla@ and @dbl@Bronze Wire@bla@.", 150); + case 5 : ~doubleobjbox(bronze_scimitar,bronze_spear,"You can now make @dbl@Bronze Scimitars@bla@ and members|can make @dbl@Bronze Arrow Heads@bla@ and @dbl@Bronze|@dbl@Spears@bla@.", 150); case 6 : ~objbox(bronze_longsword,"You can now make @dbl@Bronze Long Swords@bla@.", 250, 0, 0); - case 7 : ~doubleobjbox(bronze_full_helm,bronze_knife,"You can now make @dbl@Bronze Full Helms@bla@ and members|can make @dbl@Bronze Throwing Knives@bla@."); + case 7 : ~doubleobjbox(bronze_full_helm,bronze_knife,"You can now make @dbl@Bronze Full Helms@bla@ and members|can make @dbl@Bronze Throwing Knives@bla@.", 150); case 8 : ~objbox(bronze_sq_shield,"You can now make @dbl@Bronze Square Shields@bla@.", 250, 0, 0); case 9 : ~objbox(bronze_warhammer,"You can now make @dbl@Bronze Warhammers@bla@.", 250, 0, 0); case 10 : ~objbox(bronze_battleaxe,"You can now make @dbl@Bronze Battle Axes@bla@.", 250, 0, 0); case 11 : ~objbox(bronze_chainbody,"You can now make @dbl@Bronze Chainmail Bodies@bla@.", 250, 0, 0); case 12 : ~objbox(bronze_kiteshield,"You can now make @dbl@Bronze Kite Shields@bla@.", 250, 0, 0); case 14 : ~objbox(bronze_2h_sword,"You can now make @dbl@Bronze Two Handed Swords@bla@.", 250, 0, 0); - case 15 : ~doubleobjbox(iron_ore,iron_dagger,"You can now smelt @dbl@Iron Ore@bla@ and make @dbl@Iron|@dbl@Daggers@bla@."); - case 16 : ~doubleobjbox(bronze_platelegs,iron_axe,"You can now make @dbl@Bronze Plate Legs@bla@, @dbl@Bronze|@dbl@plate skirts@bla@ and @dbl@Iron Axes@bla@."); + case 15 : ~doubleobjbox(iron_ore,iron_dagger,"You can now smelt @dbl@Iron Ore@bla@ and make @dbl@Iron|@dbl@Daggers@bla@.", 150); + case 16 : ~doubleobjbox(bronze_platelegs,iron_axe,"You can now make @dbl@Bronze Plate Legs@bla@, @dbl@Bronze|@dbl@plate skirts@bla@ and @dbl@Iron Axes@bla@.", 150); case 17 : ~objbox(iron_mace,"You can now make @dbl@Iron Maces@bla@.", 250, 0, divide(^objbox_height, 2)); - case 18 : ~doubleobjbox(bronze_platebody,iron_med_helm,"You can now make @dbl@Bronze Plate Bodies@bla@ and @dbl@Iron|@dbl@Medium Helms@bla@."); - case 19 : ~doubleobjbox(iron_sword,iron_dart_tip,"You can now make @dbl@Iron Short Swords@bla@ and members|can make @dbl@Iron Dart Tips@bla@."); - case 20 : ~doubleobjbox(silver_ore,iron_scimitar,"You can now smlet @dbl@Silver Ore@bla@ and make @dbl@Iron|@dbl@Scimitars@bla@ and members can make @dbl@Iron Arrow Heads@bla@|and @dbl@Iron|@dbl@Spears@bla@."); + case 18 : ~doubleobjbox(bronze_platebody,iron_med_helm,"You can now make @dbl@Bronze Plate Bodies@bla@ and @dbl@Iron|@dbl@Medium Helms@bla@.", 150); + case 19 : ~doubleobjbox(iron_sword,iron_dart_tip,"You can now make @dbl@Iron Short Swords@bla@ and members|can make @dbl@Iron Dart Tips@bla@.", 150); + case 20 : ~doubleobjbox(silver_ore,iron_scimitar,"You can now smlet @dbl@Silver Ore@bla@ and make @dbl@Iron|@dbl@Scimitars@bla@ and members can make @dbl@Iron Arrow Heads@bla@|and @dbl@Iron|@dbl@Spears@bla@.", 150); case 21 : ~objbox(iron_longsword,"You can now make @dbl@Iron Long Swords@bla@.", 250, 0, 0); - case 22 : ~doubleobjbox(iron_full_helm,iron_knife,"You can now make @dbl@Iron Full Helms@bla@ and members can|make @dbl@Iron Throwing Knives@bla@."); + case 22 : ~doubleobjbox(iron_full_helm,iron_knife,"You can now make @dbl@Iron Full Helms@bla@ and members can|make @dbl@Iron Throwing Knives@bla@.", 150); case 23 : ~objbox(iron_sq_shield,"You can now make @dbl@Iron Square Shields@bla@.", 250, 0, 0); case 24 : ~objbox(iron_warhammer,"You can now make @dbl@Iron Warhammers@bla@.", 250, 0, 0); case 25 : ~objbox(iron_battleaxe,"You can now make @dbl@Iron Battleaxes@bla@.", 250, 0, 0); case 26 : ~objbox(iron_chainbody,"You can now make @dbl@Iron Chainmail Bodies@bla@.", 250, 0, 0); case 27 : ~objbox(iron_kiteshield,"You can now make @dbl@Iron Kite Shields@bla@.", 250, 0, 0); case 29 : ~objbox(iron_2h_sword,"You can now make @dbl@Iron Two Handed Swords@bla@.", 250, 0, 0); - case 30 : ~doubleobjbox(iron_ore,steel_dagger,"You can now smelt @dbl@Steel@bla@ and make @dbl@Steel Daggers@bla@."); - case 31 : ~doubleobjbox(iron_platelegs,steel_axe,"You can now make @dbl@Iron Plate Legs@bla@, @dbl@Iron plate skirts|@bla@and @dbl@Steel Axes@bla@."); + case 30 : ~doubleobjbox(iron_ore,steel_dagger,"You can now smelt @dbl@Steel@bla@ and make @dbl@Steel Daggers@bla@.", 150); + case 31 : ~doubleobjbox(iron_platelegs,steel_axe,"You can now make @dbl@Iron Plate Legs@bla@, @dbl@Iron plate skirts|@bla@and @dbl@Steel Axes@bla@.", 150); case 32 : ~objbox(steel_mace,"You can now make @dbl@Steel Maces@bla@.", 250, 0, divide(^objbox_height, 2)); - case 33 : ~doubleobjbox(iron_platebody,steel_med_helm,"You can now make @dbl@Iron Plate Bodies@bla@ and @dbl@Steel|@dbl@Medium Helms@bla@."); - case 34 : ~doubleobjbox(steel_sword,steel_dart_tip,"You can now make @dbl@Steel Short Swords@bla@ and members|can make @dbl@Steel Dart Tips@bla@."); - case 35 : ~doubleobjbox(steel_scimitar,steel_spear,"You can now make @dbl@Steel Scimitars and members can|make @dbl@Steel Arrow Heads@bla@ and @dbl@Steel Spears@bla@."); - case 36 : ~doubleobjbox(steel_longsword,steel_studs,"You can now make @dbl@Steel Long Swords@bla@. Members can|make @dbl@Steel Studs@bla@."); - case 37 : ~doubleobjbox(steel_full_helm,steel_knife,"You can now make @dbl@Steel Full Helms@bla@ and members can|make @dbl@Steel Throwing Knives@bla@."); + case 33 : ~doubleobjbox(iron_platebody,steel_med_helm,"You can now make @dbl@Iron Plate Bodies@bla@ and @dbl@Steel|@dbl@Medium Helms@bla@.", 150); + case 34 : ~doubleobjbox(steel_sword,steel_dart_tip,"You can now make @dbl@Steel Short Swords@bla@ and members|can make @dbl@Steel Dart Tips@bla@.", 150); + case 35 : ~doubleobjbox(steel_scimitar,steel_spear,"You can now make @dbl@Steel Scimitars and members can|make @dbl@Steel Arrow Heads@bla@ and @dbl@Steel Spears@bla@.", 150); + case 36 : ~doubleobjbox(steel_longsword,steel_studs,"You can now make @dbl@Steel Long Swords@bla@. Members can|make @dbl@Steel Studs@bla@.", 150); + case 37 : ~doubleobjbox(steel_full_helm,steel_knife,"You can now make @dbl@Steel Full Helms@bla@ and members can|make @dbl@Steel Throwing Knives@bla@.", 150); case 38 : ~objbox(steel_sq_shield,"You can now make @dbl@Steel Square Shields@bla@.", 250, 0, 0); case 39 : ~objbox(steel_warhammer,"You can now make @dbl@Steel Warhammers@bla@.", 250, 0, 0); - case 40 : ~doubleobjbox(gold_ore,steel_battleaxe,"You can now smelt @dbl@Gold Ore@bla@ and make @dbl@Steel|@dbl@Battleaxes@bla@."); + case 40 : ~doubleobjbox(gold_ore,steel_battleaxe,"You can now smelt @dbl@Gold Ore@bla@ and make @dbl@Steel|@dbl@Battleaxes@bla@.", 150); case 41 : ~objbox(steel_chainbody,"You can now make @dbl@Steel Chainmail Bodies@bla@.", 250, 0, 0); case 42 : ~objbox(steel_kiteshield,"You can now make @dbl@Steel Kite Shields@bla@.", 250, 0, 0); case 44 : ~objbox(steel_2h_sword,"You can now make @dbl@Steel Two Handed Swords@bla@.", 250, 0, 0); - case 46 : ~doubleobjbox(steel_platelegs,steel_plateskirt,"You can now make @dbl@Steel Plate Legs@bla@ and @dbl@Steel plate skirts@bla@."); + case 46 : ~doubleobjbox(steel_platelegs,steel_plateskirt,"You can now make @dbl@Steel Plate Legs@bla@ and @dbl@Steel plate skirts@bla@.", 150); case 48 : ~objbox(steel_platebody,"You can now make @dbl@Steel Plate Bodies@bla@.", 250, 0, 0); - case 50 : ~objbox(mithril_dagger,"You can now make @dbl@Mithril Daggesr@bla@.", 250, 0, 0); + case 50 : ~objbox(mithril_dagger,"You can now make @dbl@Mithril Daggers@bla@.", 250, 0, 0); case 51 : ~objbox(mithril_axe,"You can now make @dbl@Mithril Axes@bla@.", 250, 0, 0); case 52 : ~objbox(mithril_mace,"You can now make @dbl@Mithril Maces@bla@.", 250, 0, divide(^objbox_height, 2)); case 53 : ~objbox(mithril_med_helm,"You can now make @dbl@Mithril Medium Helms@bla@.", 250, 0, divide(^objbox_height, 2)); - case 54 : ~doubleobjbox(mithril_sword,iron_dart_tip,"You can now make @dbl@Mithril Short Swords@bla@ and members|can make @dbl@Mithril Dart Tips@bla@."); - case 55 : ~doubleobjbox(mithril_scimitar,mithril_spear,"You can now make @dbl@Mithril Scimitars@bla@ and members|can make @dbl@Mithril Arrow Heads@bla@ and @dbl@Mithril|@dbl@Spears@bla@."); + case 54 : ~doubleobjbox(mithril_sword,iron_dart_tip,"You can now make @dbl@Mithril Short Swords@bla@ and members|can make @dbl@Mithril Dart Tips@bla@.", 150); + case 55 : ~doubleobjbox(mithril_scimitar,mithril_spear,"You can now make @dbl@Mithril Scimitars@bla@ and members|can make @dbl@Mithril Arrow Heads@bla@ and @dbl@Mithril|@dbl@Spears@bla@.", 150); case 56 : ~objbox(mithril_longsword,"You can now make @dbl@Mithril Long Swords@bla@.", 250, 0, 0); - case 57 : ~doubleobjbox(mithril_full_helm,mithril_knife,"You can now make @dbl@Mithril Full Helms@bla@ and members|can make @dbl@Mithril Throwing Knives@bla@."); + case 57 : ~doubleobjbox(mithril_full_helm,mithril_knife,"You can now make @dbl@Mithril Full Helms@bla@ and members|can make @dbl@Mithril Throwing Knives@bla@.", 150); case 58 : ~objbox(mithril_sq_shield,"You can now make @dbl@Mithril Square Shields@bla@.", 250, 0, 0); case 59 : ~objbox(mithril_warhammer,"You can now make @dbl@Mithril Warhammers@bla@.", 250, 0, 0); case 60 : ~objbox(mithril_battleaxe,"You can now make @dbl@Mithril Battleaxes@bla@.", 250, 0, 0); case 61 : ~objbox(mithril_chainbody,"You can now make @dbl@Mithril Chainmail Bodies@bla@.", 250, 0, 0); case 62 : ~objbox(mithril_kiteshield,"You can now make @dbl@Mithril Kite Shields@bla@.", 250, 0, 0); case 64 : ~objbox(mithril_2h_sword,"You can now make @dbl@Mithril Two Handed Swords@bla@.", 250, 0, 0); - case 66 : ~doubleobjbox(mithril_platelegs,mithril_plateskirt,"You can now make @dbl@Mithril Plate Legs@bla@ and @dbl@Mithril plate skirts@bla@."); + case 66 : ~doubleobjbox(mithril_platelegs,mithril_plateskirt,"You can now make @dbl@Mithril Plate Legs@bla@ and @dbl@Mithril plate skirts@bla@.", 150); case 68 : ~objbox(mithril_platebody,"You can now make @dbl@Mithril Plate Bodies@bla@.", 250, 0, 0); - case 70 : ~objbox(adamant_dagger,"You can now make @dbl@Adamant Daggesr@bla@.", 250, 0, 0); + case 70 : ~objbox(adamant_dagger,"You can now make @dbl@Adamant Daggers@bla@.", 250, 0, 0); case 71 : ~objbox(adamant_axe,"You can now make @dbl@Adamant Axes@bla@.", 250, 0, 0); case 72 : ~objbox(adamant_mace,"You can now make @dbl@Adamant Maces@bla@.", 250, 0, divide(^objbox_height, 2)); case 73 : ~objbox(adamant_med_helm,"You can now make @dbl@Adamant Medium Helms@bla@.", 250, 0, divide(^objbox_height, 2)); - case 74 : ~doubleobjbox(adamant_sword,adamant_dart_tip,"You can now make @dbl@Adamant Short Swords@bla@ and members|can make @dbl@Adamant Dart Tips@bla@."); - case 75 : ~doubleobjbox(adamant_scimitar,adamant_spear,"You can now make @dbl@Adamant Scimitars@bla@ and members|can make @dbl@Adamant Arrow Heads@bla@ and @dbl@Adamant|@dbl@Spears@bla@."); + case 74 : ~doubleobjbox(adamant_sword,adamant_dart_tip,"You can now make @dbl@Adamant Short Swords@bla@ and members|can make @dbl@Adamant Dart Tips@bla@.", 150); + case 75 : ~doubleobjbox(adamant_scimitar,adamant_spear,"You can now make @dbl@Adamant Scimitars@bla@ and members|can make @dbl@Adamant Arrow Heads@bla@ and @dbl@Adamant|@dbl@Spears@bla@.", 150); case 76 : ~objbox(adamant_longsword,"You can now make @dbl@Adamant Long Swords@bla@.", 250, 0, 0); - case 77 : ~doubleobjbox(adamant_full_helm,adamant_knife,"You can now make @dbl@Adamant Full Helms@bla@ and members|can make @dbl@Adamant Throwing Knives@bla@."); + case 77 : ~doubleobjbox(adamant_full_helm,adamant_knife,"You can now make @dbl@Adamant Full Helms@bla@ and members|can make @dbl@Adamant Throwing Knives@bla@.", 150); case 78 : ~objbox(adamant_sq_shield,"You can now make @dbl@Adamant Square Shields@bla@.", 250, 0, 0); case 79 : ~objbox(adamant_warhammer,"You can now make @dbl@Adamant Warhammers@bla@.", 250, 0, 0); case 80 : ~objbox(adamant_battleaxe,"You can now make @dbl@Adamant Battleaxes@bla@.", 250, 0, 0); @@ -74,17 +74,17 @@ switch_int(stat_base(smithing)) { case 82 : ~objbox(adamant_kiteshield,"You can now make @dbl@Adamant Kite Shields@bla@.", 250, 0, 0); case 84 : ~objbox(adamant_2h_sword,"You can now make @dbl@Adamant Two Handed Swords@bla@.", 250, 0, 0); case 85 : ~objbox(rune_dagger,"You can now make @dbl@Rune Daggers@bla@.", 250, 0, 0); - case 86 : ~doubleobjbox(adamant_platelegs,adamant_plateskirt,"You can now make @dbl@Adamant Plate Legs@bla@, @dbl@Adamant plate skirts@bla@ and @dbl@Rune Axes@bla@."); + case 86 : ~doubleobjbox(adamant_platelegs,adamant_plateskirt,"You can now make @dbl@Adamant Plate Legs@bla@, @dbl@Adamant plate skirts@bla@ and @dbl@Rune Axes@bla@.", 150); case 87 : ~objbox(rune_mace,"You can now make @dbl@Rune Maces@bla@.", 250, 0, divide(^objbox_height, 2)); - case 88 : ~doubleobjbox(adamant_platebody,rune_med_helm,"You can now make @dbl@Adamant Plate Bodies@bla@ and @dbl@Rune|@dbl@Medium Helms@bla@."); - case 89 : ~doubleobjbox(rune_sword,rune_dart_tip,"You can now make @dbl@Rune Short Swords@bla@ and members|can make @dbl@Rune Dart Tips@bla@."); - case 90 : ~doubleobjbox(rune_scimitar,rune_spear,"You can now make @dbl@Rune Scimitars@bla@ and members|can make @dbl@Rune Arrow Heads@bla@ and @dbl@Rune|@dbl@Spears@bla@."); + case 88 : ~doubleobjbox(adamant_platebody,rune_med_helm,"You can now make @dbl@Adamant Plate Bodies@bla@ and @dbl@Rune|@dbl@Medium Helms@bla@.", 150); + case 89 : ~doubleobjbox(rune_sword,rune_dart_tip,"You can now make @dbl@Rune Short Swords@bla@ and members|can make @dbl@Rune Dart Tips@bla@.", 150); + case 90 : ~doubleobjbox(rune_scimitar,rune_spear,"You can now make @dbl@Rune Scimitars@bla@ and members|can make @dbl@Rune Arrow Heads@bla@ and @dbl@Rune|@dbl@Spears@bla@.", 150); case 91 : ~objbox(rune_longsword,"You can now make @dbl@Rune Long Swords@bla@.", 250, 0, 0); - case 92 : ~doubleobjbox(rune_full_helm,rune_knife,"You can now make @dbl@Rune Full Helms@bla@ and members|can make @dbl@Rune Throwing Knives@bla@."); + case 92 : ~doubleobjbox(rune_full_helm,rune_knife,"You can now make @dbl@Rune Full Helms@bla@ and members|can make @dbl@Rune Throwing Knives@bla@.", 150); case 93 : ~objbox(rune_sq_shield,"You can now make @dbl@Rune Square Shields@bla@.", 250, 0, 0); case 94 : ~objbox(rune_warhammer,"You can now make @dbl@Rune Warhammers@bla@.", 250, 0, 0); case 95 : ~objbox(rune_battleaxe,"You can now make @dbl@Rune Battleaxes@bla@.", 250, 0, 0); case 96 : ~objbox(rune_chainbody,"You can now make @dbl@Rune Chainmail Bodies@bla@.", 250, 0, 0); case 97 : ~objbox(rune_kiteshield,"You can now make @dbl@Rune Kite Shields@bla@.", 250, 0, 0); - case 99 : ~doubleobjbox(rune_2h_sword,rune_platebody,"You can now make @dbl@Rune Two Handed Swords@bla@, @dbl@Plate|@dbl@Legs@dbl@, @dbl@plate skirts@bla@, and @dbl@Plate Bodies@bla@."); + case 99 : ~doubleobjbox(rune_2h_sword,rune_platebody,"You can now make @dbl@Rune Two Handed Swords@bla@, @dbl@Plate|@dbl@Legs@dbl@, @dbl@plate skirts@bla@, and @dbl@Plate Bodies@bla@.", 150); } diff --git a/data/src/scripts/login_logout/logout.rs2 b/data/src/scripts/login_logout/logout.rs2 index 61f184be7d..e25599d695 100644 --- a/data/src/scripts/login_logout/logout.rs2 +++ b/data/src/scripts/login_logout/logout.rs2 @@ -3,18 +3,7 @@ if (busy = true) { return(false); } -if (~in_duel_arena(coord) = true) { - mes("You can't log out during a duel."); //https://youtu.be/xLE8au7T50Q?t=227 - return(false); -} - -if (~inzone_coord_pair_table(gnomeball_zones, coord) = true) { - mes("You can't log out on a gnomeball pitch."); // osrs - return(false); -} - if (map_clock > 17 & add(%lastcombat, 17) > map_clock) { - mes("You can't logout until 10 seconds after the end of combat."); // todo: confirm this message for 2004 return(false); } @@ -33,11 +22,26 @@ if (%tradepartner ! null) { ~set_cannon_vars_logout; ~follower_logout; ~rashiliyia_door_logout; +~duel_arena_logout; return(true); [if_button,logout:try_logout] if_close; if (p_finduid(uid) = true) { + if (~in_duel_arena(coord) = true) { + mes("You can't log out during a duel."); //https://youtu.be/xLE8au7T50Q?t=227 + return; + } + + if (~inzone_coord_pair_table(gnomeball_zones, coord) = true) { + mes("You can't log out on a gnomeball pitch."); // osrs + return; + } + + if (map_clock > 17 & add(%lastcombat, 17) > map_clock) { + mes("You can't logout until 10 seconds after the end of combat."); // todo: confirm this message for 2004 + return; + } p_logout; } diff --git a/data/src/scripts/macro events/configs/antimacro.npc b/data/src/scripts/macro events/configs/antimacro.npc index c4fcb8d84a..e805c0bb0d 100644 --- a/data/src/scripts/macro events/configs/antimacro.npc +++ b/data/src/scripts/macro events/configs/antimacro.npc @@ -1020,7 +1020,7 @@ param=attack_sound,mace_crush param=damagetype,^crush_style param=combat_xp_multiplier,25 -[npc_437] +[brownimp] name=Brownie walkanim=imp_walk readyanim=imp_ready @@ -1036,6 +1036,12 @@ recol3d=8352 recol4s=2240 recol4d=8352 model1=model_2887_npc +param=attack_anim,imp_attack +param=defend_anim,imp_block +param=death_anim,imp_death +param=attack_sound,imp_attack +param=defend_sound,imp_hit +param=death_sound,imp_death // TODO [macro_event_dryad1] @@ -1069,7 +1075,9 @@ param=damagetype,^crush_style param=attack_anim,dryhad_attack param=defend_anim,dryhad_block param=death_anim,dryhad_death -// TODO sounds +param=attack_sound,null +param=defend_sound,null +param=death_sound,null param=combat_xp_multiplier,25 [macro_event_dryad2] @@ -1102,7 +1110,9 @@ param=damagetype,^crush_style param=attack_anim,dryhad_attack param=defend_anim,dryhad_block param=death_anim,dryhad_death -// TODO sounds +param=attack_sound,null +param=defend_sound,null +param=death_sound,null param=combat_xp_multiplier,25 [macro_event_dryad3] @@ -1135,7 +1145,9 @@ param=damagetype,^crush_style param=attack_anim,dryhad_attack param=defend_anim,dryhad_block param=death_anim,dryhad_death -// TODO sounds +param=attack_sound,null +param=defend_sound,null +param=death_sound,null param=combat_xp_multiplier,25 [macro_event_dryad4] @@ -1168,7 +1180,9 @@ param=damagetype,^crush_style param=attack_anim,dryhad_attack param=defend_anim,dryhad_block param=death_anim,dryhad_death -// TODO sounds +param=attack_sound,null +param=defend_sound,null +param=death_sound,null param=combat_xp_multiplier,25 [macro_event_dryad5] @@ -1201,7 +1215,9 @@ param=damagetype,^crush_style param=attack_anim,dryhad_attack param=defend_anim,dryhad_block param=death_anim,dryhad_death -// TODO sounds +param=attack_sound,null +param=defend_sound,null +param=death_sound,null param=combat_xp_multiplier,25 [macro_event_dryad6] @@ -1234,7 +1250,9 @@ param=damagetype,^crush_style param=attack_anim,dryhad_attack param=defend_anim,dryhad_block param=death_anim,dryhad_death -// TODO sounds +param=attack_sound,null +param=defend_sound,null +param=death_sound,null param=combat_xp_multiplier,25 [macro_event_ent_tree1] @@ -1441,6 +1459,7 @@ param=death_anim,dwarf_death param=attackrate,4 param=attack_sound,thrown // stats are completely guessed +// TODO sounds [macro_event_big_fish] name=Big fish @@ -1479,10 +1498,10 @@ defence=9 timer=10 param=damagetype,^crush_style param=attack_anim,troll_attack -param=attack_sound,null param=defend_anim,troll_block -param=defend_sound,null param=death_anim,troll_death +param=attack_sound,null +param=defend_sound,null param=death_sound,null param=combat_xp_multiplier,25 category=macro_event_river_troll @@ -1511,10 +1530,10 @@ defence=22 timer=10 param=damagetype,^crush_style param=attack_anim,troll_attack -param=attack_sound,null param=defend_anim,troll_block -param=defend_sound,null param=death_anim,troll_death +param=attack_sound,null +param=defend_sound,null param=death_sound,null param=combat_xp_multiplier,25 category=macro_event_river_troll @@ -1543,10 +1562,10 @@ defence=38 timer=10 param=damagetype,^crush_style param=attack_anim,troll_attack -param=attack_sound,null param=defend_anim,troll_block -param=defend_sound,null param=death_anim,troll_death +param=attack_sound,null +param=defend_sound,null param=death_sound,null param=combat_xp_multiplier,25 category=macro_event_river_troll @@ -1575,10 +1594,10 @@ defence=65 timer=10 param=damagetype,^crush_style param=attack_anim,troll_attack -param=attack_sound,null param=defend_anim,troll_block -param=defend_sound,null param=death_anim,troll_death +param=attack_sound,null +param=defend_sound,null param=death_sound,null param=combat_xp_multiplier,25 category=macro_event_river_troll @@ -1607,10 +1626,10 @@ defence=100 timer=10 param=damagetype,^crush_style param=attack_anim,troll_attack -param=attack_sound,null param=defend_anim,troll_block -param=defend_sound,null param=death_anim,troll_death +param=attack_sound,null +param=defend_sound,null param=death_sound,null param=combat_xp_multiplier,25 category=macro_event_river_troll @@ -1639,10 +1658,10 @@ defence=130 timer=10 param=damagetype,^crush_style param=attack_anim,troll_attack -param=attack_sound,null param=defend_anim,troll_block -param=defend_sound,null param=death_anim,troll_death +param=attack_sound,null +param=defend_sound,null param=death_sound,null param=combat_xp_multiplier,25 category=macro_event_river_troll diff --git a/data/src/scripts/macro events/configs/antimacro.obj b/data/src/scripts/macro events/configs/antimacro.obj index 7ef89ba674..0894e53883 100644 --- a/data/src/scripts/macro events/configs/antimacro.obj +++ b/data/src/scripts/macro events/configs/antimacro.obj @@ -8,7 +8,7 @@ members=yes 2dxan=116 weight=3oz iop1=Eat -tradeable=yes +param=cures_poison,yes [pickaxe_handle] name=Pickaxe handle @@ -25,7 +25,6 @@ category=category_15 manwear=model_558_obj_wear,0 womanwear=model_558_obj_wear,6 cost=1 -tradeable=yes param=attackrate,5 param=crushattack_anim,human_blunt_crush param=defend_anim,human_baxe_defend1 @@ -49,7 +48,6 @@ category=category_15 manwear=model_530_obj_wear,0 womanwear=model_530_obj_wear,6 cost=0 -tradeable=yes param=attackrate,5 param=stabattack_anim,human_blunt_crush param=crushattack_anim,human_blunt_stab @@ -76,7 +74,6 @@ category=category_15 manwear=model_530_obj_wear,0 womanwear=model_530_obj_wear,6 cost=0 -tradeable=yes param=attackrate,5 param=stabattack_anim,human_blunt_crush param=crushattack_anim,human_blunt_stab @@ -101,7 +98,6 @@ category=category_15 manwear=model_530_obj_wear,0 womanwear=model_530_obj_wear,6 cost=17 -tradeable=yes param=attackrate,5 param=stabattack_anim,human_blunt_crush param=crushattack_anim,human_blunt_stab @@ -128,7 +124,6 @@ category=category_15 manwear=model_530_obj_wear,0 womanwear=model_530_obj_wear,6 cost=43 -tradeable=yes param=attackrate,5 param=stabattack_anim,human_blunt_crush param=crushattack_anim,human_blunt_stab @@ -155,7 +150,6 @@ category=category_15 manwear=model_530_obj_wear,0 womanwear=model_530_obj_wear,6 cost=107 -tradeable=yes param=attackrate,5 param=stabattack_anim,human_blunt_crush param=crushattack_anim,human_blunt_stab @@ -182,7 +176,6 @@ category=category_15 manwear=model_530_obj_wear,0 womanwear=model_530_obj_wear,6 cost=1100 -tradeable=yes param=attackrate,5 param=stabattack_anim,human_blunt_crush param=crushattack_anim,human_blunt_stab @@ -206,7 +199,6 @@ recol1d=8354 weight=4lb category=category_15 cost=1 -tradeable=yes param=fixed,bronze_pickaxe [iron_pickaxe_head] @@ -223,7 +215,6 @@ recol1d=8456 weight=4lb category=category_15 cost=139 -tradeable=yes param=fixed,iron_pickaxe [steel_pickaxe_head] @@ -238,7 +229,6 @@ model=model_2732_obj weight=4lb category=category_15 cost=499 -tradeable=yes param=fixed,steel_pickaxe [mithril_pickaxe_head] @@ -255,7 +245,6 @@ recol1d=6346 weight=4lb category=category_15 cost=1299 -tradeable=yes param=fixed,mithril_pickaxe [adamant_pickaxe_head] @@ -272,7 +261,6 @@ recol1d=6438 weight=4lb category=category_15 cost=3199 -tradeable=yes param=fixed,adamant_pickaxe [rune_pickaxe_head] @@ -289,7 +277,6 @@ recol1d=6476 weight=4lb category=category_15 cost=31999 -tradeable=yes param=fixed,rune_pickaxe [axe_handle] @@ -309,7 +296,6 @@ category=category_15 manwear=model_557_obj_wear,0 womanwear=model_557_obj_wear,6 cost=1 -tradeable=yes param=attackrate,5 param=crushattack_anim,human_blunt_crush param=defend_anim,human_baxe_defend1 @@ -332,7 +318,6 @@ category=category_15 manwear=model_487_obj_wear,0 womanwear=model_487_obj_wear,6 cost=0 -tradeable=yes param=attackrate,5 param=slashattack_anim,human_baxe_slash param=crushattack_anim,human_blunt_crush @@ -358,7 +343,6 @@ category=category_15 manwear=model_487_obj_wear,0 womanwear=model_487_obj_wear,6 cost=0 -tradeable=yes param=attackrate,5 param=slashattack_anim,human_baxe_slash param=crushattack_anim,human_blunt_crush @@ -382,7 +366,6 @@ category=category_15 manwear=model_487_obj_wear,0 womanwear=model_487_obj_wear,6 cost=0 -tradeable=yes param=attackrate,5 param=slashattack_anim,human_baxe_slash param=crushattack_anim,human_blunt_crush @@ -408,7 +391,6 @@ category=category_15 manwear=model_487_obj_wear,0 womanwear=model_487_obj_wear,6 cost=10 -tradeable=yes param=attackrate,5 param=slashattack_anim,human_baxe_slash param=crushattack_anim,human_blunt_crush @@ -434,7 +416,6 @@ category=category_15 manwear=model_487_obj_wear,0 womanwear=model_487_obj_wear,6 cost=18 -tradeable=yes param=attackrate,5 param=slashattack_anim,human_baxe_slash param=crushattack_anim,human_blunt_crush @@ -460,7 +441,6 @@ category=category_15 manwear=model_487_obj_wear,0 womanwear=model_487_obj_wear,6 cost=43 -tradeable=yes param=attackrate,5 param=slashattack_anim,human_baxe_slash param=crushattack_anim,human_blunt_crush @@ -486,7 +466,6 @@ category=category_15 manwear=model_487_obj_wear,0 womanwear=model_487_obj_wear,6 cost=427 -tradeable=yes param=attackrate,5 param=slashattack_anim,human_baxe_slash param=crushattack_anim,human_blunt_crush @@ -509,7 +488,6 @@ recol1d=8354 weight=2lb category=category_15 cost=15 -tradeable=yes param=fixed,bronze_axe [iron_axe_head] @@ -525,7 +503,6 @@ recol1d=8456 weight=2lb category=category_15 cost=55 -tradeable=yes param=fixed,iron_axe [steel_axe_head] @@ -539,7 +516,6 @@ model=model_2444_obj weight=2lb category=category_15 cost=199 -tradeable=yes param=fixed,steel_axe [black_axe_head] @@ -555,7 +531,6 @@ recol1d=0 weight=2lb category=category_15 cost=383 -tradeable=yes param=fixed,black_axe [mithril_axe_head] @@ -571,7 +546,6 @@ recol1d=6346 weight=24oz category=category_15 cost=519 -tradeable=yes param=fixed,mithril_axe [adamant_axe_head] @@ -587,7 +561,6 @@ recol1d=6438 weight=40oz category=category_15 cost=1279 -tradeable=yes param=fixed,adamant_axe [rune_axe_head] @@ -603,5 +576,4 @@ recol1d=6476 weight=2lb category=category_15 cost=12799 -tradeable=yes param=fixed,rune_axe diff --git a/data/src/scripts/minigames/game_duelarena/configs/duelarena.npc b/data/src/scripts/minigames/game_duelarena/configs/duelarena.npc index 5001136edc..fcd0fdb845 100644 --- a/data/src/scripts/minigames/game_duelarena/configs/duelarena.npc +++ b/data/src/scripts/minigames/game_duelarena/configs/duelarena.npc @@ -250,6 +250,7 @@ head1=model_53_idk_head head2=model_85_idk_head head3=model_30_npc_head wanderrange=10 +hitpoints=7 [sabeil] name=Sabeil @@ -280,6 +281,7 @@ head1=model_53_idk_head head2=model_82_idk_head head3=model_30_npc_head wanderrange=10 +hitpoints=7 [jadid] name=Jadid @@ -310,6 +312,7 @@ head1=model_53_idk_head head2=model_82_idk_head head3=model_30_npc_head wanderrange=10 +hitpoints=7 [dalal] name=Dalal @@ -338,6 +341,7 @@ model7=model_358_idk head1=model_114_idk_head head2=model_88_npc_head wanderrange=10 +hitpoints=7 [afrah] name=Afrah @@ -366,6 +370,7 @@ model7=model_358_idk head1=model_114_idk_head head2=model_88_npc_head wanderrange=10 +hitpoints=7 [jeed] name=Jeed @@ -392,6 +397,8 @@ model5=model_428_idk model6=model_358_idk head1=model_113_idk_head wanderrange=10 +hitpoints=7 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc [hamid] name=Hamid diff --git a/data/src/scripts/minigames/game_duelarena/scripts/duel_arena.rs2 b/data/src/scripts/minigames/game_duelarena/scripts/duel_arena.rs2 index 10f5c0acd7..19b7040f9d 100644 --- a/data/src/scripts/minigames/game_duelarena/scripts/duel_arena.rs2 +++ b/data/src/scripts/minigames/game_duelarena/scripts/duel_arena.rs2 @@ -125,6 +125,9 @@ if (.finduid(%duelpartner) = true & ~enough_duel_space = true) { // https://yout cam_reset; .cam_reset; + ~inv_remove_leading_empty_slots(tempinv); + ~.inv_remove_leading_empty_slots(tempinv); + def_int $tempinvused = sub(inv_size(tempinv), inv_freespace(tempinv)); if ($tempinvused < 1) { if_settext(duel_confirm:com_91, "Absolutely nothing!"); @@ -399,6 +402,26 @@ if (~.inzone_coord_pair_table(duel_arena_fight_zones, $coord) = true | ~.inzone_ return(false); [proc,duel_arena_login] -if (~in_duel_arena(coord) = true) { - p_telejump(~duel_arena_finish_coord(coord)); +if (~in_duel_arena(coord) = false) { + return; } +~duel_reset_all; + +[proc,duel_arena_logout] +if (~in_duel_arena(coord) = false) { + return; +} +if (.finduid(%duelpartner) = true) { + .%duelstatus = 0; + .%duelpartner = null; + .if_close; + .queue(duel_arena_disconnect, 0); +} +%duelstatus = 0; +%duelpartner = null; +~duel_give_stake_back; + +[queue,duel_arena_disconnect] +~duel_give_stake_back; +~duel_reset_all; +~mesbox("Your opponent timed out, there was no winner!"); // https://youtu.be/LZzhIWbSKpY?t=127 diff --git a/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_finish.rs2 b/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_finish.rs2 index 91cc1eef11..3501149bd7 100644 --- a/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_finish.rs2 +++ b/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_finish.rs2 @@ -7,30 +7,7 @@ if (~in_duel_arena(coord) = false) { %duelpartner = null; return; } -// get arrows back -def_int $i = 0; -while ($i < inv_size(tempinv)) { - if (inv_getobj(tempinv, $i) ! null) { - inv_movefromslot(tempinv, inv, $i); - } - $i = calc($i + 1); -} - -buildappearance(worn); -~deactivate_prayers; -~follower_death; -p_telejump(~duel_arena_finish_coord(coord)); -anim(null, 0); -p_stopaction; - -~stat_reset_all; -healenergy(10000); -~combat_clearqueue; -clearqueue(player_death); -~clear_pk_skull; -~clear_poison; -~update_all(inv_getobj(worn, ^wearpos_rhand)); -hint_stop; +~duel_reset_all; if (.finduid(%duelpartner) = true & (%duelstatus = ^duelstatus_victory | %duelstatus = ^duelstatus_opponent_resigned)) { if (%duelstatus = ^duelstatus_opponent_resigned) { @@ -46,15 +23,8 @@ if (.finduid(%duelpartner) = true & (%duelstatus = ^duelstatus_victory | %duelst if_settext(duel_win:displayname, .displayname); if_settext(duel_win:combat_level, tostring(~.player_combat_level)); - $i = 0; - while ($i < inv_size(stakeinv)) { - if (inv_getobj(stakeinv, $i) ! null) { - //mes(": "); - inv_movefromslot(stakeinv, inv, $i); - } - $i = calc($i + 1); - } - inv_clear(stakeinv); + ~duel_give_stake_back; + // take stuff from other player's stakeinv .both_moveinv(stakeinv, stakeinv); // .%duelpartner = null; @@ -65,15 +35,44 @@ if (.finduid(%duelpartner) = true & (%duelstatus = ^duelstatus_victory | %duelst %duelstatus = 0; %duelpartner = null; -[if_close,duel_win] +[proc,duel_reset_all] +// get arrows back +def_int $i = 0; +while ($i < inv_size(tempinv)) { + if (inv_getobj(tempinv, $i) ! null) { + inv_movefromslot(tempinv, inv, $i); + } + $i = calc($i + 1); +} + +buildappearance(worn); +~deactivate_prayers; +~follower_death; +p_telejump(~duel_arena_finish_coord(coord)); +anim(null, 0); +p_stopaction; + +~stat_reset_all; +healenergy(10000); +~combat_clearqueue; +clearqueue(player_death); +~clear_pk_skull; +~clear_poison; +~update_all(inv_getobj(worn, ^wearpos_rhand)); +hint_stop; + +[proc,duel_give_stake_back] def_int $i = 0; while ($i < inv_size(stakeinv)) { if (inv_getobj(stakeinv, $i) ! null) { + //mes(": "); inv_movefromslot(stakeinv, inv, $i); } $i = calc($i + 1); } -inv_clear(stakeinv); + +[if_close,duel_win] +~duel_give_stake_back; inv_stoptransmit(duel_win:spoils); // https://youtu.be/QggKGBAl_X8?t=111 diff --git a/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_start.rs2 b/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_start.rs2 index 68f5641119..ddd0a217b2 100644 --- a/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_start.rs2 +++ b/data/src/scripts/minigames/game_duelarena/scripts/duel_arena_start.rs2 @@ -54,6 +54,7 @@ if (.finduid(%duelpartner) = true) { hint_player(.uid); softtimer(duel_arena_start_3, 3); // todo: confirm these timings + softtimer(duel_arena_time_limit, 6000); // 60 minute time limit https://runescape.wiki/w/Update:Assist_System midi_jingle(^duel_start_jingle, ^duel_start_jingle_millis); } @@ -152,6 +153,18 @@ if (~duel_arena_movement_check = true & ~in_duel_arena(coord) = true) { walktrigger(duel_arena_no_move); } +[softtimer,duel_arena_time_limit] +if (~in_duel_arena(coord) = false) { + clearsofttimer(duel_arena_time_limit); + return; +} +%duelstatus = 0; +%duelpartner = null; +if_close; +queue(duel_arena_time_limit, 0); + -[queue,duel_arena_full] -~mesbox("All arenas of this type are full! Select another type of arena, try|again in a few minutes or try a different server."); // https://youtu.be/TcrIr9O92sw?t=89 \ No newline at end of file +[queue,duel_arena_time_limit] +~duel_give_stake_back; +~duel_reset_all; +~mesbox("Time is up, there was no winner!"); // complete guess \ No newline at end of file diff --git a/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.hunt b/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.hunt index 403d3e7f87..543614947c 100644 --- a/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.hunt +++ b/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.hunt @@ -2,7 +2,7 @@ type=player check_vis=lineofsight check_afk=off -check_inv=worn,gnomeball,1,2147483647 +check_inv=worn,gnomeball,>0 check_notcombat=%lastcombat check_notcombat_self=%npc_lastcombat rate=1 diff --git a/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.obj b/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.obj index b63856597c..a9c0507bcc 100644 --- a/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.obj +++ b/data/src/scripts/minigames/game_gnomeball/configs/gnomeball.obj @@ -11,4 +11,3 @@ wearpos=righthand manwear=model_528_obj_wear,0 womanwear=model_528_obj_wear,6 members=yes -tradeable=yes diff --git a/data/src/scripts/minigames/game_ranging/configs/ranging.npc b/data/src/scripts/minigames/game_ranging/configs/ranging.npc index d7988c9ba2..93d00703fe 100644 --- a/data/src/scripts/minigames/game_ranging/configs/ranging.npc +++ b/data/src/scripts/minigames/game_ranging/configs/ranging.npc @@ -20,8 +20,8 @@ head1=model_63_idk_head head2=model_85_idk_head head3=model_32_obj_wear wanderrange=1 -maxrange=19 -// 10 +maxrange=20 +attackrange=10 respawnrate=50 hitpoints=50 attack=20 @@ -42,7 +42,8 @@ param=attack_anim,human_bow param=rangeattack_sound,arrowlaunch2 param=proj_launch,iron_arrow_launch param=proj_travel,iron_arrow_travel -// TODO +// Stats match osrs version but our version Vislvl is different. +// attack and maxrange is still wip. [ranging_guild_doorman] vislevel=hide @@ -65,6 +66,11 @@ head1=model_63_idk_head head2=model_85_idk_head head3=model_32_obj_wear wanderrange=1 +hitpoints=50 +attack=20 +strength=20 +defence=40 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_6057 [leatherworker] vislevel=hide @@ -288,17 +294,17 @@ model6=model_262_obj_wear model7=model_185_obj_wear model8=model_563_obj_wear wanderrange=1 +maxrange=11 +attackrange=11 hitpoints=30 attack=10 strength=10 defence=10 ranged=20 -maxrange=11 -attackrange=11 param=attackrate,6 param=rangebonus,16 -param=magicdefence,34 -param=rangedefence,66 +param=magicdefence,6 +param=rangedefence,12 param=damagetype,^ranged_style param=attack_anim,human_bow param=rangeattack_sound,arrowlaunch2 @@ -308,6 +314,7 @@ param=npc_ammo,iron_arrow huntmode=aggressive_ranged // https://oldschool.runescape.wiki/w/Tower_Archer huntrange=11 +// Stats match osrs version but our version Vislvl is different. [tower_archer_east] name=Tower Archer @@ -329,13 +336,13 @@ model6=model_262_obj_wear model7=model_185_obj_wear model8=model_563_obj_wear wanderrange=1 +maxrange=11 +attackrange=11 hitpoints=50 attack=10 strength=10 defence=10 ranged=40 -maxrange=11 -attackrange=11 param=attackrate,6 param=rangebonus,22 param=magicdefence,24 @@ -349,6 +356,7 @@ param=npc_ammo,steel_arrow huntmode=aggressive_ranged // https://oldschool.runescape.wiki/w/Tower_Archer huntrange=11 +// Stats match osrs version but our version Vislvl is different. [tower_archer_south] name=Tower Archer @@ -370,13 +378,13 @@ model6=model_277_obj_wear model7=model_185_obj_wear model8=model_563_obj_wear wanderrange=1 +maxrange=11 +attackrange=11 hitpoints=70 attack=10 strength=10 defence=10 ranged=60 -maxrange=11 -attackrange=11 param=attackrate,6 param=rangebonus,31 param=magicdefence,20 @@ -390,6 +398,7 @@ param=npc_ammo,mithril_arrow huntmode=aggressive_ranged // https://oldschool.runescape.wiki/w/Tower_Archer huntrange=11 +// Stats match osrs version but our version Vislvl is different. [tower_archer_west] name=Tower Archer @@ -411,13 +420,13 @@ model6=model_258_obj_wear model7=model_185_obj_wear model8=model_563_obj_wear wanderrange=1 +maxrange=11 +attackrange=11 hitpoints=90 attack=10 strength=10 defence=10 ranged=80 -maxrange=11 -attackrange=11 param=attackrate,6 param=rangebonus,49 param=magicdefence,34 @@ -431,6 +440,7 @@ param=npc_ammo,adamant_arrow huntmode=aggressive_ranged // https://oldschool.runescape.wiki/w/Tower_Archer huntrange=11 +// Stats match osrs version but our version Vislvl is different. [tribal_weapon_salesman] vislevel=hide diff --git a/data/src/scripts/minigames/game_ranging/scripts/guard.rs2 b/data/src/scripts/minigames/game_ranging/scripts/guard.rs2 index 0a6767da4e..cc94797376 100644 --- a/data/src/scripts/minigames/game_ranging/scripts/guard.rs2 +++ b/data/src/scripts/minigames/game_ranging/scripts/guard.rs2 @@ -1,3 +1,7 @@ [opnpc1,ranging_guild_guard] ~chatplayer("Hello there."); -~chatnpc("Greetings, traveller. Enjoy your time at the Ranging Guild."); \ No newline at end of file +~chatnpc("Greetings, traveller. Enjoy your time at the Ranging Guild."); + +[ai_queue1,ranging_guild_guard] ~npc_default_retaliate_ap; +[ai_opplayer2,ranging_guild_guard] npc_setmode(applayer2); +[ai_applayer2,ranging_guild_guard] ~npc_rangeattack; \ No newline at end of file diff --git a/data/src/scripts/minigames/game_trail/configs/trail.obj b/data/src/scripts/minigames/game_trail/configs/trail.obj index a144510084..7449faa952 100644 --- a/data/src/scripts/minigames/game_trail/configs/trail.obj +++ b/data/src/scripts/minigames/game_trail/configs/trail.obj @@ -16,6 +16,7 @@ recol3d=12481 2dzoom=990 2dyan=1716 2dxan=264 +tradeable=no [trail_watch] name=Watch @@ -28,6 +29,7 @@ model=model_2525_obj 2dzoom=690 2dyan=2032 2dxan=368 +tradeable=no [trail_sextant] name=Sextant @@ -42,6 +44,7 @@ model=model_2628_obj 2dyan=124 2dxan=488 iop1=Look through +tradeable=no [trail_casket_easy_map001] name=Casket @@ -56,6 +59,7 @@ cost=50 iop1=Open members=yes category=trail_casket_easy +tradeable=no [obj_2715] name=Casket @@ -70,6 +74,7 @@ cost=50 iop1=Open members=yes stackable=yes +tradeable=no [trail_casket_easy_map002] name=Casket @@ -84,6 +89,7 @@ cost=50 iop1=Open members=yes category=trail_casket_easy +tradeable=no [obj_2718] name=Casket @@ -98,6 +104,7 @@ cost=50 iop1=Open members=yes stackable=yes +tradeable=no [trail_casket_easy_map003] name=Casket @@ -112,6 +119,7 @@ cost=50 iop1=Open members=yes category=trail_casket_easy +tradeable=no [obj_2721] name=Casket @@ -126,6 +134,7 @@ cost=50 iop1=Open members=yes stackable=yes +tradeable=no [trail_casket_hard_sextant_exp001] name=Casket @@ -140,6 +149,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp002] name=Casket @@ -154,6 +164,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp003] name=Casket @@ -168,6 +179,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp007] name=Casket @@ -182,6 +194,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp008] name=Casket @@ -196,6 +209,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp009] name=Casket @@ -210,6 +224,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp010] name=Casket @@ -224,6 +239,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp011] name=Casket @@ -238,6 +254,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp012] name=Casket @@ -252,6 +269,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp013] name=Casket @@ -266,6 +284,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [obj_2749] name=Sliding piece @@ -592,6 +611,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_riddle_exp003] name=Casket @@ -606,6 +626,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_riddle_exp004] name=Casket @@ -620,6 +641,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_riddle_exp005] name=Casket @@ -634,6 +656,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_riddle_exp007] name=Casket @@ -648,6 +671,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_riddle_exp009] name=Casket @@ -662,6 +686,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_riddle_exp010] name=Casket @@ -676,6 +701,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_riddle_exp011] name=Casket @@ -690,6 +716,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_clue_hard_puzzle_exp014] name=Puzzle box @@ -703,6 +730,7 @@ model=model_3372_obj 2dxan=420 iop1=Open category=trail_puzzle +tradeable=no [trail_clue_hard_puzzle_exp016] name=Puzzle box @@ -716,6 +744,7 @@ model=model_3372_obj 2dxan=420 iop1=Open category=trail_puzzle +tradeable=no [trail_clue_hard_puzzle_exp017] name=Puzzle box @@ -729,6 +758,7 @@ model=model_3372_obj 2dxan=420 iop1=Open category=trail_puzzle +tradeable=no [trail_casket_medium_sextant_exp001] name=Casket @@ -743,6 +773,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_map001] name=Casket @@ -757,6 +788,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_map002] name=Casket @@ -771,6 +803,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp002] name=Casket @@ -785,6 +818,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp003] name=Casket @@ -799,6 +833,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp004] name=Casket @@ -813,6 +848,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp005] name=Casket @@ -827,6 +863,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp006] name=Casket @@ -841,6 +878,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp007] name=Casket @@ -855,6 +893,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp008] name=Casket @@ -869,6 +908,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp009] name=Casket @@ -883,6 +923,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp010] name=Casket @@ -897,6 +938,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp011] name=Casket @@ -911,6 +953,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp012] name=Casket @@ -925,6 +968,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_casket_medium_sextant_exp013] name=Casket @@ -939,6 +983,7 @@ cost=50 iop1=Open members=yes category=trail_casket_medium +tradeable=no [trail_clue_medium_key_exp001] name=Key @@ -951,6 +996,7 @@ model=model_2372_obj 2dzoom=700 2dyan=20 2dxan=328 +tradeable=no [trail_clue_medium_key_exp002] name=Key @@ -963,6 +1009,7 @@ model=model_2372_obj 2dzoom=700 2dyan=20 2dxan=328 +tradeable=no [trail_clue_medium_key_exp003] name=Key @@ -975,6 +1022,7 @@ model=model_2372_obj 2dzoom=700 2dyan=20 2dxan=328 +tradeable=no [trail_clue_medium_key_exp004] name=Key @@ -987,6 +1035,7 @@ model=model_2372_obj 2dzoom=700 2dyan=20 2dxan=328 +tradeable=no [trail_clue_medium_key_exp005] name=Key @@ -998,4 +1047,5 @@ model=model_2372_obj 2dyof=5 2dzoom=700 2dyan=20 -2dxan=328 \ No newline at end of file +2dxan=328 +tradeable=no diff --git a/data/src/scripts/minigames/game_trail/configs/trail_casket.obj b/data/src/scripts/minigames/game_trail/configs/trail_casket.obj index a476de07ad..ac61ce9157 100644 --- a/data/src/scripts/minigames/game_trail/configs/trail_casket.obj +++ b/data/src/scripts/minigames/game_trail/configs/trail_casket.obj @@ -11,6 +11,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp005] name=Casket @@ -25,6 +26,7 @@ cost=50 iop1=Open members=yes category=trail_casket_hard +tradeable=no [trail_casket_hard_sextant_exp006] name=Casket @@ -38,4 +40,5 @@ model=model_2450_obj cost=50 iop1=Open members=yes -category=trail_casket_hard \ No newline at end of file +category=trail_casket_hard +tradeable=no diff --git a/data/src/scripts/minigames/game_trail/configs/trail_easy.obj b/data/src/scripts/minigames/game_trail/configs/trail_easy.obj index 4cafbb1479..8fae1cc866 100644 --- a/data/src/scripts/minigames/game_trail/configs/trail_easy.obj +++ b/data/src/scripts/minigames/game_trail/configs/trail_easy.obj @@ -12,6 +12,7 @@ iop1=Read category=trail_clue_easy param=trail_coord,0_49_52_41_32 param=trail_casket,trail_casket_easy_map001 +tradeable=no [trail_clue_easy_map002] name=Clue scroll @@ -27,6 +28,7 @@ iop1=Read category=trail_clue_easy param=trail_coord,0_51_52_26_46 param=trail_casket,trail_casket_easy_map002 +tradeable=no [trail_clue_easy_map003] name=Clue scroll @@ -42,6 +44,7 @@ iop1=Read category=trail_clue_easy param=trail_coord,0_47_53_35_6 param=trail_casket,trail_casket_easy_map003 +tradeable=no [trail_clue_easy_simple_exp001] name=Clue scroll @@ -56,6 +59,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the chest in the|Duke of Lumbridge's bedroom. +tradeable=no [trail_clue_easy_simple_exp002] name=Clue scroll @@ -70,6 +74,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crate in the left-|hand tower of Lumbridge Castle. +tradeable=no [trail_clue_easy_simple_exp003] name=Clue scroll @@ -84,6 +89,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the boxes in the goblin|house near Lumbridge. +tradeable=no [trail_clue_easy_simple_exp004] name=Clue scroll @@ -98,6 +104,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the chests upstairs in|Al Kharid Palace. +tradeable=no [trail_clue_easy_simple_exp005] name=Clue scroll @@ -112,6 +119,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to Hans to|solve the clue. +tradeable=no [trail_clue_easy_simple_exp006] name=Clue scroll @@ -126,6 +134,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crates in the|most north-western house in Al Kharid. +tradeable=no [trail_clue_easy_simple_exp007] name=Clue scroll @@ -140,6 +149,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Talk to Zeke in Al Kharid. +tradeable=no [trail_clue_easy_simple_exp008] name=Clue scroll @@ -154,6 +164,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to the tanner|in Al Kharid. +tradeable=no [trail_clue_easy_simple_exp009] name=Clue scroll @@ -168,6 +179,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the boxes in|the house near the|south entrance to Varrock. +tradeable=no [trail_clue_easy_simple_exp010] name=Clue scroll @@ -182,6 +194,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to the bartender of the|Blue Moon Inn in Varrock. +tradeable=no [trail_clue_easy_simple_exp011] name=Clue scroll @@ -196,6 +209,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the drawers, upstairs|in the bank to|the East of Varrock. +tradeable=no [trail_clue_easy_simple_exp012] name=Clue scroll @@ -210,6 +224,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crates|in Horvik's armoury. +tradeable=no [trail_clue_easy_simple_exp013] name=Clue scroll @@ -224,6 +239,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the drawers in|one of Gertrude's bedrooms. +tradeable=no [trail_clue_easy_simple_exp014] name=Clue scroll @@ -238,6 +254,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the boxes in the|Barbarian Village helmet shop. +tradeable=no [trail_clue_easy_simple_exp015] name=Clue scroll @@ -252,6 +269,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the drawers upstairs|in Falador's shield shop. +tradeable=no [trail_clue_easy_simple_exp016] name=Clue scroll @@ -266,6 +284,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the boxes of|Falador's general store. +tradeable=no [trail_clue_easy_simple_exp017] name=Clue scroll @@ -280,6 +299,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Talk to the Squire in the|White Knights' castle in Falador. +tradeable=no [trail_clue_easy_simple_exp018] name=Clue scroll @@ -294,6 +314,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the drawers in|Falador's chain mail shop. +tradeable=no [trail_clue_easy_simple_exp019] name=Clue scroll @@ -308,6 +329,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crates in the|Port Sarim Fishing shop. +tradeable=no [trail_clue_easy_simple_exp020] name=Clue scroll @@ -322,6 +344,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Talk to the bartender of the|Rusty Anchor in Port Sarim. +tradeable=no [trail_clue_easy_simple_exp021] name=Clue scroll @@ -336,6 +359,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to Ned in|Draynor Village. +tradeable=no [trail_clue_easy_simple_exp022] name=Clue scroll @@ -350,6 +374,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to Doric, who|lives north of Falador. +tradeable=no [trail_clue_easy_simple_exp023] name=Clue scroll @@ -364,6 +389,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to Gaius in Taverley. +tradeable=no [trail_clue_easy_simple_exp024] name=Clue scroll @@ -378,6 +404,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the drawers in|Catherby's Archery shop. +tradeable=no [trail_clue_easy_simple_exp025] name=Clue scroll @@ -392,6 +419,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to Arhein in Catherby. +tradeable=no [trail_clue_easy_simple_exp026] name=Clue scroll @@ -406,6 +434,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Speak to Sir Kay|in Camelot Castle. +tradeable=no [trail_clue_easy_riddle_exp001] name=Clue scroll @@ -420,6 +449,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the chest in the left-|hand tower of Camelot Castle. +tradeable=no [trail_clue_easy_riddle_exp002] name=Clue scroll @@ -434,6 +464,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crates in the|guard house of the northern|gate of East Ardougne. +tradeable=no [trail_clue_easy_riddle_exp003] name=Clue scroll @@ -448,6 +479,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the boxes just|outside the Armour shop|in East Ardougne. +tradeable=no [trail_clue_easy_riddle_exp004] name=Clue scroll @@ -462,6 +494,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crates in East|Ardougne's general store. +tradeable=no [trail_clue_easy_riddle_exp005] name=Clue scroll @@ -476,6 +509,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crates in the shed|just north of East Ardougne. +tradeable=no [trail_clue_easy_riddle_exp006] name=Clue scroll @@ -490,6 +524,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the drawers|above Varrock's shops. +tradeable=no [trail_clue_easy_riddle_exp007] name=Clue scroll @@ -504,6 +539,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the crates near|a cart in Varrock. +tradeable=no [trail_clue_easy_riddle_exp008] name=Clue scroll @@ -518,6 +554,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Search the drawers found upstairs|in East Ardougne's houses. +tradeable=no [trail_clue_easy_riddle_exp009] name=Clue scroll @@ -532,6 +569,7 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,A crate found in the|tower of a church is|your next location. +tradeable=no [trail_clue_easy_riddle_exp010] name=Clue scroll @@ -546,3 +584,4 @@ model=model_3374_obj iop1=Read category=trail_clue_easy param=trail_desc,Look in the ground floor|crates of houses in Falador. +tradeable=no diff --git a/data/src/scripts/minigames/game_trail/configs/trail_hard.obj b/data/src/scripts/minigames/game_trail/configs/trail_hard.obj index 8dc33f350b..16498c8706 100644 --- a/data/src/scripts/minigames/game_trail/configs/trail_hard.obj +++ b/data/src/scripts/minigames/game_trail/configs/trail_hard.obj @@ -10,6 +10,7 @@ model=model_3374_obj 2dxan=360 iop1=Read category=trail_clue_hard +tradeable=no [trail_clue_hard_sextant_exp001] name=Clue scroll @@ -28,6 +29,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp001 param=trail_coord,0_47_60_50_44 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp002] name=Clue scroll @@ -46,6 +48,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp002 param=trail_coord,0_46_61_43_59 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp003] name=Clue scroll @@ -64,6 +67,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp003 param=trail_coord,0_49_61_23_55 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp004] name=Clue scroll @@ -82,6 +86,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp004 param=trail_coord,0_49_61_53_59 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp005] name=Clue scroll @@ -100,6 +105,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp005 param=trail_coord,0_51_60_26_49 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp006] name=Clue scroll @@ -118,6 +124,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp006 param=trail_coord,0_49_59_4_28 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp007] name=Clue scroll @@ -136,6 +143,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp007 param=trail_coord,0_46_59_2_43 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp008] name=Clue scroll @@ -154,6 +162,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp008 param=trail_coord,0_47_60_5_6 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp009] name=Clue scroll @@ -172,6 +181,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp009 param=trail_coord,0_47_61_31_56 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp010] name=Clue scroll @@ -190,6 +200,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp010 param=trail_coord,0_50_59_44_16 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp011] name=Clue scroll @@ -208,6 +219,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp011 param=trail_coord,0_49_57_32_29 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp012] name=Clue scroll @@ -226,6 +238,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp012 param=trail_coord,0_47_57_47_48 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_sextant_exp013] name=Clue scroll @@ -244,6 +257,7 @@ param=trail_sextant,yes param=trail_casket,trail_casket_hard_sextant_exp013 param=trail_coord,0_51_58_47_57 param=trail_guardian,zamorak_wizard +tradeable=no [trail_clue_hard_riddle_exp001] name=Clue scroll @@ -258,6 +272,7 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,You will need to under-cook|to solve this one. +tradeable=no [trail_clue_hard_riddle_exp002] name=Clue scroll @@ -274,6 +289,7 @@ category=trail_clue_hard param=trail_desc,Come to the evil ledge,|Yew know yew want to.|Try not to get stung. param=trail_casket,trail_casket_hard_riddle_exp002 param=trail_coord,0_48_54_17_12 +tradeable=no [trail_clue_hard_riddle_exp003] name=Clue scroll @@ -291,6 +307,7 @@ param=trail_desc,I am a token of the greatest love.|I have no beginning or end. param=trail_casket,trail_casket_hard_riddle_exp003 // TODO: confirm this isnt the adjacent tile instead (dist 1) param=trail_coord,0_49_153_55_33 +tradeable=no [trail_clue_hard_riddle_exp004] name=Clue scroll @@ -306,6 +323,7 @@ iop1=Read category=trail_clue_hard param=trail_desc,If a man carried my burden,|he would break his back.|I am not rich,|but leave silver in my track.|Speak to the keeper of my trail. param=trail_casket,trail_casket_hard_riddle_exp004 +tradeable=no [trail_clue_hard_riddle_exp005] name=Clue scroll @@ -322,6 +340,7 @@ category=trail_clue_hard param=trail_desc,Aggie I see. Lonely and southern I feel.|I am neither inside nor outside the house,|yet no home would be complete without|me. The treasure lies beneath me! param=trail_casket,trail_casket_hard_riddle_exp005 param=trail_coord,0_48_50_13_55 +tradeable=no [trail_clue_hard_riddle_exp006] name=Clue scroll @@ -336,6 +355,7 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,My home is grey, and made of stone;|A castle with a search for a meal.|Hidden in some drawers I am,|across from a wooden wheel. +tradeable=no [trail_clue_hard_riddle_exp007] name=Clue scroll @@ -352,6 +372,7 @@ category=trail_clue_hard param=trail_desc,The beasts to my east|snap claws and tails,|The rest to my west|can slide and eat fish.|The force to my north|will jump and they'll wail,|Come dig by my fire|and make a wish. param=trail_casket,trail_casket_hard_riddle_exp007 param=trail_coord,0_40_51_39_3 +tradeable=no [trail_clue_hard_riddle_exp008] name=Clue scroll @@ -366,6 +387,7 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,Four blades I have, yet draw no blood;|Still I turn my prey to powder.| If you are brave, come search my roof;| It is there my blades are louder. +tradeable=no [trail_clue_hard_riddle_exp009] name=Clue scroll @@ -382,6 +404,7 @@ category=trail_clue_hard param=trail_desc,I lie lonely and forgotten|in mid wilderness,|where the dead rise from their beds.|Feel free to quarrel and wind me up,|and dig while you shoot their heads. param=trail_casket,trail_casket_hard_riddle_exp009 param=trail_coord,0_49_57_38_15 +tradeable=no [trail_clue_hard_riddle_exp010] name=Clue scroll @@ -398,6 +421,7 @@ category=trail_clue_hard param=trail_desc,46 is my number.|My body is the colour of burnt orange|and crawls among those with eight.|Three mouths I have, yet I cannot|eat.|My blinking blue eye hides my grave. param=trail_casket,trail_casket_hard_riddle_exp010 param=trail_coord,0_49_60_34_45 +tradeable=no [trail_clue_hard_riddle_exp011] name=Clue scroll @@ -414,6 +438,7 @@ category=trail_clue_hard param=trail_desc,My giant guardians below|the market streets would|be fans of rock and roll,|if only they could grab hold of it.|Dig near my green bubbles! param=trail_coord,0_49_154_25_49 param=trail_casket,trail_casket_hard_riddle_exp011 +tradeable=no [trail_clue_hard_riddle_exp012] name=Clue scroll @@ -428,6 +453,7 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,Snah? I feel all confused,|like one of those cakes... +tradeable=no [trail_clue_hard_riddle_exp013] name=Clue scroll @@ -443,6 +469,7 @@ iop1=Read category=trail_clue_hard // https://youtu.be/LWfcA_C2bJY?si=YqJBRZYBy1JFXOO_&t=124 param=trail_desc,@or2@'A bag belt only?'|He asked his balding brothers. +tradeable=no [trail_clue_hard_riddle_exp014] name=Clue scroll @@ -457,6 +484,7 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,The keeper of Melzars...|Spare? Skeleton? Anar? +tradeable=no [trail_clue_hard_riddle_exp015] name=Clue scroll @@ -471,6 +499,7 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,Surprising? I bet he is... +tradeable=no [trail_clue_hard_riddle_exp016] name=Clue scroll @@ -485,6 +514,7 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,My name is like a tree,|yet it is spelt with a 'g'.|Come see the fur|which is right near me. +tradeable=no [trail_clue_hard_riddle_exp017] name=Clue scroll @@ -499,3 +529,4 @@ model=model_3374_obj iop1=Read category=trail_clue_hard param=trail_desc,Generally speaking,|his nose was very bent. +tradeable=no diff --git a/data/src/scripts/minigames/game_trail/configs/trail_medium.obj b/data/src/scripts/minigames/game_trail/configs/trail_medium.obj index 0e85a90964..5155646acd 100644 --- a/data/src/scripts/minigames/game_trail/configs/trail_medium.obj +++ b/data/src/scripts/minigames/game_trail/configs/trail_medium.obj @@ -12,6 +12,7 @@ iop1=Read category=trail_clue_medium param=trail_coord,0_48_50_21_27 param=trail_casket,trail_casket_medium_map001 +tradeable=no // this clue is unobtainable! [trail_clue_medium_map002] @@ -28,6 +29,7 @@ iop1=Read category=trail_clue_medium param=trail_coord,0_42_53_14_36 param=trail_casket,trail_casket_medium_map002 +tradeable=no [trail_clue_medium_sextant_exp001] name=Clue scroll @@ -45,6 +47,7 @@ param=trail_desc,02 degrees 48 minutes north|22 degrees 30 minutes east param=trail_sextant,yes param=trail_coord,0_49_50_24_51 param=trail_casket,trail_casket_medium_sextant_exp001 +tradeable=no [trail_clue_medium_sextant_exp002] name=Clue scroll @@ -62,6 +65,7 @@ param=trail_desc,01 degrees 35 minutes south|07 degrees 28 minutes east param=trail_sextant,yes param=trail_coord,0_41_48_55_38 param=trail_casket,trail_casket_medium_sextant_exp002 +tradeable=no [trail_clue_medium_sextant_exp003] name=Clue scroll @@ -79,6 +83,7 @@ param=trail_desc,01 degrees 26 minutes north|08 degrees 01 minutes east param=trail_sextant,yes param=trail_coord,0_42_50_9_7 param=trail_casket,trail_casket_medium_sextant_exp003 +tradeable=no [trail_clue_medium_sextant_exp004] name=Clue scroll @@ -96,6 +101,7 @@ param=trail_desc,06 degrees 31 minutes north|01 degrees 46 minutes west param=trail_sextant,yes param=trail_coord,0_37_52_15_42 param=trail_casket,trail_casket_medium_sextant_exp004 +tradeable=no [trail_clue_medium_sextant_exp005] name=Clue scroll @@ -113,6 +119,7 @@ param=trail_desc,00 degrees 05 minutes south|01 degrees 13 minutes east param=trail_sextant,yes param=trail_coord,0_38_49_47_22 param=trail_casket,trail_casket_medium_sextant_exp005 +tradeable=no [trail_clue_medium_sextant_exp006] name=Clue scroll @@ -130,6 +137,7 @@ param=trail_desc,09 degrees 33 minutes north|02 degrees 15 minutes east param=trail_sextant,yes param=trail_coord,0_39_54_16_11 param=trail_casket,trail_casket_medium_sextant_exp006 +tradeable=no [trail_clue_medium_sextant_exp007] name=Clue scroll @@ -147,6 +155,7 @@ param=trail_desc,02 degrees 50 minutes north|06 degrees 20 minutes east param=trail_sextant,yes param=trail_coord,0_41_50_19_52 param=trail_casket,trail_casket_medium_sextant_exp007 +tradeable=no [trail_clue_medium_sextant_exp008] name=Clue scroll @@ -164,6 +173,7 @@ param=trail_desc,04 degrees 13 minutes north|12 degrees 45 minutes east param=trail_sextant,yes param=trail_coord,0_44_51_32_32 param=trail_casket,trail_casket_medium_sextant_exp008 +tradeable=no [trail_clue_medium_sextant_exp009] name=Clue scroll @@ -181,6 +191,7 @@ param=trail_desc,04 degrees 00 minutes south|12 degrees 46 minutes east param=trail_sextant,yes param=trail_coord,0_44_47_33_25 param=trail_casket,trail_casket_medium_sextant_exp009 +tradeable=no [trail_clue_medium_sextant_exp010] name=Clue scroll @@ -198,6 +209,7 @@ param=trail_desc,00 degrees 31 minutes south|17 degrees 43 minutes east param=trail_sextant,yes param=trail_coord,0_46_49_63_8 param=trail_casket,trail_casket_medium_sextant_exp010 +tradeable=no [trail_clue_medium_sextant_exp011] name=Clue scroll @@ -215,6 +227,7 @@ param=trail_desc,07 degrees 33 minutes north|15 degrees 00 minutes east param=trail_sextant,yes param=trail_coord,0_45_53_40_11 param=trail_casket,trail_casket_medium_sextant_exp011 +tradeable=no [trail_clue_medium_sextant_exp012] name=Clue scroll @@ -232,6 +245,7 @@ param=trail_desc,00 degrees 30 minutes north|24 degrees 16 minutes east param=trail_sextant,yes param=trail_coord,0_50_49_17_41 param=trail_casket,trail_casket_medium_sextant_exp012 +tradeable=no [trail_clue_medium_sextant_exp013] name=Clue scroll @@ -249,6 +263,7 @@ param=trail_desc,05 degrees 43 minutes north|23 degrees 05 minutes east param=trail_sextant,yes param=trail_coord,0_49_52_43_16 param=trail_casket,trail_casket_medium_sextant_exp013 +tradeable=no [trail_clue_medium_riddle_exp001] name=Clue scroll @@ -263,6 +278,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,You'll need to look for|a town with a central|fountain. Look for a locked|chest in the town's chapel. +tradeable=no [trail_clue_medium_riddle_exp002] name=Clue scroll @@ -277,6 +293,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,In a town where the guards|are armed with maces, search|the upstairs rooms of the|Public House. +tradeable=no [trail_clue_medium_riddle_exp003] name=Clue scroll @@ -291,6 +308,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,In a town where thieves|steal from stalls, search for|some drawers in the upstairs|of a house near the bank. +tradeable=no [trail_clue_medium_riddle_exp004] name=Clue scroll @@ -305,6 +323,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,In a town where everyone has|perfect vision, seek some|locked drawers in a house that|sits opposite a workshop. +tradeable=no [trail_clue_medium_riddle_exp005] name=Clue scroll @@ -319,6 +338,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,In a town where wizards are|known to gather, search|upstairs in a large|house to the north. +tradeable=no [trail_clue_medium_anagram_exp001] name=Clue scroll @@ -333,6 +353,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,Speak to Hazelmere. +tradeable=no [trail_clue_medium_anagram_exp002] name=Clue scroll @@ -347,6 +368,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,This anagram reveals|who to speak to next:||OK CO +tradeable=no [trail_clue_medium_anagram_exp003] name=Clue scroll @@ -361,6 +383,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,This anagram reveals|who to speak to next:||EEK ZERO OP +tradeable=no [trail_clue_medium_anagram_exp004] name=Clue scroll @@ -375,6 +398,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,This anagram reveals|who to speak to next:||EL OW +tradeable=no [trail_clue_medium_anagram_exp005] name=Clue scroll @@ -389,6 +413,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,Speak to Hadejy. +tradeable=no [trail_clue_medium_anagram_exp006] name=Clue scroll @@ -404,6 +429,7 @@ iop1=Read category=trail_clue_medium // changed to R AK MI on september 26th, 2005 param=trail_desc,This anagram reveals|who to speak to next:||BAR BELL SEEK +tradeable=no [trail_clue_medium_anagram_exp007] name=Clue scroll @@ -418,6 +444,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,This anagram reveals|who to speak to next:||ARE COL +tradeable=no [trail_clue_medium_anagram_exp008] name=Clue scroll @@ -432,6 +459,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,Speak to a referee. +tradeable=no [trail_clue_medium_anagram_exp009] name=Clue scroll @@ -446,6 +474,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,Speak to Donovan, the|Family Handyman. +tradeable=no [trail_clue_medium_anagram_exp010] name=Clue scroll @@ -460,6 +489,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,This anagram reveals|who to speak to next:||PEATY PERT +tradeable=no [trail_clue_medium_anagram_exp011] name=Clue scroll @@ -474,6 +504,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,This anagram reveals|who to speak to next:||GOBLIN KERN +tradeable=no [trail_clue_medium_anagram_exp012] name=Clue scroll @@ -488,6 +519,7 @@ model=model_3374_obj iop1=Read category=trail_clue_medium param=trail_desc,This anagram reveals|who to speak to next:||HALT US +tradeable=no [trail_clue_medium_challenge_exp001] name=Challenge scroll @@ -503,6 +535,7 @@ iop1=Read category=trail_challenge param=trail_desc,What is 19 to the power of 3? param=trail_challenge_answer,6859 +tradeable=no [trail_clue_medium_challenge_exp002] name=Challenge scroll @@ -518,6 +551,7 @@ iop1=Read category=trail_challenge param=trail_desc,How many cannons does|Lumbridge Castle have? param=trail_challenge_answer,9 +tradeable=no [trail_clue_medium_challenge_exp003] name=Challenge scroll @@ -533,6 +567,7 @@ iop1=Read category=trail_challenge param=trail_desc,How many animals in total|are there in the zoo? param=trail_challenge_answer,32 +tradeable=no [trail_clue_medium_challenge_exp004] name=Challenge scroll @@ -548,6 +583,7 @@ iop1=Read category=trail_challenge param=trail_desc,I have 16 kebabs, I eat one|myself and then share the rest|equally between 3 friends.|How many do they have each? param=trail_challenge_answer,5 +tradeable=no [trail_clue_medium_challenge_exp005] name=Challenge scroll @@ -563,6 +599,7 @@ iop1=Read category=trail_challenge param=trail_desc,If x is 15 and y is 3|What is 3x + y? param=trail_challenge_answer,48 +tradeable=no [trail_clue_medium_challenge_exp006] name=Challenge scroll @@ -578,3 +615,4 @@ iop1=Read category=trail_challenge param=trail_desc,What is 57 x 89 + 23? param=trail_challenge_answer,5096 +tradeable=no diff --git a/data/src/scripts/minigames/game_trawler/configs/trawler.obj b/data/src/scripts/minigames/game_trawler/configs/trawler.obj index 0a7a57ed93..55dbd0e362 100644 --- a/data/src/scripts/minigames/game_trawler/configs/trawler.obj +++ b/data/src/scripts/minigames/game_trawler/configs/trawler.obj @@ -12,7 +12,6 @@ womanwear=model_543_obj_wear,6 iop1=Bail-with weight=1kg members=yes -tradeable=yes [bailing_bucket_full] name=Bailing bucket @@ -28,4 +27,3 @@ womanwear=model_543_obj_wear,6 iop1=Empty weight=5kg members=yes -tradeable=yes diff --git a/data/src/scripts/npc/configs/ai_spawn.varn b/data/src/scripts/npc/configs/ai_spawn.varn new file mode 100644 index 0000000000..6a3d636a50 --- /dev/null +++ b/data/src/scripts/npc/configs/ai_spawn.varn @@ -0,0 +1 @@ +[npc_combat_xp_multiplier] \ No newline at end of file diff --git a/data/src/scripts/npc/scripts/ai_spawn.rs2 b/data/src/scripts/npc/scripts/ai_spawn.rs2 new file mode 100644 index 0000000000..8001e20886 --- /dev/null +++ b/data/src/scripts/npc/scripts/ai_spawn.rs2 @@ -0,0 +1,2 @@ +[ai_spawn,_] +%npc_combat_xp_multiplier = npc_param(combat_xp_multiplier); \ No newline at end of file diff --git a/data/src/scripts/npc/scripts/chaos_druid.rs2 b/data/src/scripts/npc/scripts/chaos_druid.rs2 index 50a58934b5..514565aed1 100644 --- a/data/src/scripts/npc/scripts/chaos_druid.rs2 +++ b/data/src/scripts/npc/scripts/chaos_druid.rs2 @@ -2,6 +2,10 @@ if (%npc_action_delay > map_clock) { return; } +if (~npc_can_attack_player = false) { + npc_setmode(null); + return; +} ~chaos_druid_spell; if(random(4) ! 0) npc_setmode(opplayer2); @@ -9,6 +13,10 @@ if(random(4) ! 0) npc_setmode(opplayer2); if (%npc_action_delay > map_clock) { return; } +if (~npc_can_attack_player = false) { + npc_setmode(null); + return; +} // ~1/4 based off 100 attacks in osrs if(random(3) = 0) { ~chaos_druid_spell; @@ -18,12 +26,24 @@ if(random(3) = 0) { [proc,chaos_druid_spell] def_dbrow $spell_data = ~get_spell_data(^bind); +def_dbrow $effect_spell = ~get_spell_data(^confuse); def_int $duration = ~npc_spell_cast($spell_data, 4); if (~npc_player_hit_roll(^magic_style) = true) { ~npc_spell_success($spell_data, null, $duration); - if(~npc_debuff_allowed($spell_data) = true) ~npc_stat_change_effect(~get_spell_data(^weaken)); + if(~npc_debuff_allowed($effect_spell) = true) ~npc_stat_change_effect($effect_spell); + queue(chaosdruid_freeze_player, 0); } else { ~npc_spell_fail($spell_data, $duration); } -~npc_set_attack_vars; \ No newline at end of file +~npc_set_attack_vars; + +[queue,chaosdruid_freeze_player] +%frozen = calc(map_clock + 3); +walktrigger(chaos_druid_frozen); + +[walktrigger,chaos_druid_frozen] +if (map_clock < %frozen) { + p_walk(coord); + walktrigger(chaos_druid_frozen); +} \ No newline at end of file diff --git a/data/src/scripts/player/configs/consumption/consume.param b/data/src/scripts/player/configs/consumption/consume.param index efade2220f..8d3c3d33ff 100644 --- a/data/src/scripts/player/configs/consumption/consume.param +++ b/data/src/scripts/player/configs/consumption/consume.param @@ -1,3 +1,7 @@ [next_obj_stage] type=namedobj -default=null \ No newline at end of file +default=null + +[cures_poison] +type=boolean +default=no \ No newline at end of file diff --git a/data/src/scripts/player/scripts/changestat.rs2 b/data/src/scripts/player/scripts/changestat.rs2 new file mode 100644 index 0000000000..3a4f693ce0 --- /dev/null +++ b/data/src/scripts/player/scripts/changestat.rs2 @@ -0,0 +1 @@ +[changestat,_] gosub(player_combat_stat); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_arena/configs/quest_arena.npc b/data/src/scripts/quests/quest_arena/configs/quest_arena.npc index 5db708eb85..6e2b3f9b9b 100644 --- a/data/src/scripts/quests/quest_arena/configs/quest_arena.npc +++ b/data/src/scripts/quests/quest_arena/configs/quest_arena.npc @@ -29,14 +29,15 @@ strength=18 defence=20 param=attackbonus,10 param=strengthbonus,14 -param=stabdefence,44 -param=slashdefence,38 -param=crushdefence,30 +param=stabdefence,35 +param=slashdefence,29 +param=crushdefence,21 param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash // param=defend_sound,blade3_mail +// Stats match osrs version but our version Vislvl is different. [khazard_guard_drunk] name=Khazard Guard @@ -69,14 +70,15 @@ strength=18 defence=20 param=attackbonus,10 param=strengthbonus,14 -param=stabdefence,44 -param=slashdefence,38 -param=crushdefence,30 +param=stabdefence,35 +param=slashdefence,29 +param=crushdefence,21 param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash // param=defend_sound,blade3_mail +// Stats match osrs version but our version Vislvl is different. [khazard_guard_chest] name=Khazard Guard @@ -108,14 +110,15 @@ strength=18 defence=20 param=attackbonus,10 param=strengthbonus,14 -param=stabdefence,44 -param=slashdefence,38 -param=crushdefence,30 +param=stabdefence,35 +param=slashdefence,29 +param=crushdefence,21 param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash // param=defend_sound,blade3_mail +// Stats match osrs version but our version Vislvl is different. [khazard_guard_standard] name=Khazard Guard @@ -148,14 +151,15 @@ strength=18 defence=20 param=attackbonus,10 param=strengthbonus,14 -param=stabdefence,44 -param=slashdefence,38 -param=crushdefence,30 +param=stabdefence,35 +param=slashdefence,29 +param=crushdefence,21 param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash // param=defend_sound,blade3_mail +// Stats match osrs version but our version Vislvl is different. [khazard_guard_cutscene] name=Khazard Guard @@ -185,9 +189,9 @@ strength=18 defence=20 param=attackbonus,10 param=strengthbonus,14 -param=stabdefence,44 -param=slashdefence,38 -param=crushdefence,30 +param=stabdefence,35 +param=slashdefence,29 +param=crushdefence,21 param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 @@ -226,6 +230,10 @@ param=defend_anim,human_2h_sword_defend // param=attack_sound, // param=defend_sound, // osrs use attack seq_406 +// TODO monster examine spell +// TODO param stats +// TODO sounds + maxranges +// Stats match osrs version but our version Vislvl is different. [khazard_barman] vislevel=hide @@ -426,6 +434,8 @@ model7=model_181_idk head1=model_63_idk_head head2=model_82_idk_head wanderrange=7 +hitpoints=20 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_12035 [local] vislevel=hide @@ -458,8 +468,8 @@ desc=Nice doggy. op2=Attack vislevel=132 model1=model_2997_npc -// wanderrange=TODO // Guess, based off old videos they will likely hunt through the whole arena: https://youtu.be/qRUXxpnYUp4?si=o4ePw20m2vZrLNBG&t=416 +// wanderrange=TODO maxrange=25 respawnrate=100 hitpoints=116 @@ -474,6 +484,9 @@ param=attack_sound,growl6 param=defend_sound,growl5 huntmode=aggressive_melee huntrange=2 +// TODO monster examine spell +// TODO param stats +// Stats match osrs version but our version Vislvl is different. [khazard_ogre] name=Khazard Ogre @@ -506,6 +519,9 @@ param=defend_sound,giant_hit param=death_sound,giant_death huntmode=aggressive_melee huntrange=2 +// TODO monster examine spell +// TODO param stats +// Stats match osrs version but our version Vislvl is different. [khazard_scorpion] name=Khazard Scorpion @@ -541,4 +557,7 @@ param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null huntmode=aggressive_melee -huntrange=2 \ No newline at end of file +huntrange=2 +// TODO monster examine spell +// TODO param stats +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_arena/configs/quest_arena.obj b/data/src/scripts/quests/quest_arena/configs/quest_arena.obj index 06e0d42b52..a4c0d96b3a 100644 --- a/data/src/scripts/quests/quest_arena/configs/quest_arena.obj +++ b/data/src/scripts/quests/quest_arena/configs/quest_arena.obj @@ -25,6 +25,7 @@ category=armour_helmet param=stabdefence,4 param=slashdefence,5 param=crushdefence,3 +tradeable=no [khazard_armour] members=yes @@ -51,6 +52,7 @@ category=armour_body param=stabdefence,9 param=slashdefence,11 param=crushdefence,10 +tradeable=no [khazard_cell_keys] members=yes @@ -64,6 +66,7 @@ model=model_2424_obj 2dxan=508 weight=10g param=no_alchemy,1 +tradeable=no [khali_brew] members=yes @@ -78,3 +81,4 @@ recol1d=384 2dyan=1888 2dxan=104 weight=4oz +tradeable=no diff --git a/data/src/scripts/quests/quest_arthur/configs/keep_le_faye.npc b/data/src/scripts/quests/quest_arthur/configs/keep_le_faye.npc index c9668ecd64..63abce72a0 100644 --- a/data/src/scripts/quests/quest_arthur/configs/keep_le_faye.npc +++ b/data/src/scripts/quests/quest_arthur/configs/keep_le_faye.npc @@ -41,6 +41,7 @@ param=attack_sound,stabsword_stab // param=defend_sound,blade4 huntmode=cowardly huntrange=1 +// Stats match osrs version but our version Vislvl is different. [sir_mordred] name=Sir Mordred @@ -90,6 +91,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=attack_sound,2H_slash // param_defend_sound,steel2 +// Stats match osrs version but our version Vislvl is different. [morgan_le_faye] vislevel=hide diff --git a/data/src/scripts/quests/quest_arthur/configs/quest_arthur.obj b/data/src/scripts/quests/quest_arthur/configs/quest_arthur.obj index d4a8078112..76e8cb09cf 100644 --- a/data/src/scripts/quests/quest_arthur/configs/quest_arthur.obj +++ b/data/src/scripts/quests/quest_arthur/configs/quest_arthur.obj @@ -12,6 +12,7 @@ recol1d=2114 2dxan=168 weight=1oz category=light_source_lit +tradeable=no [lit_candle] name=Lit candle @@ -24,7 +25,6 @@ model=model_2575_obj 2dyan=1864 2dxan=168 weight=1oz -tradeable=yes category=light_source_lit [excalibur] @@ -57,6 +57,7 @@ param=stabattack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=slash_sound,hacksword_slash param=stab_sound,hacksword_stab +tradeable=no [candle] name=Candle @@ -69,7 +70,6 @@ model=model_2467_obj 2dyan=1864 2dxan=168 weight=1oz -tradeable=yes category=light_source_unlit param=product,lit_candle @@ -88,3 +88,4 @@ recol1d=2114 weight=1oz category=light_source_unlit param=product,lit_black_candle +tradeable=no diff --git a/data/src/scripts/quests/quest_ball/configs/quest_ball.obj b/data/src/scripts/quests/quest_ball/configs/quest_ball.obj index 4669329c7e..2e3265c13d 100644 --- a/data/src/scripts/quests/quest_ball/configs/quest_ball.obj +++ b/data/src/scripts/quests/quest_ball/configs/quest_ball.obj @@ -8,6 +8,7 @@ model=model_2755_obj 2dxan=300 weight=150g members=yes +tradeable=no [ball_diary] name=Diary @@ -22,6 +23,7 @@ recol1d=23056 2dxan=256 weight=18oz respawnrate=30 +tradeable=no [ball_doorkey] name=Door key @@ -37,6 +39,7 @@ recol1d=22945 2dxan=328 weight=10g respawnrate=95 +tradeable=no [magnet] name=Magnet @@ -50,6 +53,7 @@ model=model_2798_obj 2dxan=440 weight=20g members=yes +tradeable=no [ball_shedkey] name=Key @@ -63,4 +67,5 @@ recol1d=16912 2dzoom=700 2dyan=20 2dxan=328 -weight=10g \ No newline at end of file +weight=10g +tradeable=no diff --git a/data/src/scripts/quests/quest_ball/configs/witches_house.npc b/data/src/scripts/quests/quest_ball/configs/witches_house.npc index c79ac17e16..ff8fa57835 100644 --- a/data/src/scripts/quests/quest_ball/configs/witches_house.npc +++ b/data/src/scripts/quests/quest_ball/configs/witches_house.npc @@ -57,7 +57,9 @@ param=death_anim,skavid_death param=attack_sound,imp_attack param=defend_sound,imp_hit param=death_sound,imp_death +param=death_drop,null category=witches_experiment +// osrs stats and Vislvl match 1:1 [witches_experiment_p2] name=Witches experiment second form @@ -84,6 +86,7 @@ param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null category=witches_experiment +// osrs stats and Vislvl match 1:1 [witches_experiment_p3] name=Witches experiment third form @@ -112,7 +115,9 @@ param=death_anim,bear_death param=attack_sound,bear_attack param=defend_sound,bear_hit param=death_sound,bear_death +param=death_drop,null category=witches_experiment +// osrs stats and Vislvl match 1:1 [witches_experiment_p4] name=Witches experiment fourth form @@ -137,11 +142,12 @@ param=damagetype,^stab_style param=attack_anim,dog_attack param=defend_anim,dog_block param=death_anim,dog_death -// param_attack_sound, -// param_defend_sound, -// param_death_sound, +param=attack_sound,wolf_attack2 +param=defend_sound,wolf_hit +param=death_sound,wolf_death param=death_drop,null category=witches_experiment +// osrs stats and Vislvl match 1:1 [ball_mouse] vislevel=hide diff --git a/data/src/scripts/quests/quest_barcrawl/configs/quest_barcrawl.obj b/data/src/scripts/quests/quest_barcrawl/configs/quest_barcrawl.obj index 5b6fb55633..193ed381cb 100644 --- a/data/src/scripts/quests/quest_barcrawl/configs/quest_barcrawl.obj +++ b/data/src/scripts/quests/quest_barcrawl/configs/quest_barcrawl.obj @@ -11,3 +11,4 @@ model=model_2430_obj 2dxan=404 weight=150g iop1=Read +tradeable=no diff --git a/data/src/scripts/quests/quest_biohazard/configs/quest_biohazard.obj b/data/src/scripts/quests/quest_biohazard/configs/quest_biohazard.obj index 095fc4e9e6..ba1cc951a3 100644 --- a/data/src/scripts/quests/quest_biohazard/configs/quest_biohazard.obj +++ b/data/src/scripts/quests/quest_biohazard/configs/quest_biohazard.obj @@ -11,6 +11,7 @@ desc=An expensive colourless liquid. 2dxan=84 weight=30g param=no_alchemy,1 +tradeable=no [liquid_honey] cost=0 @@ -26,6 +27,7 @@ desc=This isn't worth much. 2dxan=84 weight=30g param=no_alchemy,1 +tradeable=no [sulphuric_broline] cost=1 @@ -41,6 +43,7 @@ desc=It's highly poisonous. 2dxan=84 weight=30g param=no_alchemy,1 +tradeable=no [plague_sample] name=Plague sample @@ -54,6 +57,7 @@ model=model_2788_obj weight=50g members=yes param=no_alchemy,1 +tradeable=no [touch_paper] name=Touch paper @@ -68,6 +72,7 @@ model=model_2781_obj weight=10g members=yes param=no_alchemy,1 +tradeable=no [distillator] members=yes @@ -82,6 +87,7 @@ model=model_2613_obj 2dxan=304 weight=20g param=no_alchemy,1 +tradeable=no [obj_421] name=Lathas' amulet @@ -99,6 +105,7 @@ wearpos=front manwear=model_282_obj_wear,0 womanwear=model_446_obj_wear,0 weight=10g +tradeable=no [bird_feed] name=Bird feed @@ -113,6 +120,7 @@ model=model_2678_obj weight=50g members=yes param=no_alchemy,1 +tradeable=no [biohazard_key] name=Key @@ -127,6 +135,7 @@ model=model_2372_obj weight=10g members=yes param=no_alchemy,1 +tradeable=no [pigeon_cage] cost=1 @@ -142,6 +151,7 @@ iop1=Open weight=2kg members=yes param=no_alchemy,1 +tradeable=no [pigeon_cage_empty] cost=1 @@ -154,6 +164,7 @@ model=model_2663_obj weight=500g members=yes param=no_alchemy,1 +tradeable=no [priest_gown_top] name=Priest gown @@ -173,7 +184,6 @@ manwear2=model_170_idk womanwear=model_456_idk,0 womanwear2=model_348_idk weight=4lb -tradeable=yes param=prayerbonus,3 [priest_gown_bottom] @@ -191,7 +201,6 @@ wearpos=legs manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=4lb -tradeable=yes param=prayerbonus,3 [doctors_gown] @@ -213,3 +222,4 @@ womanwear=model_456_idk,0 womanwear2=model_332_idk weight=4lb members=yes +tradeable=no diff --git a/data/src/scripts/quests/quest_blackarmgang/configs/quest_blackarmgang.obj b/data/src/scripts/quests/quest_blackarmgang/configs/quest_blackarmgang.obj index 99ec5e063d..9b9e3dcd37 100644 --- a/data/src/scripts/quests/quest_blackarmgang/configs/quest_blackarmgang.obj +++ b/data/src/scripts/quests/quest_blackarmgang/configs/quest_blackarmgang.obj @@ -7,6 +7,7 @@ model=model_2794_obj 2dyan=152 2dxan=256 weight=200g +tradeable=no [obj_758] name=Key @@ -18,6 +19,7 @@ model=model_2372_obj 2dyan=20 2dxan=328 weight=10g +tradeable=no [weapon_store_key] name=Key @@ -29,7 +31,6 @@ model=model_2372_obj 2dyan=20 2dxan=328 weight=10g -tradeable=yes [blackarmgang_scroll] name=Scroll @@ -42,7 +43,6 @@ model=model_2600_obj 2dyan=120 2dxan=380 weight=20g -tradeable=yes [arravshield1] name=Broken shield @@ -54,7 +54,6 @@ model=model_2757_obj 2dyan=172 2dxan=220 weight=6lb -tradeable=yes param=no_alchemy,1 [arravshield2] @@ -66,7 +65,6 @@ model=model_2757_obj 2dyan=1160 2dxan=192 weight=6lb -tradeable=yes param=no_alchemy,1 [phoenix_crossbow] @@ -86,7 +84,6 @@ iop2=Wield wearpos=righthand manwear=model_508_obj_wear,0 womanwear=model_508_obj_wear,6 -tradeable=yes param=rangeattack,6 param=levelrequire,1 param=attackrate,6 @@ -105,4 +102,3 @@ model=model_2600_obj 2dyan=120 2dxan=380 weight=20g -tradeable=yes diff --git a/data/src/scripts/quests/quest_blackknight/configs/quest_blackknight.npc b/data/src/scripts/quests/quest_blackknight/configs/quest_blackknight.npc index 7e204a869e..c10d306686 100644 --- a/data/src/scripts/quests/quest_blackknight/configs/quest_blackknight.npc +++ b/data/src/scripts/quests/quest_blackknight/configs/quest_blackknight.npc @@ -26,6 +26,7 @@ hitpoints=22 attack=18 strength=18 defence=15 +param=attackrate,6 param=attackbonus,5 param=strengthbonus,6 param=stabdefence,14 @@ -33,11 +34,11 @@ param=slashdefence,18 param=crushdefence,14 param=magicdefence,-4 param=crushdefence,15 -param=attackrate,6 param=damagetype,^stab_style param=attack_anim,human_spear_stab param=defend_anim,human_spear_def param=attack_sound,staff_stab +// osrs stats and Vislvl match 1:1 [black_knight_knight] vislevel=hide diff --git a/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.npc b/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.npc index 3d22630f30..509edbc14b 100644 --- a/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.npc +++ b/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.npc @@ -82,16 +82,23 @@ resizev=180 op5=Attack vislevel=6 model1=model_3445_obj -param=attack_sound,chompy_bird_attack +wanderrange=3 +hitpoints=10 +attack=5 +strength=5 +defence=3 param=attack_anim,seq_1012 -param=defend_sound,chompy_bird_hit param=defend_anim,seq_1011 -param=death_sound,chompy_bird_death param=death_anim,seq_1009 -// TODO tbc -huntrange=10 -hitpoints=10 +param=attack_sound,chompy_bird_attack +param=defend_sound,chompy_bird_hit +param=death_sound,chompy_bird_death +// TODO tbc + missing datas wanderrange=3 +// Hunt range is a guess +// If removed, chompy won't hunt for toads during quest +huntrange=10 +// osrs stats and Vislvl match 1:1 [chompy_bird_corpse] vislevel=hide diff --git a/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.obj b/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.obj index 0621de2b9e..58e27f6e81 100644 --- a/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.obj +++ b/data/src/scripts/quests/quest_chompybird/configs/quest_chompybird.obj @@ -10,6 +10,7 @@ model=model_3440_obj 2dyan=36 2dxan=112 weight=18oz +tradeable=no [ogre_bellows_3] name=Ogre bellows (3) @@ -23,6 +24,7 @@ recol1d=6628 2dyan=36 2dxan=112 weight=18oz +tradeable=no [ogre_bellows_2] name=Ogre bellows (2) @@ -36,6 +38,7 @@ recol1d=10726 2dyan=36 2dxan=112 weight=18oz +tradeable=no [ogre_bellows_1] name=Ogre bellows (1) @@ -49,6 +52,7 @@ recol1d=14824 2dyan=36 2dxan=112 weight=18oz +tradeable=no [bloated_toad] name=Bloated toad @@ -64,6 +68,7 @@ weight=750g iop1=Drop iop4=Release All iop5=Release +tradeable=no [raw_chompy] name=Raw chompy @@ -78,7 +83,6 @@ recol1d=19014 2dyan=1748 2dxan=88 weight=10kg -tradeable=yes [cooked_chompy] name=Cooked chompy @@ -95,7 +99,6 @@ recol1d=14690 weight=10kg iop1=Eat category=category_5 -tradeable=yes [ruined_chompy] name=Ruined chompy @@ -109,7 +112,6 @@ recol1d=6273 2dyan=1748 2dxan=88 weight=10kg -tradeable=yes [seasoned_chompy] name=Seasoned chompy @@ -124,8 +126,9 @@ recol1d=17697 2dyan=1748 2dxan=88 weight=10kg +tradeable=no [chompy_bird_obj] model=model_3445_obj -tradeable=yes -dummyitem=graphic_only +// there's a cert, so it must be tradeable and therefore not a dummyitem? +//dummyitem=graphic_only diff --git a/data/src/scripts/quests/quest_chompybird/scripts/bugs.rs2 b/data/src/scripts/quests/quest_chompybird/scripts/bugs.rs2 index 937d5e840f..1fc8b28a83 100644 --- a/data/src/scripts/quests/quest_chompybird/scripts/bugs.rs2 +++ b/data/src/scripts/quests/quest_chompybird/scripts/bugs.rs2 @@ -13,7 +13,7 @@ switch_int(%chompybird_progress) { ~chatplayer("That's right... I'm making some 'stabbers' for Rantz."); ~chatnpc("Dat's great...Dad want's to hunt da chompy... Da chompy is our bestest yumms! Yous needies da scratchers for makin' dem huh? I's wants some bright pretties for em!"); - ~doubleobjbox(chisel, knife, "Bugs shows you a chisel and a knife."); + ~doubleobjbox(chisel, knife, "Bugs shows you a chisel and a knife.", 150); ~chatplayer("How many 'bright pretties' do you want?"); ~chatnpc("Bugs wants lots of bright pretties, this many!|@blu@~ Bugs quickly opens and closes his hands in front ~|@blu@~ of you to indicate a number of bright pretties. ~|@blu@~ It looks like he wants 10 gold coins.~"); @@ -27,23 +27,22 @@ switch_int(%chompybird_progress) { return; } - if (inv_freespace(inv) < 2) { - // todo what to do? - return; - } - - ~doubleobjbox(chisel, coins, "You offer the 10 coins for the tools."); + // No inv space check - OSRS drops the feathers on the floor + ~doubleobjbox(chisel, coins, "You offer the 10 coins for the tools.", 150); inv_del(inv, coins, 10); inv_add(inv, chisel, 1); inv_add(inv, knife, 1); ~chatnpc("Ok, dat's a good 'un, I got da bright pretties and you got da scratchers!"); case 2 : - // todo mesanim tbc ~chatplayer("Er, sorry, I can't give you that many..."); ~chatnpc("Well, you not have da scratchers den!"); } + case ^chompybird_kids_play_with_toad, ^chompybird_removed_rock_from_chest : + ~chatplayer("Rantz said that you play with the 'fatsy toadies', what are they?"); + ~chatnpc("Oh we sometimes use da blower on da toadies but Dad don't let us get in da locked box no more. He, he, it was good fun making da toadies fat on da swamp gas."); + case ^chompybird_shown_toad : ~chatnpc("You's better talk to Dad, he might have something for you to do."); @@ -62,11 +61,9 @@ switch_int(%chompybird_progress) { ~chatnpc("Dad say's you's making da chompy for us! Slurp! Me's|has to have <$chompy_flavour> wiv mine! Chompy is our|favourite yummms!"); - case ^chompybird_chompy_cooked : - // todo mesanim TBC - ~chatnpc("Have you talked to Dad, he might have something for you to do."); + case ^chompybird_complete : + ~chatnpc("Thanks for da chompy, it was deloverly!"); case default : - // todo TBC other states - return; + ~chatnpc("Have you talked to Dad, he might have something for you to do."); } diff --git a/data/src/scripts/quests/quest_chompybird/scripts/chompy_bird.rs2 b/data/src/scripts/quests/quest_chompybird/scripts/chompy_bird.rs2 index cfe22ad937..497ec8be4b 100644 --- a/data/src/scripts/quests/quest_chompybird/scripts/chompy_bird.rs2 +++ b/data/src/scripts/quests/quest_chompybird/scripts/chompy_bird.rs2 @@ -48,7 +48,6 @@ npc_del; [apnpc5,chompy_bird] def_obj $rhand = inv_getobj(worn, ^wearpos_rhand); - // make the player run to the bird if they are unarmed if ($rhand = null) { @@ -147,7 +146,7 @@ if (%damagestyle = ^style_ranged_longrange) { } if (($attackrange <= 1 & ~player_in_combat_check = false) | $distance > $attackrange) { - // p_opnpc(2); + p_opnpc(5); p_aprange($attackrange); return; } @@ -157,7 +156,7 @@ p_stopaction; // facesquare(npc_coord); if (%action_delay > map_clock) { - p_opnpc(2); + p_opnpc(5); return; } @@ -175,10 +174,10 @@ def_int $damage = 0; if (~player_npc_hit_roll(%damagetype) = true) { $damage = randominc(min(%com_maxhit, npc_param(max_dealt))); $damage = min($damage, npc_stat(hitpoints)); - ~give_combat_experience(%damagestyle, $damage, npc_param(combat_xp_multiplier)); + ~give_combat_experience(%damagestyle, $damage, %npc_combat_xp_multiplier); } -def_int $delay = add(~player_ranged_use_weapon($rhand, $ammo), 30); // osrs it seems to be delayed an extra tick +def_int $delay = add(~player_use_ogre_bow($ammo), 30); // osrs it seems to be delayed an extra tick anim(%com_attackanim, 0); sound_synth(%com_attacksound, 0, 0); ~npc_retaliate(calc($delay / 30)); @@ -189,8 +188,7 @@ if (npc_param(defend_sound) ! null) { } npc_heropoints($damage); - -p_opnpc(2); +p_opnpc(5); if (random(5) ! 0) { world_delay(calc($delay / 30 - 2)); if (map_blocked(npc_coord) = false) { @@ -201,6 +199,12 @@ if (random(5) ! 0) { } inv_clear(ranged_quiver_inv); +// Ogre arrow launch spotanim is higher than other arrows by default, so we compensate for that here +[proc,player_use_ogre_bow](obj $ammo)(int) +spotanim_pl(oc_param($ammo, proj_launch), 46, 0); +inv_moveitem(worn, ranged_quiver_inv, $ammo, 1); +return(~npc_projectile(coord, npc_uid, oc_param($ammo, proj_travel), 40, 36, 41, 15, 5, 11, 5)); + [ai_queue3,chompy_bird] gosub(npc_death); diff --git a/data/src/scripts/quests/quest_chompybird/scripts/fycie.rs2 b/data/src/scripts/quests/quest_chompybird/scripts/fycie.rs2 index 768bda9245..4007777b50 100644 --- a/data/src/scripts/quests/quest_chompybird/scripts/fycie.rs2 +++ b/data/src/scripts/quests/quest_chompybird/scripts/fycie.rs2 @@ -27,12 +27,8 @@ switch_int(%chompybird_progress) { return; } - if (inv_freespace(inv) = 0 & inv_total(inv, feather) = 0) { - // todo what to do? - return; - } - - ~doubleobjbox(feather, coins, "You offer the 50 coins for the 25 flufsies."); + // No inv space check - OSRS drops the feathers on the floor + ~doubleobjbox(feather, coins, "You offer the 50 coins for the 25 flufsies.", 150); inv_del(inv, coins, 50); inv_add(inv, feather, 25); @@ -42,8 +38,9 @@ switch_int(%chompybird_progress) { ~chatnpc("Well, you not have da flufsies den!"); } - case ^chompybird_shown_toad : - ~chatnpc("You's better talk to Dad, him chasey sneaky chompy."); + case ^chompybird_kids_play_with_toad, ^chompybird_removed_rock_from_chest : + ~chatplayer("Rantz said that you play with the 'fatsy toadies', what are they?"); + ~chatnpc("Oh we sometimes is using blower on da toadies but Dad don't let us get in da locksy bocksy no more. He, he, big chuklees when make da toadies fat on da swampy gas."); case ^chompybird_told_to_cook_chompy : def_int $flavour = getbit_range(%chompybird_kills, ^chompybird_varbit_fycie_flavour_start, ^chompybird_varbit_fycie_flavour_end); @@ -59,12 +56,10 @@ switch_int(%chompybird_progress) { } ~chatnpc("Dad say's you's roastling da chompy for us! Slurp!|Me's wants <$chompy_flavour> wiv mine! Yummy, can't wait|to eats it."); - - case ^chompybird_chompy_cooked : - // todo mesanim TBC - ~chatnpc("Go talk to Dad, him chasey sneaky chompy."); + + case ^chompybird_complete : + ~chatnpc("Thanks for da chompy, it was deloverly!"); case default : - // todo TBC other states - return; + ~chatnpc("You's better talk to Dad, him chasey sneaky chompy."); } diff --git a/data/src/scripts/quests/quest_chompybird/scripts/rantz.rs2 b/data/src/scripts/quests/quest_chompybird/scripts/rantz.rs2 index a82a9357a4..8de674ebd4 100644 --- a/data/src/scripts/quests/quest_chompybird/scripts/rantz.rs2 +++ b/data/src/scripts/quests/quest_chompybird/scripts/rantz.rs2 @@ -11,7 +11,6 @@ switch_int(%chompybird_progress) { ~chatplayer("I think I understand. You want me to make some arrows for you?"); ~chatnpc("Yeah, is what Rantz sayed, make da stabbers for da stabby chucker!"); - // todo this dialogue isn't in OSRS, try to find an old video switch_int(~p_choice2("OK, I'll make you some 'stabbers'.", 1, "Er, make you're own 'stabbers'!", 2)) { case 1 : ~chatplayer("OK, I'll make you some 'stabbers'."); @@ -19,13 +18,12 @@ switch_int(%chompybird_progress) { %chompybird_progress = ^chompybird_started; ~send_quest_progress(questlist:chompybird, %chompybird_progress, ^chompybird_complete); case 2 : - // todo text and mesanims TBC ~chatplayer("Er, make you're own 'stabbers'!"); ~chatnpc("When I make 'stabbers', I pretend you chompy and practice on you!"); } case ^chompybird_started : @return_to_rantz; - case ^chompybird_given_arrows : + case ^chompybird_given_arrows, ^chompybird_kids_play_with_toad, ^chompybird_removed_rock_from_chest : ~chatnpc("Hey you creature, you still here?"); ~chatnpc("Da chompy still not coming! We need da fatsy toady to get da chompy, do you got it? Do you got da fatsy toady? Then we can sneaky, sneaky stick da chompy."); @@ -39,15 +37,15 @@ switch_int(%chompybird_progress) { } case ^chompybird_shown_toad : @where_to_put_toadies; - case ^chompybird_dropped_toad : + // Maybe chompy_ate_toad has a separate set of dialogue, but in normal circumstances the stage + // advances to rantz_tried_to_shoot_chompy too quickly to tell. + case ^chompybird_dropped_toad, ^chompybird_chompy_ate_toad : // todo mesanim TBC ~chatplayer("There you go, I've placed the bait."); ~chatnpc("Goodz, me now waits for da chompy! It shouldn't be long now. Sneaky... sneaky..."); ~chatplayer("Yes, I know... stick da chompy!"); ~chatnpc("Hey, you's creature, is da fatsy toady still dere? Go get more fatsy toadies if dey all gone!"); ~chatplayer("What? I have to get more bait if there's none there? Does this Chompy Bird even exist I wonder?"); - case ^chompybird_chompy_ate_toad : - mes("[debug] currently unimplemented"); case ^chompybird_rantz_tried_to_shoot_chompy : ~chatplayer("Hey there, you keep missing the chompy bird."); ~chatnpc("I knows, I keeps missing... because your stabbers are|worserer at flying than a dead dog."); @@ -86,7 +84,9 @@ switch_int(%chompybird_progress) { ~chatnpc("Well hurry up and get some, we is hungry!"); case ^chompybird_player_killed_chompy : if (inv_total(inv, raw_chompy) = 0) { - mes("[debug] todo currently unimplemented"); + ~chatnpc("Hey You! Got da chompy yet?"); + ~chatplayer("Not yet!"); + ~chatnpc("Well hurry up and get some, we is hungry!"); } else { // todo mesanim TBC ~chatnpc("Hey You! Got da chompy yet?"); @@ -99,8 +99,8 @@ switch_int(%chompybird_progress) { // todo what if the player no longer has the seasoned chompy? Does it still auto-hand in? @hand_chompy_to_rantz; case ^chompybird_complete : - // todo message tbc - ~chatnpc("Tank's very much for da chompy...|Fycie an Bugs like very much da chompy yumms!"); + ~chatnpc("Hey deyr, t'anks for da chompy, it was scrumbly!"); + // No chompy bird hats yet // todo dialog to buy ogre bow back from Rantz } @@ -111,9 +111,9 @@ switch_int(%chompybird_progress) { ~chatnpc("Dat's a great chompy, you musta got a lucky shot wiv|da stabbie chucker."); %chompybird_progress = ^chompybird_told_to_cook_chompy; if (random(1) = 0) { - setbit(%chompybird_kills, ^chompybird_varbit_rantz_flavour); + %chompybird_kills = setbit(%chompybird_kills, ^chompybird_varbit_rantz_flavour); } else { - clearbit(%chompybird_kills, ^chompybird_varbit_rantz_flavour); + %chompybird_kills = clearbit(%chompybird_kills, ^chompybird_varbit_rantz_flavour); } @rantz_tell_chompy_flavour; @@ -183,8 +183,8 @@ switch_obj(last_useitem) { ~chatnpc("Hey you creature..you made da stabbers|Dat's good creature!"); - if (%chompybird_progress = ^chompybird_started) { - // todo mesanim TBC + if (%chompybird_progress = ^chompybird_started & testbit(%chompybird_kills, ^chompybird_varbit_made_arrows) = false) { + // todo mesanim TBC ~chatnpc("Hey, deese stabbers no good... did you make dem you's self? You go make dem stabbers for me creature! Don't get old ones or from other creatures."); @no_arrows_choice; @@ -245,20 +245,17 @@ switch_int(~p_choice2("How do I make the 'stabbers' again?", 1, "Ok, I'll make t [label,attempt_give_rantz_arrows] ~chatplayer("Well, yes actually, as you asked so nicely. Here you go! Here's your 'stabbers'."); -if (inv_total(inv, ogre_arrow) < 6) { - // todo mesanim tbc +// This check runs first, then quantity +if (testbit(%chompybird_kills, ^chompybird_varbit_made_arrows) = false) { + ~chatnpc("Hey, 'dee'se stabbers no good! Did you make dem you's self? YOU go make dem arrows for ME creature!"); +} +else if (inv_total(inv, ogre_arrow) < 6) { ~chatnpc("Dat's not enough, me's an good shot, but need some for practice. Bring more than fingers on hand..."); - return; } - -if (testbit(%chompybird_kills, ^chompybird_varbit_made_arrows) = true) { - // todo mesanim tbc - ~chatnpc("Hey, 'dee'se stabbers no good! Did you make dem you's self? YOU go make dem arrows for ME creature!"); - return; +else { + @give_rantz_arrows; } -@give_rantz_arrows; - [label,give_rantz_arrows] inv_del(inv, ogre_arrow, 6); %chompybird_progress = ^chompybird_given_arrows; @@ -274,7 +271,9 @@ switch_int(~p_choice5("How do we make the chompys come?", 1, "What are 'fatsy to case 1 : ~chatplayer("How do we make the chompys come?"); ~chatnpc("Chompys love da fatsy toadies. Toadies get big on der swamp gas and der chompys are licking der lips for em as me is licking lips for da chompy. Da chompys don't like da smaller toadies from nearby swampy."); - %chompybird_progress = ^chompybird_kids_play_with_toad; + if (%chompybird_progress < ^chompybird_kids_play_with_toad) { + %chompybird_progress = ^chompybird_kids_play_with_toad; + } ~chatnpc("Dey's fussie eaters just like Rantz. Fycie an' Bugs play with toadies and blower dey's all times making fatsy toadies."); @toadies_questions; case 2 : @@ -341,21 +340,18 @@ while (.npc_findnext = true) { if (p_finduid(.%quest_chompybird_baiter) = true) { // we only run this logic for players in the right quest state if (%chompybird_progress = ^chompybird_chompy_ate_toad) { - // todo fix the delays in this section - // todo send mesbox if player is close? // not sure which one was in 04 mes("Rantz: Hey, dere's da chompy, I's gonna shoot it."); npc_facesquare(.npc_coord); - // npc_delay(1); + npc_delay(1); npc_anim(ogre_attackbow, 0); spotanim_npc(ogre_arrow_launch, 50, 0); def_int $duration = ~npc_projectile(npc_coord, .npc_uid, ogre_arrow_travel, 40, 36, 41, 15, 5, 11, 5); - // def_int $delay = add(sub(divide($duration, 30), 1), 2); - - // npc_delay($delay); + def_int $delay = add(sub(divide($duration, 30), 1), 2); + npc_delay($delay); if (p_finduid(.%quest_chompybird_baiter) = true) { %chompybird_progress = ^chompybird_rantz_tried_to_shoot_chompy; @@ -364,6 +360,7 @@ while (.npc_findnext = true) { mes("Rantz keeps missing the chompy bird..."); mes("Rantz: Grrr...de'ese arrows are rubbish."); } + return; } } } diff --git a/data/src/scripts/quests/quest_chompybird/scripts/raw_chompy.rs2 b/data/src/scripts/quests/quest_chompybird/scripts/raw_chompy.rs2 index 8f9556c362..6fccd0908f 100644 --- a/data/src/scripts/quests/quest_chompybird/scripts/raw_chompy.rs2 +++ b/data/src/scripts/quests/quest_chompybird/scripts/raw_chompy.rs2 @@ -18,6 +18,11 @@ if (last_useitem ! raw_chompy) ~displaymessage(^dm_default); return; } +if (stat(cooking) < 30) { + // Guess + ~mesbox("You need a Cooking level of 30 to cook chompy birds."); + return; +} // todo allow cooking after quest if (%chompybird_progress < ^chompybird_told_to_cook_chompy) @@ -29,10 +34,9 @@ if (%chompybird_progress < ^chompybird_told_to_cook_chompy) if (%chompybird_progress = ^chompybird_told_to_cook_chompy) { - @cook_chompy_quest; + @cook_chompy_quest(loc_coord); return; } - if (%chompybird_progress = ^chompybird_chompy_cooked) { // todo what if the player no longer has the original chompy? Does it still auto-hand in? @@ -51,7 +55,7 @@ if (%chompybird_progress = ^chompybird_chompy_cooked) // todo handle non-quest cooking ~displaymessage(^dm_default); -[label,cook_chompy_quest] +[label,cook_chompy_quest](coord $loc_coord) def_int $bugs_ingredient = getbit_range(%chompybird_kills, ^chompybird_varbit_bugs_flavour_start, ^chompybird_varbit_bugs_flavour_end); def_int $fycie_ingredient = getbit_range(%chompybird_kills, ^chompybird_varbit_fycie_flavour_start, ^chompybird_varbit_fycie_flavour_end); @@ -136,12 +140,46 @@ if ($has_rantz_ingredient = false | $has_bugs_ingredient = false | $has_fycie_in return; } -// todo in OSRS this takes some time, and the spit is animated -%chompybird_progress = ^chompybird_chompy_cooked; -mes("You carefully place the chompy bird on the spit-roast."); -inv_del(inv, raw_chompy, 1); +if (loc_find($loc_coord, ogre_spitroast) = true) { + %chompybird_progress = ^chompybird_chompy_cooked; + + mes("You carefully place the chompy bird on the spit-roast."); + inv_del(inv, raw_chompy, 1); + loc_change(ogre_spitroast_raw_chompy, 4); + loc_anim(spit_anim); + anim(human_cooking, 0); + sound_synth(spit_roast, 0, 0); + p_delay(2); + + def_boolean $passes_roll = stat_random(stat(cooking), 200, 255); + if ($passes_roll = true) { + mes("You add the other ingredients and cook the food."); + ~delete_chompy_ingredients($rantz_ingredient, $bugs_ingredient, $fycie_ingredient); + loc_change(ogre_spitroast_cooked_chompy, 4); + loc_anim(spit_anim); + anim(human_cooking, 0); + p_delay(2); + anim(human_pickuptable, 0); + mes("Eventually the chompy is cooked."); + inv_add(inv, seasoned_chompy, 1); + stat_advance(cooking, 142); + p_delay(1); + ~objbox(seasoned_chompy, "You use the <$rantz_ingredient_name>, <$bugs_ingredient_name> and the <$fycie_ingredient_name>|with the chompy bird to make a seasoned chompy.", 250, 0, divide(^objbox_height, 2)); + } + else { + mes("You accidentally burn the chompy."); + ~delete_chompy_ingredients($rantz_ingredient, $bugs_ingredient, $fycie_ingredient); + loc_change(ogre_spitroast_burnt_chompy, 4); + loc_anim(spit_anim); + anim(human_cooking, 0); + p_delay(2); + anim(human_pickuptable, 0); + inv_add(inv, ruined_chompy, 1); + p_delay(1); + } +} -mes("You add the other ingredients and cook the food."); +[proc,delete_chompy_ingredients](int $rantz_ingredient, int $bugs_ingredient, int $fycie_ingredient) if ($rantz_ingredient = 0) { inv_del(inv, potato, 1); @@ -167,8 +205,4 @@ if ($fycie_ingredient = 1) else if ($fycie_ingredient = 2) { inv_del(inv, doogle_leaves, 1); -} - -mes("Eventually the chompy is cooked."); -inv_add(inv, seasoned_chompy, 1); -~objbox(seasoned_chompy, "You use the <$rantz_ingredient_name>, <$bugs_ingredient_name> and the <$fycie_ingredient_name>|with the chompy bird to make a seasoned chompy.", 250, 0, divide(^objbox_height, 2)); +} \ No newline at end of file diff --git a/data/src/scripts/quests/quest_cog/configs/quest_cog.npc b/data/src/scripts/quests/quest_cog/configs/quest_cog.npc index 171e956194..c56a11459c 100644 --- a/data/src/scripts/quests/quest_cog/configs/quest_cog.npc +++ b/data/src/scripts/quests/quest_cog/configs/quest_cog.npc @@ -23,4 +23,7 @@ param=defend_anim,giantrat_block param=death_anim,giantrat_death param=attack_sound,rat_attack param=defend_sound,rat_hit -param=death_sound,rat_death \ No newline at end of file +param=death_sound,rat_death +// TODO monster examine spell +// Stats match osrs version but our version Vislvl is different. +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3607 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_cog/configs/quest_cog.obj b/data/src/scripts/quests/quest_cog/configs/quest_cog.obj index fb62641b5e..f472294844 100644 --- a/data/src/scripts/quests/quest_cog/configs/quest_cog.obj +++ b/data/src/scripts/quests/quest_cog/configs/quest_cog.obj @@ -7,6 +7,7 @@ members=yes 2dxan=292 weight=1kg category=cog +tradeable=no [black_cog] name=Cog @@ -19,6 +20,7 @@ members=yes 2dxan=292 weight=1kg category=cog +tradeable=no [blue_cog] name=Cog @@ -31,6 +33,7 @@ members=yes 2dxan=292 weight=1kg category=cog +tradeable=no [red_cog] name=Cog @@ -43,6 +46,7 @@ members=yes 2dxan=292 weight=1kg category=cog +tradeable=no [rat_poison] name=Rat poison @@ -52,4 +56,5 @@ members=yes 2dzoom=900 2dyan=1828 2dxan=68 -weight=5oz \ No newline at end of file +weight=5oz +tradeable=no diff --git a/data/src/scripts/quests/quest_crest/configs/quest_crest.constant b/data/src/scripts/quests/quest_crest/configs/quest_crest.constant new file mode 100644 index 0000000000..26c2718355 --- /dev/null +++ b/data/src/scripts/quests/quest_crest/configs/quest_crest.constant @@ -0,0 +1,28 @@ +^crest_not_started = 0 +^crest_spoken_dimintheis = 1 +^crest_spoken_caleb = 2 +^crest_caleb_piece = 3 +^crest_caleb_where = 4 +^crest_spoken_gem_trader = 5 +^crest_spoken_avan = 6 +^crest_spoken_boot = 7 +^crest_avan_piece = 8 +^crest_spoken_johnathon = 9 +^crest_cured_johnathon = 10 +^crest_complete = 11 + +^crest_wind_blast_used = 0 +^crest_water_blast_used = 1 +^crest_earth_blast_used = 2 +^crest_fire_blast_used = 3 +^crest_north_room_lever = 4 +^crest_north_lever = 5 +^crest_south_lever = 6 +^crest_cooking_gauntlets_chosen = 7 +^crest_goldsmithing_gauntlets_chosen = 8 +^crest_chaos_gauntlets_chosen = 9 + +^crest_all_spells_cast = 15 + +^crest_perfect_mine_lower_bound = 0_42_151_48_20 +^crest_perfect_mine_upper_bound = 0_42_151_52_29 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_crest/configs/quest_crest.loc b/data/src/scripts/quests/quest_crest/configs/quest_crest.loc new file mode 100644 index 0000000000..ac97bd4f7e --- /dev/null +++ b/data/src/scripts/quests/quest_crest/configs/quest_crest.loc @@ -0,0 +1,129 @@ + +[witchaven_north_lever_down] +name=Lever +desc=This lever is down. +model=model_loc_33 +active=yes +op1=Pull + +[witchaven_north_lever_up] +name=Lever +desc=This lever is up. +model=model_loc_34 +active=yes +op1=Pull + +[witchaven_south_lever_down] +name=Lever +desc=This lever is down. +model=model_loc_33 +active=yes +op1=Pull + +[witchaven_south_lever_up] +name=Lever +desc=This lever is up. +model=model_loc_34 +active=yes +op1=Pull + +[witchaven_north_room_lever_down] +name=Lever +desc=This lever is down. +model=model_loc_33 +active=yes +op1=Pull + +[witchaven_north_room_lever_up] +name=Lever +desc=This lever is up. +model=model_loc_34 +active=yes +op1=Pull + +[witchaven_south_west_door] +name=Door +desc=This door is closed by an unknown mechanism. +model=model_loc_3 +active=yes +op1=Open +retex1s=wall +retex1d=door2 +recol2s=6342 +recol2d=11458 + +[witchaven_door_open] +name=Door +desc=This door is closed by an unknown mechanism. +model=model_loc_3 +active=yes +op1=Open +retex1s=wall +retex1d=door2 +recol2s=6342 +recol2d=11458 + +[witchaven_south_east_door] +name=Door +desc=This door is closed by an unknown mechanism. +model=model_loc_3 +active=yes +op1=Open +retex1s=wall +retex1d=door2 +recol2s=6342 +recol2d=11458 + +[witchaven_goldmine_door] +name=Door +desc=This door is closed by an unknown mechanism. +model=model_loc_3 +active=yes +op1=Open +retex1s=wall +retex1d=door2 +recol2s=6342 +recol2d=11458 + +[witchaven_north_door] +name=Door +desc=This door is closed by an unknown mechanism. +model=model_loc_3 +active=yes +op1=Open +retex1s=wall +retex1d=door2 +recol2s=6342 +recol2d=11458 + +// These gates were added in rev 194, and removed somewhere between 299 and 306. +// Can't find any footage of how they operated, but are no opened versions available, +// so assuming they close automatically after the player passes through. +[edgeville_dungeon_chronozon_gate_west] +name=Gate +desc=This gate is closed shut. +model=model_loc_52 +active=yes +op1=Open +retex1s=wall +retex1d=door2 +recol2s=6342 +recol2d=11458 +category=double_door_open_and_close_left +param=next_loc_stage,loc_1562 +param=open_sound,grate_open + +[edgeville_dungeon_chronozon_gate_east] +name=Gate +desc=This gate is closed shut. +model=model_loc_52 +active=yes +op1=Open +mirror=yes +retex1s=wall +retex1d=door2 +recol2s=6342 +recol2d=11458 +category=double_door_open_and_close_right +param=next_loc_stage,loc_1563 +param=open_sound,grate_open \ No newline at end of file diff --git a/data/src/scripts/quests/quest_crest/configs/quest_crest.npc b/data/src/scripts/quests/quest_crest/configs/quest_crest.npc new file mode 100644 index 0000000000..84efaf90da --- /dev/null +++ b/data/src/scripts/quests/quest_crest/configs/quest_crest.npc @@ -0,0 +1,63 @@ +[crest_man] +vislevel=hide +name=Man +desc=A well dressed nobleman. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=2340 +recol1d=11627 +recol2s=14724 +recol2d=22226 +recol3s=8386 +recol3d=31649 +recol4s=15360 +recol4d=31649 +recol5s=14801 +recol5d=24075 +model1=model_215_idk +model2=model_281_obj_wear +model3=model_246_idk +model4=model_292_idk +model5=model_151_idk +model6=model_176_idk +model7=model_254_idk +model8=model_181_idk +model9=model_323_obj_wear +head1=model_53_idk_head + +[crest_chronozon] +size=3 +walkanim=demon_walk +readyanim=demon_ready +name=Chronozon +desc=Chronozon the blood demon. +op2=Attack +resizeh=110 +resizev=110 +vislevel=139 +recol1s=29596 +recol1d=18597 +recol2s=15393 +recol2d=18597 +model1=model_2942_npc +wanderrange=6 +maxrange=8 +respawnrate=60 +hitpoints=60 +attack=173 +strength=172 +defence=173 +param=damagetype,^slash_style +param=attack_anim,demon_attack +param=defend_anim,demon_block +param=death_anim,demon_death +param=demonbane_vulnerable,yes +param=attack_sound,black_demon_attack +param=defend_sound,black_demon_hit +param=death_sound,black_demon_death +param=death_drop,ashes +param=combat_xp_multiplier,25 +huntmode=cowardly +huntrange=3 +// Stats match osrs version but our version Vislvl is different. \ No newline at end of file diff --git a/data/src/scripts/quests/quest_crest/configs/quest_crest.obj b/data/src/scripts/quests/quest_crest/configs/quest_crest.obj index c6452baed4..8cdfaa0186 100644 --- a/data/src/scripts/quests/quest_crest/configs/quest_crest.obj +++ b/data/src/scripts/quests/quest_crest/configs/quest_crest.obj @@ -1,4 +1,4 @@ -[obj_773] +[perfect_ring] name='perfect' ring desc=A perfect ruby ring. cost=2025 @@ -15,8 +15,9 @@ iop2=Wear wearpos=ring weight=7g members=yes +tradeable=no -[obj_774] +[perfect_necklace] cost=2175 name='perfect' necklace desc=A perfect ruby necklace. @@ -34,6 +35,7 @@ manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=10g members=yes +tradeable=no [gauntlets_of_cooking] category=category_16 @@ -62,6 +64,7 @@ param=stabdefence,8 param=slashdefence,9 param=crushdefence,7 param=strengthbonus,2 +tradeable=no [gauntlets_of_goldsmithing] category=category_16 @@ -88,8 +91,9 @@ param=stabdefence,8 param=slashdefence,9 param=crushdefence,7 param=strengthbonus,2 +tradeable=no -[obj_777] +[gauntlets_of_chaos] category=category_16 name=Chaos gauntlets desc=These gauntlets empower spell casters. @@ -114,8 +118,9 @@ param=stabdefence,8 param=slashdefence,9 param=crushdefence,7 param=strengthbonus,2 +tradeable=no -[obj_778] +[steel_gauntlets] category=category_16 name=Steel gauntlets desc=My reward for assisting the Fitzharmon family. @@ -140,8 +145,9 @@ param=stabdefence,8 param=slashdefence,9 param=crushdefence,7 param=strengthbonus,2 +tradeable=no -[obj_779] +[crest_part_1] model=model_2688_obj name=Crest part desc=A fragment of the Fitzharmon family crest. @@ -150,8 +156,9 @@ members=yes 2dyan=148 2dxan=356 weight=4lb +tradeable=no -[obj_780] +[crest_part_2] model=model_2691_obj name=Crest part desc=A fragment of the Fitzharmon family crest. @@ -160,8 +167,12 @@ members=yes 2dyan=148 2dxan=356 weight=3lb +tradeable=no -[obj_781] +// This piece is visually identical to part 2. +// 20 July 2004 - The model for Johnathon's part was corrected; previously it used the same model as Caleb's part. +// https://oldschool.runescape.wiki/w/Crest_part#Changes +[crest_part_3] model=model_2691_obj name=Crest part desc=A fragment of the Fitzharmon family crest. @@ -170,8 +181,9 @@ members=yes 2dyan=148 2dxan=356 weight=3lb +tradeable=no -[obj_782] +[family_crest] model=model_2369_obj name=Family crest desc=The Fitzharmon family crest. @@ -180,3 +192,4 @@ members=yes 2dyan=148 2dxan=356 weight=10lb +tradeable=no diff --git a/data/src/scripts/quests/quest_crest/configs/quest_crest.varp b/data/src/scripts/quests/quest_crest/configs/quest_crest.varp index 2a92b4368b..a5c651228b 100644 --- a/data/src/scripts/quests/quest_crest/configs/quest_crest.varp +++ b/data/src/scripts/quests/quest_crest/configs/quest_crest.varp @@ -1,2 +1,5 @@ [crest_progress] +scope=perm + +[crest_spells_levers_gauntlets] scope=perm \ No newline at end of file diff --git a/data/src/scripts/quests/quest_crest/scripts/crest_boot.rs2 b/data/src/scripts/quests/quest_crest/scripts/crest_boot.rs2 new file mode 100644 index 0000000000..7adf47f1c0 --- /dev/null +++ b/data/src/scripts/quests/quest_crest/scripts/crest_boot.rs2 @@ -0,0 +1,29 @@ +[opnpc1,crest_boot] +~chatnpc("Hello tall person."); +if (%crest_progress = ^crest_spoken_avan) { + @multi3( + "Hello. I'm in search of very high quality gold.", crest_boot_gold, + "Hello short person.", crest_boot_hello, + "Why are you called boot?", crest_boot_why + ); +} +else { + @multi2( + "Hello short person.", crest_boot_hello, + "Why are you called boot?", crest_boot_why + ); +} + +[label,crest_boot_gold] +~chatplayer("Hello. I'm in search of very high quality gold."); +~chatnpc("High quality gold eh? Hmmm... Well, the very best quality gold that I know of, is just East of the large city Ardougne, underground somewhere."); +%crest_progress = ^crest_spoken_boot; +~chatnpc("I don't believe it's exactly easy to get to though..."); + +[label,crest_boot_hello] +~chatplayer("Hello short person."); + +[label,crest_boot_why] +~chatplayer("Why are you called Boot?"); +~chatnpc("I'm called Boot, because when I was very young, I used to sleep, in a large boot."); +~chatplayer("Yeah, great, I didn't want your life story."); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_crest/scripts/crest_caleb.rs2 b/data/src/scripts/quests/quest_crest/scripts/crest_caleb.rs2 new file mode 100644 index 0000000000..80481850ba --- /dev/null +++ b/data/src/scripts/quests/quest_crest/scripts/crest_caleb.rs2 @@ -0,0 +1,168 @@ +[opnpc1,crest_caleb] +switch_int(%crest_progress) { + case ^crest_not_started : @crest_caleb_prequest; + case ^crest_spoken_dimintheis : @crest_caleb_start; + case ^crest_spoken_caleb : @crest_caleb_fish; + case ^crest_caleb_piece : @crest_caleb_salad; + case ^crest_caleb_where : @crest_caleb_avan; + case ^crest_complete : @crest_caleb_gauntlets; + case default : @crest_caleb_pieces; +} + +[label,crest_caleb_prequest] +~chatnpc("Who are you? What are you after?"); +@multi2("Nothing, I will be on my way.", crest_caleb_nothing, "I see you are a chef, will you cook me anything?", crest_caleb_chef); + +[label,crest_caleb_start] +~chatnpc("Who are you? What are you after?"); +@multi3("Are you Caleb Fitzharmon?", crest_caleb_areyou, + "Nothing, I will be on my way.", crest_caleb_nothing, + "I see you are a chef, will you cook me anything?", crest_caleb_chef); + +[label,crest_caleb_areyou] +~chatplayer("Are you Caleb Fitzharmon?"); +~chatnpc("Why... yes I am, but I don't believe I know you... how did you know my name?"); +~chatplayer("I have been sent by your father. He wishes the Fitzharmon Crest be restored."); +~chatnpc("Ah... well... hmmm... yes... I do have a piece of it anyway..."); +@multi2("Uh... what happened to the rest of it?", crest_caleb_rest, "So can I have your bit?", crest_caleb_bit); + +[label,crest_caleb_rest] +~chatplayer("Uh... what happened to the rest of it?"); +~chatnpc("Well... my brothers and I had a slight disagreement about it... we all wanted to be heir to my fathers' lands, and we each ended up with a piece of the crest."); +~chatnpc("None of us wanted to give up our rights to our brothers, so we didn't want to give up our pieces of the crest, but none of us wanted to face our father by"); +~chatnpc("returning to him with an incomplete crest... We each went our seperate ways many years past, none of us seeing our father or willing to give up our fragments."); +// If the player doesn't have Caleb's piece yet, the dialogue ends here +// https://youtu.be/e8btuenT4nE?t=167 +if (%crest_progress = ^crest_caleb_piece) { + ~chatplayer("So do you know where I could find any of your brothers?"); + ~chatnpc("Well, we haven't really kept in touch... what with the dispute over the crest and all... I did hear from my brother Avan a while ago though."); + ~chatnpc("He said he was on some kind of search for treasure, or gold, or something out in the desert. You might want to ask around there for him."); + %crest_progress = ^crest_caleb_where; + ~chatnpc("Avan always did have expensive tastes however. You may find he is not prepared to hand over his crest piece to you as easily as I have."); +} + +[label,crest_caleb_bit] +~chatplayer("So can I have your bit?"); +~chatnpc("Well, I am the oldest son, so by the rules of chivalry, I am most entitled to be rightful bearer of the crest."); +~chatplayer("It's not really much use without the other fragments is it though?"); +~chatnpc("Well that is true... perhaps it is time to put my pride aside... I'll tell you what: I'm struggling to complete this fish salad of mine,"); +~chatnpc("so if you will assist me in my search for the ingredients, then I will let you take my piece as reward for your assistance."); +~chatplayer("So what ingredients are you missing?"); +~chatnpc("I require the following cooked fish: Swordfish, Bass, Tuna, Salmon and Shrimp."); +def_int $op = ~p_choice2("Ok, I will get those.", 1, "Why don't you just give me the crest?", 2); +if ($op = 1) { + ~chatplayer("Ok, I will get those."); + ~chatnpc("You will? It would help me a lot!"); + %crest_progress = ^crest_spoken_caleb; +} +else { + ~chatplayer("Why don't you just give me the crest?"); + ~chatnpc("It's a valuable family heirloom. I think the least you can do is prove you're worthy of it before I hand it over."); +} + +[label,crest_caleb_fish] +~chatnpc("How is the fish collecting going?"); +if (inv_total(inv, swordfish) >= 1 & + inv_total(inv, bass) >= 1 & + inv_total(inv, tuna) >= 1 & + inv_total(inv, salmon) >= 1 & + inv_total(inv, shrimps) >= 1) { + ~chatplayer("Got them all with me."); + %crest_progress = ^crest_caleb_piece; + inv_del(inv, swordfish, 1); + inv_del(inv, bass, 1); + inv_del(inv, tuna, 1); + inv_del(inv, salmon, 1); + inv_del(inv, shrimps, 1); + inv_add(inv, crest_part_1, 1); + ~mesbox("You exchange the fish for Caleb's piece of the crest."); + @multi2("Uh... what happened to the rest of it?", crest_caleb_rest, "Thank you very much!", crest_caleb_thanks); + } +else { + ~chatplayer("I didn't manage to get them all yet..."); + ~chatnpc("Remember, I want the following cooked fish: Swordfish, Bass, Tuna, Salmon, and Shrimp."); +} + +[label,crest_caleb_thanks] +~chatplayer("Thank you very much."); +~chatnpc("You're welcome."); + +[label,crest_caleb_salad] +~chatnpc("Hello again. I'm just putting the finishing touches to my masterful salad."); +@multi2("Uh... what happened to the rest of the crest?", crest_caleb_rest, "Good luck with that then.", crest_caleb_luck); + +[label,crest_caleb_luck] +~chatplayer("Good luck with that then."); +~chatnpc("Luck? LUCK? With my cooking skill, I don't really need LUCK."); + +[label,crest_caleb_avan] +~chatplayer("Where did you say I could find Avan again?"); +~chatnpc("Last I heard he was on some stupid treasure hunt out in the desert somewhere. Your best bet is asking around there."); +@crest_caleb_pieces; + +[label,crest_caleb_pieces] +~chatnpc("How are you doing getting the crest pieces?"); +if (inv_total(inv, family_crest) >= 1) { + ~chatplayer("I've got it right here!"); + ~chatnpc("Excellent work! Please take it to my father immediately."); +} +else if (inv_total(inv, crest_part_1) = 0 & inv_total(bank, crest_part_1) = 0) { + @multi2("I am still working on it.", crest_caleb_working, "I have lost the piece you gave me.", crest_caleb_lost); +} +else { + @crest_caleb_working; +} + +[label,crest_caleb_working] +~chatplayer("I am still working on it."); +~chatnpc("Then why are you wasting your time here?"); + +[label,crest_caleb_lost] +~chatplayer("I have lost the piece you gave me..."); +~chatnpc("I have some good news for you then. One of my customers found this on their travels and recognised it as mine and returned it to me here."); +inv_add(inv, crest_part_1, 1); +~mesbox("Caleb hands over his crest piece again."); +~chatnpc("I suggest you be less careless in the future. The crest is extremely valuable, and utterly irreplaceable."); + +[label,crest_caleb_nothing] +~chatplayer("Nothing, I will be on my way."); + +[label,crest_caleb_chef] +~chatplayer("I see you are a chef, will you cook me anything?"); +// "reknown" is verbatim +~chatnpc("I would, but I am very busy. I am trying to increase my reknown as one of the worlds' leading chefs by preparing a special and unique fish salad."); + +[label,crest_caleb_gauntlets] +// Ability to change gauntlets for 25k was added 30/08/05, so this decision is permanent +// https://oldschool.runescape.wiki/w/Update:Garden_Of_Tranquillity +~chatnpc("I hear you brought the completed crest to my father. I must say, that was awfully impressive work."); +if (inv_total(inv, steel_gauntlets) >= 1) { + ~chatplayer("I believe your father mentioned you would be able to improve these gauntlets for me..."); + ~chatnpc("Yes, that is correct. I can slightly alter these gauntlets to allow you some of my skill at preparing seafood by making them cooking gauntlets."); + ~chatnpc("When you wear them you will burn lobsters, sharks and swordfish a lot less. It will be a permanent modification however, so make sure this is what you want."); + def_int $op = ~p_choice2("Yes, please do that for me.", 1, "I'll see what your brothers have to offer first.", 2); + if ($op = 1) { + ~chatplayer("Yes, please do that for me."); + ~mesbox("Caleb takes the gauntlets from you, pours some herbs and seasonings on them, bakes them on his range for a short time, then hands them back to you."); + %crest_spells_levers_gauntlets = setbit(%crest_spells_levers_gauntlets, ^crest_cooking_gauntlets_chosen); + inv_del(inv, steel_gauntlets, 1); + inv_add(inv, gauntlets_of_cooking, 1); + } + else { + ~chatplayer("I'll see what your brothers have to offer first."); + ~chatnpc("As you wish. Let me know if you change your mind."); + } +} +else if (testbit(%crest_spells_levers_gauntlets, ^crest_cooking_gauntlets_chosen) = true) { + if (inv_total(inv, gauntlets_of_cooking) >= 1) { + ~chatplayer("I believe your father mentioned you would be able to improve these gauntlets for me..."); + } + else { + ~chatplayer("I believe your father mentioned you would be able to improve some gauntlets for me..."); + } + ~chatnpc("Your gauntlets have already been treated with my potions."); +} +else { + ~chatplayer("I believe your father mentioned you would be able to improve some gauntlets for me..."); + ~chatnpc("Bring them to me, and I'll see what I can do."); +} diff --git a/data/src/scripts/quests/quest_crest/scripts/crest_chronozon.rs2 b/data/src/scripts/quests/quest_crest/scripts/crest_chronozon.rs2 new file mode 100644 index 0000000000..8b39d2ddec --- /dev/null +++ b/data/src/scripts/quests/quest_crest/scripts/crest_chronozon.rs2 @@ -0,0 +1,42 @@ +[ai_queue3,crest_chronozon] +if (finduid(%npc_attacking_uid) = true) { + if (getbit_range(%crest_spells_levers_gauntlets, ^crest_wind_blast_used, ^crest_fire_blast_used) = ^crest_all_spells_cast) { + gosub(npc_death); + if (npc_findhero = true){ + if (%crest_progress = ^crest_cured_johnathon) { + obj_add(npc_coord, crest_part_3, 1, ^lootdrop_duration); + } + obj_add(npc_coord, npc_param(death_drop), 1, ^lootdrop_duration); + } + } + else { + @crest_chronozon_regenerate; + } +} +else { + npc_statheal(hitpoints, npc_basestat(hitpoints), 0); +} + + +[proc,crest_chronozon_spell](int $spell) +switch_int ($spell) { + case ^wind_blast : + ~crest_chronozon_weaken(^crest_wind_blast_used); + case ^water_blast : + ~crest_chronozon_weaken(^crest_water_blast_used); + case ^earth_blast : + ~crest_chronozon_weaken(^crest_earth_blast_used); + case ^fire_blast : + ~crest_chronozon_weaken(^crest_fire_blast_used); +} + +[proc,crest_chronozon_weaken](int $used) +%crest_spells_levers_gauntlets = setbit(%crest_spells_levers_gauntlets, $used); +// Message is shown multiple times for repeated casts of the same spell +// https://youtu.be/AKFPNpw2ROQ?t=76 +mes("Chronozon weakens..."); + +[label,crest_chronozon_regenerate] +npc_statheal(hitpoints, npc_basestat(hitpoints), 0); +npc_setmode(opplayer2); +mes("Chronozon regenerates..."); diff --git a/data/src/scripts/quests/quest_crest/scripts/crest_dimintheis.rs2 b/data/src/scripts/quests/quest_crest/scripts/crest_dimintheis.rs2 new file mode 100644 index 0000000000..465b9751a7 --- /dev/null +++ b/data/src/scripts/quests/quest_crest/scripts/crest_dimintheis.rs2 @@ -0,0 +1,135 @@ +[opnpc1,crest_dimintheis] +if (%crest_progress = ^crest_complete) { + @crest_dimintheis_gauntlets; +} +else if (%crest_progress = ^crest_spoken_dimintheis) { + ~chatplayer("Where did you say I could find your son Caleb again?"); + ~chatnpc("The only thing I have heard of my son Caleb is that he is trying to earn his fortune as a great chef in the lands beyond White Wolf Mountain."); +} +else if (%crest_progress > ^crest_spoken_caleb) { + if (inv_total(inv, family_crest) >= 1) { + @crest_dimintheis_complete; + } + else { + ~chatnpc("Have you any news on my crest yet?"); + ~chatplayer("I'm still looking for it."); + } +} +else { + ~chatnpc("Hello. My name is Dimintheis, of the noble family Fitzharmon."); + @multi3("Why would a nobleman live in a dump like this?", crest_dimintheis_dump, "You're rich then? Can I have some money?", crest_dimintheis_rich, "Hi, I am a bold adventurer.", crest_dimintheis_adventurer); +} + +[label,crest_dimintheis_dump] +~chatplayer("Why would a nobleman live in a dump like this?"); +~chatnpc("The King has taken my estate from me until such time as I can show my family crest to him."); +@multi2("Why would he do that?", crest_dimintheis_why, "So where is this crest?", crest_dimintheis_where); + +[label,crest_dimintheis_why] +~chatplayer("Why would he do that?"); +@crest_dimintheis_lore; + +[label,crest_dimintheis_lore] +~chatnpc("Well, there is a long standing rule of chivalry amongst the Varrockian aristocracy, where each noble family is in possession of a unique crest, which signifies the honour and lineage of the family. More than this"); +~chatnpc("however, it also represents the lawful rights of each family to prove their ownership of their wealth and lands. If the family crest is lost, then the family's estate is handed over to the current monarch until the crest is"); +~chatnpc("restored."); +~chatnpc("This dates back to the times when there was much in- fighting amongst the noble families and their clans, and was introduced as a way of reducing the bloodshed that was devestating the ranks of the ruling classes at that"); +~chatnpc("time. When you captured a rival family's clan, you also captured their lands and wealth."); +@crest_dimintheis_where; + +[label,crest_dimintheis_where] +~chatplayer("So where is this crest?"); +~chatnpc("Well, my three sons took it with them many years ago when they rode out to fight in the war against the undead necromancer and his army in the battle to save Varrock."); +~chatnpc("For many years I had assumed them all dead, as I had heard no word from them, but recently I heard word that my son Caleb is alive and well, and trying to earn his fortune as a great chef in the lands beyond White"); +~chatnpc("Wolf Mountain, although I know not where."); +@multi2("Ok, I will help you.", crest_dimintheis_accept, "I'm not interested in that adventure right now.", crest_dimintheis_decline); + +[label,crest_dimintheis_accept] +%crest_progress = ^crest_spoken_dimintheis; +~send_quest_progress(questlist:crest, %crest_progress, ^crest_complete); +~chatplayer("Ok, I will help you."); +~chatnpc("I thank you greatly adventurer! Also... if you find Caleb... please... let him know his father still loves him...."); + +[label,crest_dimintheis_decline] +~chatplayer("I'm not interested in that adventure right now."); +~chatnpc("I realise it was a lot to ask of a stranger."); + +[label,crest_dimintheis_rich] +~chatplayer("You're rich then? Can I have some money?"); +~chatnpc("Gah! Lousy Beggar! Your sort is what's ruining this great land! Why don't you just go and get a job if you need the money so badly?"); + +[label,crest_dimintheis_adventurer] +~chatplayer("Hi, I am a bold adventurer."); +~chatnpc("An adventurer hmmm? How lucky. I may have an adventure for you. I desperately need my family crest returning to me. It is of utmost importance."); +@multi3("Why are you so desperate for it?", crest_dimintheis_desperate, "So where is this crest?", crest_dimintheis_where, "I'm not interested in that adventure right now.", crest_dimintheis_decline); + +[label,crest_dimintheis_desperate] +~chatplayer("Why are you so desperate for it?"); +@crest_dimintheis_lore; + +[label,crest_dimintheis_complete] +~chatplayer("I have retrieved your crest."); +~chatnpc("Adventurer... I can only thank you for your kindness, although the words are insufficient to express the gratitude I feel!"); +~chatnpc("You are truly a hero in every sense, and perhaps your efforts can begin to patch the wounds that have torn this family apart..."); +~chatnpc("I know not how I can adequately reward you for your efforts... although I do have these mystical gauntlets, a family heirloom that through some power unknown to me, have always returned to the head of the family"); +~chatnpc("whenever lost, or if the owner has died. I will pledge these to you, and if you should lose them return to me, and they will be here."); +~chatnpc("They can also be granted extra powers. Take them to one of my sons, they should be able to imbue them with a skill for you."); +// Takes all crests and pieces from bank and inventory (based on OSRS wiki and Youtube comments on guide video) +// https://oldschool.runescape.wiki/w/Family_crest_(item) +~del_all_if_exists(inv, family_crest); +~del_all_if_exists(bank, family_crest); +~del_all_if_exists(inv, crest_part_1); +~del_all_if_exists(bank, crest_part_1); +~del_all_if_exists(inv, crest_part_2); +~del_all_if_exists(bank, crest_part_2); +~del_all_if_exists(inv, crest_part_3); +~del_all_if_exists(bank, crest_part_3); +queue(crest_complete, 0); + +[label,crest_dimintheis_gauntlets] +~chatnpc("You have my eternal gratitude adventurer, for all you have done in saving my family's honour. Perhaps some day my sons will overcome their differences."); +if (testbit(%crest_spells_levers_gauntlets, ^crest_cooking_gauntlets_chosen) = true) { + if (~obj_gettotal(gauntlets_of_cooking) = 0) { + @crest_dimintheis_offer_gauntlets(gauntlets_of_cooking); + } +} +else if (testbit(%crest_spells_levers_gauntlets, ^crest_goldsmithing_gauntlets_chosen) = true) { + if (~obj_gettotal(gauntlets_of_goldsmithing) = 0) { + @crest_dimintheis_offer_gauntlets(gauntlets_of_goldsmithing); + } +} +else if (testbit(%crest_spells_levers_gauntlets, ^crest_chaos_gauntlets_chosen) = true) { + if (~obj_gettotal(gauntlets_of_chaos) = 0) { + @crest_dimintheis_offer_gauntlets(gauntlets_of_chaos); + } +} +else if (~obj_gettotal(steel_gauntlets) = 0) { + @crest_dimintheis_offer_gauntlets(steel_gauntlets); +} + +[label,crest_dimintheis_offer_gauntlets](namedobj $gauntlets) +def_string $gauntlets_name = "steel gauntlets"; +switch_obj($gauntlets) { + case gauntlets_of_cooking : + $gauntlets_name = "cooking gauntlets"; + case gauntlets_of_goldsmithing : + $gauntlets_name = "goldsmithing gauntlets"; + case gauntlets_of_chaos : + $gauntlets_name = "chaos gauntlets"; +} +if(inv_freespace(inv) = 0) { + ~chatnpc("Your <$gauntlets_name> returned to me through their magic power recently. Clear some space and you can have them back."); +} +else { + ~chatnpc("Your <$gauntlets_name> returned to me through their magic power recently. Would you like them back?"); + def_int $op = ~p_choice2("Yes please.", 1, "Not right now.", 2); + if ($op = 1) { + ~chatplayer("Yes please."); + inv_add(inv, $gauntlets, 1); + ~chatnpc("Here you go."); + } + else { + ~chatplayer("Not right now."); + ~chatnpc("Well, come back if you change your mind any time. I owe you for your trouble."); + } +} diff --git a/data/src/scripts/quests/quest_crest/scripts/crest_johnathon.rs2 b/data/src/scripts/quests/quest_crest/scripts/crest_johnathon.rs2 new file mode 100644 index 0000000000..57787ac295 --- /dev/null +++ b/data/src/scripts/quests/quest_crest/scripts/crest_johnathon.rs2 @@ -0,0 +1,128 @@ +[opnpc1,crest_johnathon] +if (%crest_progress < ^crest_avan_piece) { + ~chatnpc("I am so very tired... Leave me be... to rest..."); +} +else { + switch_int(%crest_progress) { + case ^crest_avan_piece : @crest_johnathon_intro; + case ^crest_spoken_johnathon : @crest_johnathon_spider; + case ^crest_cured_johnathon : @crest_johnathon_postcure; + case ^crest_complete : @crest_johnathon_gauntlets; + } +} + +[opnpcu,crest_johnathon] +if (oc_param(last_useitem, cures_poison) = true) { + if (%crest_progress >= ^crest_cured_johnathon) { + ~chatnpc("I'm feeling alright now, thanks."); + return; + } + else if (%crest_progress = ^crest_spoken_johnathon) { + inv_del(inv, last_useitem, 1); + %crest_progress = ^crest_cured_johnathon; + @crest_johnathon_cured; + } +} +~displaymessage(^dm_default); + +[label,crest_johnathon_intro] +~chatplayer("Greetings. Would you happen to be Johnathon Fitzharmon?"); +~chatnpc("That... I am..."); +~chatplayer("I am here to retrieve your fragment of the Fitzharmon family crest."); +~chatnpc("The.. poison.. it is all.. too much... My head... will not... stop spinning..."); +%crest_progress = ^crest_spoken_johnathon; +~mesbox("Sweat is pouring down Johnathons' face."); + +[label,crest_johnathon_spider] +~chatnpc("What... what did that spider... DO to me? I... I feel so weak... I can hardly... think at all..."); + +[label,crest_johnathon_cured] +~chatnpc("Ooooh... thank you... Wow! That's completely cured me!"); +~chatnpc("How can I reward you?"); +~chatplayer("I've come here for your piece of the Fitzharmon family crest."); +~chatnpc("You have? Unfortunately I don't have it any more... in my attempts to slay the fiendish Chronozon, the blood demon, I lost a lot of equipment in"); +~chatnpc("our last battle when he bested me and forced me away from his den. He probably still has it now."); +@multi3( + "So is this Chronozon hard to defeat?", crest_johnathon_hard, + "Where can I find Chronozon?", crest_johnathon_where, + "So how did you end up getting poisoned?", crest_johnathon_how); + +[label,crest_johnathon_postcure] +if (inv_total(inv, crest_part_3) >= 1) { + ~chatplayer("I have your piece of the crest!"); + ~chatnpc("Well done! Now return it to my father!"); +} +else { + ~chatplayer("I'm trying to kill this demon Chronozon that you mentioned..."); + @multi3( + "So is this Chronozon hard to defeat?", crest_johnathon_hard, + "Where can I find Chronozon?", crest_johnathon_where, + "Wish me luck.", crest_johnathon_gl); +} + +[label,crest_johnathon_hard] +~chatplayer("So is this Chronozon hard to defeat?"); +~chatnpc("Well... you will have to be a skilled Mage to defeat him, and my powers are not good enough yet. You will need to hit him once with each of the four elemental spells of death"); +~chatnpc("before he will be defeated."); +@multi3( + "Where can I find Chronozon?", crest_johnathon_where, + "So how did you end up getting poisoned?", crest_johnathon_how, + "I will be on my way now.", crest_johnathon_leave); + +[label,crest_johnathon_where] +~chatplayer("Where can I find Chronozon?"); +~chatnpc("The fiend has made his lair in the Wilderness below the Obelisk of Air."); +@multi3( + "So is this Chronozon hard to defeat?", crest_johnathon_hard, + "So how did you end up getting poisoned?", crest_johnathon_how, + "I will be on my way now.", crest_johnathon_leave); + +[label,crest_johnathon_how] +~chatplayer("So how did you end up getting poisoned?"); +~chatnpc("Those accursed poison spiders that surround the entrance to Chronozon's lair... I must have taken a nip from one of them as I attempted to make my escape."); +@multi3( + "So is this Chronozon hard to defeat?", crest_johnathon_hard, + "Where can I find Chronozon?", crest_johnathon_where, + "I will be on my way now.", crest_johnathon_leave); + +[label,crest_johnathon_leave] +~chatplayer("I will be on my way now."); +~chatnpc("My thanks for the assistance adventurer."); + +[label,crest_johnathon_gl] +~chatplayer("Wish me luck."); +~chatnpc("Good luck. You'll need it."); + +[label,crest_johnathon_gauntlets] +~chatnpc("Hello again. My family now considers you a hero."); +if (inv_total(inv, steel_gauntlets) >= 1) { + ~chatplayer("Your father tells me you can improve these gauntlets for me..."); + ~chatnpc("And right he is at that. Although my skill with Death Rune magiks was not great enough to defeat Chronozon, I am adequately skilled at Chaos Rune magiks."); + ~chatnpc("If you give me your gauntlets I will bestow upon them some of my power, and make any bolt spells you wish to cast more effective."); + def_int $op = ~p_choice2("That sounds good to me.", 1, "I shall see what options your brothers can offer me first.", 2); + if ($op = 1) { + ~chatplayer("That sounds good to me!"); + ~mesbox("Johnathon takes your gauntlets from you, and begins a low chant over them. You see them begin to glow and sparkle, before he returns them to you."); + %crest_spells_levers_gauntlets = setbit(%crest_spells_levers_gauntlets, ^crest_chaos_gauntlets_chosen); + inv_del(inv, steel_gauntlets, 1); + inv_add(inv, gauntlets_of_chaos, 1); + } + else { + ~chatplayer("I think I'll check my other options with your brothers before committing myself."); + ~chatnpc("I doubt they will offer anything as useful as my magical boost, but as you wish."); + } +} +else if (testbit(%crest_spells_levers_gauntlets, ^crest_chaos_gauntlets_chosen) = true) { + if (inv_total(inv, gauntlets_of_chaos) >= 1) { + ~chatplayer("Your father tells me you can improve these gauntlets for me..."); + } + else { + ~chatplayer("Your father told me you could improve some gauntlets for me."); + } + ~chatnpc("Your gauntlets are already imbued with my powers."); +} +else { + ~chatplayer("Your father told me you could improve some gauntlets for me."); + ~chatnpc("Bring them to me, and I'll see what I can do."); +} + diff --git a/data/src/scripts/quests/quest_crest/scripts/crest_man.rs2 b/data/src/scripts/quests/quest_crest/scripts/crest_man.rs2 new file mode 100644 index 0000000000..9148117ace --- /dev/null +++ b/data/src/scripts/quests/quest_crest/scripts/crest_man.rs2 @@ -0,0 +1,138 @@ +[opnpc1,crest_man] +if (%crest_progress <= ^crest_caleb_where) { + ~chatnpc("What? Can't you see I'm busy?"); + ~chatplayer("Well, sooooorry..."); +} +else { + switch_int(%crest_progress) { + case ^crest_spoken_gem_trader : @crest_man_intro; + case ^crest_spoken_avan : @crest_man_gold; + case ^crest_spoken_boot : @crest_man_jewelry; + case ^crest_avan_piece : @crest_man_where; + case ^crest_complete : @crest_man_gauntlets; + case default : @crest_man_pieces; + } +} + +[label,crest_man_intro] +@multi2("Why are you hanging around in a scorpion pit?", crest_man_lurking, "I'm looking for a man named Avan Fitzharmon.", crest_man_avan); + +[label,crest_man_lurking] +~chatplayer("Why are you lurking around a scorpion pit?"); +~chatnpc("It's a good place to find gold..."); + +[label,crest_man_avan] +~chatplayer("I'm looking for a man... his name is Avan Fitzharmon."); +~chatnpc("Then you have found him. My name is Avan Fitzharmon."); +~chatplayer("You have a part of your family crest. I am on a quest to retrieve all of the fragmented pieces and restore the crest."); +~chatnpc("Ha! I suppose one of my worthless brothers has sent you on this quest then?"); +~chatplayer("No, it was your father who has asked me to do this for him."); +~chatnpc("My... my father wishes this? Then that is a different matter. I will let you have my crest shard, adventurer, but you must first do something for me."); +~chatnpc("There is a certain lady I am trying to impress. As a man of noble birth, I can not give her just any old trinket to show my devotion. What I intend to give her,"); +~chatnpc("is a golden ring, embedded with the finest precious red stone available, and a necklace to match this ring. The problem however for me, is that"); +~chatnpc("not just any old gold will be suitable. I seek only the purest, the most high quality of gold - what I seek, if you will, is perfect gold."); +~chatnpc("None of the gold around here is even remotely suitable in terms of quality. I have searched far and wide for the perfect gold I desire, but have had no success so"); +~chatnpc("in finding it I am afraid. If you can find me my perfect gold, make a ring and necklace from it, and add rubies to them, I will"); +~chatnpc("gladly hand over my fragment of the family crest to you."); +~chatplayer("Can you give me any help on finding this 'perfect gold'?"); +~chatnpc("I thought I had found a solid lead on its whereabouts when I heard of a dwarf who is an expert on gold who goes by the name of 'Boot'."); +~chatnpc("Unfortunately he has apparently returned to his home, somewhere in the mountains, and I have no idea how to find him."); +// In OSRS, "Man" (385) is replaced with "Avan" (386) here. +// We don't have another NPC to swap to in this revision (crest_man + 1 is crest_dimintheis). +%crest_progress = ^crest_spoken_avan; +~chatplayer("Well, I'll see what I can do."); + +[label,crest_man_gold] +~chatnpc("So how are you doing getting me my perfect gold jewelry?"); +~chatplayer("I'm still after that 'perfect gold'."); +~chatnpc("I know how you feel... for such a long time I have searched and searched for the elusive perfect gold... I thought I had gotten a good lead on finding it"); +~chatnpc("when I heard talk of a dwarven expert on gold named Boot some time back, but unfortunately for me, he has returned to his mountain home, which I cannot find."); + +[label,crest_man_jewelry] +~chatnpc("So how are you doing making me my perfect gold jewelry?"); +if (inv_total(inv, perfect_ring) >= 1 & inv_total(inv, perfect_necklace) >= 1) { + ~chatplayer("I have the ring and necklace right here."); + ~mesbox("You hand Avan the perfect gold ring and necklace."); + %crest_progress = ^crest_avan_piece; + inv_del(inv, perfect_ring, 1); + inv_del(inv, perfect_necklace, 1); + inv_add(inv, crest_part_2, 1); + ~chatnpc("These... these are exquisite! EXACTLY what I was searching for all of this time! Please, take my crest fragment!"); + ~chatnpc("Now, I suppose you will be wanting to find my brother Johnathon who is in possession of the final piece of the family's crest?"); + ~chatplayer("That's correct."); + @crest_man_johnathon; +} +else { + ~chatplayer("I have spoken to Boot the dwarf about the location of 'perfect gold' but haven't managed to make you your jewelry yet."); + ~chatnpc("Well, I won't entrust you with my piece of the crest until you have brought me a necklace of perfect gold with a red precious stone, and a perfect gold ring to match."); +} + +[label,crest_man_where] +// Second crest piece is not reobtainable until after Johnathon's section +~chatplayer("Where did you say I could find your brother Johnathon again?"); +@crest_man_johnathon; + +[label,crest_man_johnathon] +~chatnpc("Well, the last I heard of my brother Johnathon, he was studying the magical arts, and trying to hunt some demon or other out in The Wilderness."); +~chatnpc("Unsurprisingly, I do not believe he is doing a particularly good job of things, and spends most of his time recovering from his injuries in"); +~chatnpc("some tavern or other near the edge of The Wilderness. You'll probably find him still there."); +~chatplayer("Thanks Avan."); + +[label,crest_man_pieces] +~chatnpc("Greetings again, adventurer. How are you doing on retrieving the crest pieces?"); +if (inv_total(inv, family_crest) >= 1) { + ~chatplayer("I have assembled all of the pieces!"); + ~chatnpc("Very well done adventurer! Now please return it to my father!"); +} +else if (inv_total(inv, crest_part_2) = 0 & inv_total(bank, crest_part_2) = 0) { + @multi2("I am still working on it.", crest_man_working, "I have lost the fragment you gave me.", crest_man_lost); +} +else { + @crest_man_working; +} + +[label,crest_man_working] +~chatplayer("I am still working on it."); +~chatnpc("I hope you succeed for my father's sake."); + +[label,crest_man_lost] +~chatplayer("I have lost the piece you gave me..."); +~chatnpc("I have a confession myself adventurer... I did not fully trust you with the actual part of my family's crest before, and gave you a worthless replica before..."); +~chatnpc("In hindsight, it seems I was right. I will give you the real piece now, but PLEASE try not to lose it; it is a priceless family heirloom."); +inv_add(inv, crest_part_2, 1); + +[label,crest_man_gauntlets] +~chatnpc("I have received word from my father of your assistance to our family in this matter. You have my thanks for restoring our honour."); +if (inv_total(inv, steel_gauntlets) >= 1) { + ~chatplayer("Your father mentioned that you could improve these gauntlets in some way for me..."); + ~chatnpc("Indeed I can. In my long time searching for the 'perfect' gold I learned a lot about gold items. I can improve these gauntlets so that they provide more than normal."); + ~chatnpc("experience when smithing gold. I can easily modify these for you."); + def_int $op = ~p_choice2("That sounds good, improve them for me.", 1, "I think I'll check my other options with your brothers.", 2); + if ($op = 1) { + ~chatplayer("That sounds good, improve them for me."); + ~mesbox("Avan takes your gauntlets, takes out a small hammer, and pounds them into a slightly new shape, then hands them back to you."); + %crest_spells_levers_gauntlets = setbit(%crest_spells_levers_gauntlets, ^crest_goldsmithing_gauntlets_chosen); + inv_del(inv, steel_gauntlets, 1); + inv_add(inv, gauntlets_of_goldsmithing, 1); + } + else { + ~chatplayer("I think I'll check my other options with your brothers before committing myself."); + ~chatnpc("If you feel you really must consort with the likes of them. I await your decision."); + } +} +else if (testbit(%crest_spells_levers_gauntlets, ^crest_goldsmithing_gauntlets_chosen) = true) { + // Guess - unsure on dialogue structure before ability to change gauntlets + if (inv_total(inv, gauntlets_of_goldsmithing) >= 1) { + ~chatplayer("Your father mentioned that you could improve these gauntlets in some way for me..."); + } + else { + ~chatplayer("Your father mentioned that you could improve some gauntlets for me."); + } + ~chatnpc("Your gauntlets have already been forged by me."); +} +else { + // https://chisel.weirdgloop.org/dialogue/content/39108 + ~chatplayer("Your father mentioned that you could improve some gauntlets for me."); + ~chatnpc("Bring them to me, and I'll see what I can do."); +} + diff --git a/data/src/scripts/quests/quest_crest/scripts/quest_crest.rs2 b/data/src/scripts/quests/quest_crest/scripts/quest_crest.rs2 new file mode 100644 index 0000000000..c2f9ba0715 --- /dev/null +++ b/data/src/scripts/quests/quest_crest/scripts/quest_crest.rs2 @@ -0,0 +1,123 @@ +// RSC https://www.youtube.com/watch?v=BqHt6DrmIiY +// RS 2006 (fight + finish) https://www.youtube.com/watch?v=AKFPNpw2ROQ +// RS 2008 (full) https://www.youtube.com/watch?v=RFff1NoOGDo + +[queue,crest_complete] +%crest_progress = ^crest_complete; +inv_add(inv, steel_gauntlets, 1); +~send_quest_complete(questlist:crest, steel_gauntlets, 250, ^squire_questpoints, "You have completed the\\nFamily Crest Quest!"); + +[oploc1,witchaven_north_room_lever_down] +~crest_toggle_lever(coord, witchaven_north_room_lever_up, ^crest_north_room_lever, true); + +[oploc1,witchaven_north_room_lever_up] +~crest_toggle_lever(coord, witchaven_north_room_lever_down, ^crest_north_room_lever, false); + +[oploc1,witchaven_north_lever_down] +~crest_toggle_lever(coord, witchaven_north_lever_up, ^crest_north_lever, true); + +[oploc1,witchaven_north_lever_up] +~crest_toggle_lever(coord, witchaven_north_lever_down, ^crest_north_lever, false); + +[oploc1,witchaven_south_lever_down] +~crest_toggle_lever(coord, witchaven_south_lever_up, ^crest_south_lever, true); + +[oploc1,witchaven_south_lever_up] +~crest_toggle_lever(coord, witchaven_south_lever_down, ^crest_south_lever, false); + +[proc,crest_toggle_lever](coord $coord, loc $new_loc, int $lever, boolean $up) { + facesquare(movecoord($coord, 0, 1, 0)); + anim(human_leverdown, 0); + sound_synth(lever, 0, 0); + // Tested on OSRS, levers revert to original state after 5 mins + loc_change($new_loc, 300); + if ($up = true) { + %crest_spells_levers_gauntlets = setbit(%crest_spells_levers_gauntlets, $lever); + mes("The lever is now up."); + } + else { + %crest_spells_levers_gauntlets = clearbit(%crest_spells_levers_gauntlets, $lever); + mes("The lever is now down."); + } +} + +// Opens if north lever is down and south lever is up +[oploc1,witchaven_north_door] +if (testbit(%crest_spells_levers_gauntlets, ^crest_north_lever) = false & + testbit(%crest_spells_levers_gauntlets, ^crest_south_lever) = true) { + ~open_and_close_door(witchaven_door_open, ~check_axis(coord, loc_coord, loc_angle), false); +} +else { + mes("This door is locked."); +} + +// Opens if north lever is up and south lever is up +[oploc1,witchaven_south_west_door] +if (testbit(%crest_spells_levers_gauntlets, ^crest_north_lever) = true & + testbit(%crest_spells_levers_gauntlets, ^crest_south_lever) = true) { + ~open_and_close_door(witchaven_door_open, ~check_axis(coord, loc_coord, loc_angle), false); +} +else { + mes("This door is locked."); +} + +// Opens if north lever is up and south lever is down +[oploc1,witchaven_south_east_door] +if (testbit(%crest_spells_levers_gauntlets, ^crest_north_lever) = true & + testbit(%crest_spells_levers_gauntlets, ^crest_south_lever) = false) { + ~open_and_close_door(witchaven_door_open, ~check_axis(coord, loc_coord, loc_angle), false); +} +else { + mes("This door is locked."); +} + +// Opens if north lever is up, south lever is down, and the north room lever is up +[oploc1,witchaven_goldmine_door] +if (testbit(%crest_spells_levers_gauntlets, ^crest_north_lever) = true & + testbit(%crest_spells_levers_gauntlets, ^crest_south_lever) = false & + testbit(%crest_spells_levers_gauntlets, ^crest_north_room_lever) = true) { + ~open_and_close_door(witchaven_door_open, ~check_axis(coord, loc_coord, loc_angle), false); +} +else { + mes("This door is locked."); +} + +[opheldu,crest_part_1] +if (last_useitem = crest_part_2 | last_useitem = crest_part_3) { + @combine_crest_parts; +} else { + ~displaymessage(^dm_default); +} + +[opheldu,crest_part_2] +if (last_useitem = crest_part_1 | last_useitem = crest_part_3) { + @combine_crest_parts; +} else { + ~displaymessage(^dm_default); +} + +[opheldu,crest_part_3] +if (last_useitem = crest_part_1 | last_useitem = crest_part_2) { + @combine_crest_parts; +} else { + ~displaymessage(^dm_default); +} + +[label,combine_crest_parts] +if (inv_total(inv, crest_part_1) > 0 & inv_total(inv, crest_part_2) > 0 & inv_total(inv, crest_part_3) > 0) { + inv_del(inv, crest_part_1, 1); + inv_del(inv, crest_part_2, 1); + inv_del(inv, crest_part_3, 1); + inv_add(inv, family_crest, 1); + mes("You have restored the Family Crest."); +} else { + mes("You still need one more piece of the crest."); +} + +[opheld5,steel_gauntlets] @drop_gauntlets; +[opheld5,gauntlets_of_cooking] @drop_gauntlets; +[opheld5,gauntlets_of_goldsmithing] @drop_gauntlets; +[opheld5,gauntlets_of_chaos] @drop_gauntlets; + +[label,drop_gauntlets] +inv_delslot(inv, last_slot); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_demon/configs/demon.npc b/data/src/scripts/quests/quest_demon/configs/demon.npc index 81e7154e61..6910dc0f05 100644 --- a/data/src/scripts/quests/quest_demon/configs/demon.npc +++ b/data/src/scripts/quests/quest_demon/configs/demon.npc @@ -11,11 +11,11 @@ wanderrange=2 maxrange=4 // TODO respawnrate? hitpoints=7 -attack=11 -strength=10 -defence=5 -// TODO attackstyle +attack=32 +strength=25 +defence=27 param=attackrate,6 +// TODO attackstyle param=attack_anim,demon_attack param=defend_anim,demon_block param=death_anim,demon_death @@ -25,6 +25,8 @@ param=defend_sound,demon_hit param=death_sound,demon_death param=death_drop,ashes timer=100 +// TODO monster examine spell +// osrs stats and Vislvl match 1:1 [weakened_delrith] size=2 diff --git a/data/src/scripts/quests/quest_demon/configs/demon.obj b/data/src/scripts/quests/quest_demon/configs/demon.obj index 5072f0c9e7..52010db59d 100644 --- a/data/src/scripts/quests/quest_demon/configs/demon.obj +++ b/data/src/scripts/quests/quest_demon/configs/demon.obj @@ -10,6 +10,7 @@ recol1d=22197 2dyan=20 2dxan=328 weight=1kg +tradeable=no [demon_rovin_key] name=Key @@ -23,6 +24,7 @@ recol1d=22197 2dyan=20 2dxan=328 weight=1kg +tradeable=no [demon_prysin_key] name=Key @@ -36,6 +38,7 @@ recol1d=22197 2dyan=20 2dxan=328 weight=1kg +tradeable=no [silverlight] name=Silverlight @@ -68,4 +71,5 @@ param=slashattack_anim,human_sword_slash param=stabattack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=slash_sound,hacksword_slash -param=stab_sound,hacksword_stab \ No newline at end of file +param=stab_sound,hacksword_stab +tradeable=no diff --git a/data/src/scripts/quests/quest_dragon/configs/quest_dragon.npc b/data/src/scripts/quests/quest_dragon/configs/quest_dragon.npc index fa45aed8c9..2918191d4e 100644 --- a/data/src/scripts/quests/quest_dragon/configs/quest_dragon.npc +++ b/data/src/scripts/quests/quest_dragon/configs/quest_dragon.npc @@ -23,7 +23,7 @@ param=slashdefence,40 param=crushdefence,40 param=magicdefence,30 param=rangedefence,20 -param=damagetype,1 +param=damagetype,^slash_style param=attack_anim,dragon_attack param=defend_anim,dragon_block param=death_anim,dragon_death @@ -36,6 +36,8 @@ huntmode=elvarg_hunt attackrange=8 maxrange=7 huntrange=7 +// all the stats information matches otherwise osrs but we only have 120hp +// instead of 80 hp. and osrs Vislvl is also 83 while we have 86 again. [dragonslayer_ned] vislevel=hide @@ -82,7 +84,7 @@ hitpoints=10 attack=6 strength=5 defence=2 -param=damagetype,0 +param=damagetype,^stab_style param=attack_anim,giantrat_attack param=defend_anim,giantrat_block param=death_anim,giantrat_death @@ -91,6 +93,7 @@ param=defend_sound,rat_hit param=death_sound,rat_death huntmode=cowardly huntrange=1 +// stats and information taken from normal 6lv Giant rat // Vislvl match 1:1 [melzar_maze_ghost] name=Ghost @@ -116,7 +119,7 @@ param=slashdefence,5 param=crushdefence,5 param=magicdefence,-5 param=rangedefence,5 -param=damagetype,2 +param=damagetype,^crush_style param=attack_anim,ghost_attack param=defend_anim,ghost_block param=death_anim,ghost_death @@ -126,6 +129,7 @@ param=death_sound,ghost_death param=death_drop,null huntmode=cowardly huntrange=1 +// osrs stats and Vislvl match 1:1 [melzar_maze_skeleton] name=Skeleton @@ -139,15 +143,18 @@ model2=model_2946_npc wanderrange=9 maxrange=11 respawnrate=70 -hitpoints=24 -attack=17 -strength=17 -defence=17 -param=stabdefence,5 -param=slashdefence,5 -param=crushdefence,-5 -param=rangedefence,5 -param=damagetype,2 +hitpoints=17 +attack=24 +strength=24 +defence=24 +param=attackbonus,15 +param=strengthbonus,14 +param=stabdefence,9 +param=slashdefence,11 +param=crushdefence,-2 +param=magicdefence,1 +param=rangedefence,4 +param=damagetype,^slash_style param=attack_anim,skeleton_attack param=defend_anim,skeleton_block param=death_anim,skeleton_death @@ -156,6 +163,7 @@ param=defend_sound,skelly_hit param=death_sound,skeleton_death huntmode=cowardly huntrange=1 +// stats and information taken from a normal 25lv skeleton // Vislvl match 1:1 [melzar_maze_zombie] name=Zombie @@ -168,9 +176,19 @@ model1=model_2931_npc model2=model_2932_npc wanderrange=9 maxrange=11 -// https://web.archive.org/web/20051105211000/http://www.tip.it/runescape/index.php?rs2monster_id=151 +// TODO respawntime hitpoints=30 -// TODO +attack=19 +strength=21 +defence=21 +param=attackbonus,5 +param=strengthbonus,7 +param=stabdefence,10 +param=slashdefence,8 +param=crushdefence,12 +param=magicdefence,10 +param=rangedefence,10 +param=damagetype,^slash_style param=attack_anim,zombie_attack param=defend_anim,zombie_block param=death_anim,zombie_death @@ -179,6 +197,8 @@ param=defend_sound,zombie_hit param=death_sound,zombie_death huntmode=cowardly huntrange=1 +// https://web.archive.org/web/20051105211000/http://www.tip.it/runescape/index.php?rs2monster_id=151 +// stats taken zombie_entrana // Vislvl match 1:1 [melzar_maze_lesser_demon] size=2 @@ -197,7 +217,7 @@ attack=68 strength=70 defence=71 param=magicdefence,-10 -param=damagetype,1 +param=damagetype,^slash_style param=attack_anim,demon_attack param=defend_anim,demon_block param=death_anim,demon_death @@ -208,6 +228,7 @@ param=death_sound,demon_death param=death_drop,ashes huntmode=cowardly huntrange=2 +// osrs stats and Vislvl match 1:1 [melzar] name=Melzar the mad @@ -229,20 +250,20 @@ model4=model_292_idk model5=model_170_idk model6=model_176_idk model7=model_265_obj_wear +wanderrange=2 +attackrange=8 respawnrate=60 hitpoints=44 attack=37 strength=37 defence=34 magic=40 -param=damagetype,2 +param=damagetype,^crush_style param=attack_anim,human_unarmedkick param=attack_sound,unarmed_kick -// osrs -attackrange=8 -maxrange=8 huntmode=aggressive_melee huntrange=1 +// osrs stats and Vislvl match 1:1 [cabin_boy_jenkins] vislevel=hide diff --git a/data/src/scripts/quests/quest_dragon/configs/quest_dragon.obj b/data/src/scripts/quests/quest_dragon/configs/quest_dragon.obj index 21edbf04c0..fe010595c8 100644 --- a/data/src/scripts/quests/quest_dragon/configs/quest_dragon.obj +++ b/data/src/scripts/quests/quest_dragon/configs/quest_dragon.obj @@ -9,6 +9,7 @@ model=model_2686_obj 2dxan=368 iop1=Study weight=5g +tradeable=no [crandor_map_part2] name=Map part @@ -21,6 +22,7 @@ model=model_2689_obj 2dxan=420 iop1=Study weight=5g +tradeable=no [crandor_map_part3] name=Map part @@ -33,6 +35,7 @@ model=model_2692_obj 2dxan=336 iop1=Study weight=5g +tradeable=no [crandor_map] name=Crandor map @@ -44,6 +47,7 @@ model=model_2497_obj 2dxan=312 iop1=Study weight=15g +tradeable=no [nails] name=Nails @@ -58,6 +62,7 @@ stackable=yes 2dxan=308 weight=5g category=category_74 +tradeable=no [maze_key] name=Maze key @@ -72,6 +77,7 @@ recol1d=15855 2dyan=20 2dxan=328 weight=10g +tradeable=no [maze_key_red] name=Key @@ -85,6 +91,7 @@ recol1d=30753 2dyan=20 2dxan=328 weight=10g +tradeable=no [maze_key_orange] name=Key @@ -98,6 +105,7 @@ recol1d=31201 2dyan=20 2dxan=328 weight=10g +tradeable=no [maze_key_yellow] name=Key @@ -111,6 +119,7 @@ recol1d=31649 2dyan=20 2dxan=328 weight=10g +tradeable=no [maze_key_blue] name=Key @@ -124,6 +133,7 @@ recol1d=31 2dyan=20 2dxan=328 weight=10g +tradeable=no [maze_key_magenta] name=Key @@ -137,6 +147,7 @@ recol1d=30781 2dyan=20 2dxan=328 weight=10g +tradeable=no [maze_key_green] name=Key @@ -149,4 +160,5 @@ recol1d=2626 2dzoom=700 2dyan=20 2dxan=328 -weight=10g \ No newline at end of file +weight=10g +tradeable=no diff --git a/data/src/scripts/quests/quest_druid/configs/quest_druid.obj b/data/src/scripts/quests/quest_druid/configs/quest_druid.obj index 6081c47e11..eb17ac957e 100644 --- a/data/src/scripts/quests/quest_druid/configs/quest_druid.obj +++ b/data/src/scripts/quests/quest_druid/configs/quest_druid.obj @@ -14,6 +14,7 @@ recol2d=21151 2dxan=308 cost=1 weight=500g +tradeable=no [druid_enchanted_rat] name=Enchanted rat @@ -31,6 +32,7 @@ recol2d=21151 2dxan=308 cost=1 weight=200g +tradeable=no [druid_enchanted_bear] name=Enchanted bear @@ -48,6 +50,7 @@ recol2d=21151 2dxan=308 cost=1 weight=500g +tradeable=no [druid_enchanted_chicken] name=Enchanted chicken @@ -64,3 +67,4 @@ recol2d=20095 2dxan=88 cost=1 weight=300g +tradeable=no diff --git a/data/src/scripts/quests/quest_drunkmonk/configs/quest_drunkmonk.obj b/data/src/scripts/quests/quest_drunkmonk/configs/quest_drunkmonk.obj index a71d443706..5c07cb1161 100644 --- a/data/src/scripts/quests/quest_drunkmonk/configs/quest_drunkmonk.obj +++ b/data/src/scripts/quests/quest_drunkmonk/configs/quest_drunkmonk.obj @@ -8,4 +8,5 @@ model=model_2725_obj members=yes cost=5 weight=2lb -respawnrate=50 \ No newline at end of file +respawnrate=50 +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/book.obj b/data/src/scripts/quests/quest_elena/configs/book.obj index 871b9a8414..dc64f7af73 100644 --- a/data/src/scripts/quests/quest_elena/configs/book.obj +++ b/data/src/scripts/quests/quest_elena/configs/book.obj @@ -8,3 +8,4 @@ model=model_2794_obj weight=18oz name=Book desc=Turnip growing for beginners. +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/gasmask.obj b/data/src/scripts/quests/quest_elena/configs/gasmask.obj index 809adbf522..99ed0cd56a 100644 --- a/data/src/scripts/quests/quest_elena/configs/gasmask.obj +++ b/data/src/scripts/quests/quest_elena/configs/gasmask.obj @@ -18,3 +18,4 @@ womanwear=model_389_obj_wear,0 manhead=model_51_obj_wear womanhead=model_112_obj_wear weight=9oz +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/hangover_cure.obj b/data/src/scripts/quests/quest_elena/configs/hangover_cure.obj index b81153364b..d1a77e6a91 100644 --- a/data/src/scripts/quests/quest_elena/configs/hangover_cure.obj +++ b/data/src/scripts/quests/quest_elena/configs/hangover_cure.obj @@ -11,3 +11,4 @@ recol1d=16047 weight=2200g name=Hangover cure desc=It doesn't look very tasty. +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/key.obj b/data/src/scripts/quests/quest_elena/configs/key.obj index 679f5103e5..d91762dad4 100644 --- a/data/src/scripts/quests/quest_elena/configs/key.obj +++ b/data/src/scripts/quests/quest_elena/configs/key.obj @@ -10,3 +10,4 @@ model=model_2372_obj weight=10g name=A small key desc=Quite a small key. +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/note.obj b/data/src/scripts/quests/quest_elena/configs/note.obj index 09e0e04063..f01bad4617 100644 --- a/data/src/scripts/quests/quest_elena/configs/note.obj +++ b/data/src/scripts/quests/quest_elena/configs/note.obj @@ -11,3 +11,4 @@ weight=10g name=A scruffy note desc=It seems to say "hongorer lure"... iop1=Read +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/picture.obj b/data/src/scripts/quests/quest_elena/configs/picture.obj index 5788528437..38d594dd49 100644 --- a/data/src/scripts/quests/quest_elena/configs/picture.obj +++ b/data/src/scripts/quests/quest_elena/configs/picture.obj @@ -11,3 +11,4 @@ weight=1lb name=Picture desc=A picture of a lady called Elena. respawnrate=5 +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/teleportscroll.obj b/data/src/scripts/quests/quest_elena/configs/teleportscroll.obj index b86dd8237f..a172645ec4 100644 --- a/data/src/scripts/quests/quest_elena/configs/teleportscroll.obj +++ b/data/src/scripts/quests/quest_elena/configs/teleportscroll.obj @@ -11,3 +11,4 @@ name=A magic scroll desc=Maybe I should read it... iop1=Read weight=20g +tradeable=no diff --git a/data/src/scripts/quests/quest_elena/configs/warrant.obj b/data/src/scripts/quests/quest_elena/configs/warrant.obj index b8466658b1..0a4a3120b3 100644 --- a/data/src/scripts/quests/quest_elena/configs/warrant.obj +++ b/data/src/scripts/quests/quest_elena/configs/warrant.obj @@ -10,3 +10,4 @@ model=model_2675_obj weight=10g name=Warrant desc=A search warrant for a house in Ardougne. +tradeable=no diff --git a/data/src/scripts/quests/quest_fishingcompo/configs/quest_fishingcompo.obj b/data/src/scripts/quests/quest_fishingcompo/configs/quest_fishingcompo.obj index 0ce714f84d..ba7416d317 100644 --- a/data/src/scripts/quests/quest_fishingcompo/configs/quest_fishingcompo.obj +++ b/data/src/scripts/quests/quest_fishingcompo/configs/quest_fishingcompo.obj @@ -13,6 +13,7 @@ stackable=yes 2dxan=340 2dxan=404 weight=10g +tradeable=no [fishing_trophy] name=Fishing trophy @@ -24,6 +25,7 @@ members=yes 2dyan=124 2dxan=104 weight=3oz +tradeable=no [fishing_pass] name=Fishing pass @@ -36,3 +38,4 @@ members=yes 2dyan=120 2dxan=380 weight=6g +tradeable=no diff --git a/data/src/scripts/quests/quest_fluffs/configs/quest_fluffs.obj b/data/src/scripts/quests/quest_fluffs/configs/quest_fluffs.obj index f1e26546f7..3c2f5276f4 100644 --- a/data/src/scripts/quests/quest_fluffs/configs/quest_fluffs.obj +++ b/data/src/scripts/quests/quest_fluffs/configs/quest_fluffs.obj @@ -13,7 +13,6 @@ members=yes 2dyan=1588 2dxan=376 weight=7g -tradeable=yes [seasoned_sardine] name=Seasoned sardine @@ -32,7 +31,6 @@ members=yes 2dzan=1964 2dxan=320 weight=120g -tradeable=yes [cat_training_medal] cost=350 @@ -49,7 +47,6 @@ wearpos=front manwear=model_289_obj_wear,0 womanwear=model_453_obj_wear,0 weight=10g -tradeable=yes [fluffs_kitten] name=Fluffs' kitten @@ -65,6 +62,7 @@ weight=750g category=category_81 members=yes op1=Use +tradeable=no [kitten_greyblack] name=Pet kitten @@ -80,6 +78,7 @@ members=yes weight=750g category=kitten param=follower_id,follower_kitten_greyblack +tradeable=no //https://chisel.weirdgloop.org/structs_rs3/index.html?type=items&id=1555 [kitten_white] @@ -104,6 +103,7 @@ members=yes weight=750g category=kitten param=follower_id,follower_kitten_white +tradeable=no [kitten_brown] name=Pet kitten @@ -125,6 +125,7 @@ members=yes weight=750g category=kitten param=follower_id,follower_kitten_brown +tradeable=no [kitten_black] name=Pet kitten @@ -146,6 +147,7 @@ members=yes weight=750g category=kitten param=follower_id,follower_kitten_black +tradeable=no [kitten_greybrown] name=Pet kitten @@ -167,6 +169,7 @@ members=yes weight=750g category=kitten param=follower_id,follower_kitten_greybrown +tradeable=no [kitten_greyblue] name=Pet kitten @@ -188,6 +191,7 @@ members=yes weight=750g category=kitten param=follower_id,follower_kitten_greyblue +tradeable=no [cat_greyblack] name=Pet cat @@ -203,6 +207,7 @@ members=yes weight=1500g category=cat param=follower_id,follower_cat_greyblack +tradeable=no [cat_white] name=Pet cat @@ -226,6 +231,7 @@ members=yes weight=1500g category=cat param=follower_id,follower_cat_white +tradeable=no [cat_brown] name=Pet cat @@ -247,6 +253,7 @@ members=yes weight=1500g category=cat param=follower_id,follower_cat_brown +tradeable=no [cat_black] name=Pet cat @@ -268,6 +275,7 @@ members=yes weight=1500g category=cat param=follower_id,follower_cat_black +tradeable=no [cat_greybrown] name=Pet cat @@ -289,6 +297,7 @@ members=yes weight=1500g category=cat param=follower_id,follower_cat_greybrown +tradeable=no [cat_greyblue] name=Pet cat @@ -310,6 +319,7 @@ members=yes weight=1500g category=cat param=follower_id,follower_cat_greyblue +tradeable=no [overgrown_greyblack] name=Pet cat @@ -325,6 +335,7 @@ members=yes weight=2500g category=overgrown param=follower_id,follower_overgrown_greyblack +tradeable=no [overgrown_white] name=Pet cat @@ -348,6 +359,7 @@ members=yes weight=2500g category=overgrown param=follower_id,follower_overgrown_white +tradeable=no [overgrown_brown] name=Pet cat @@ -369,6 +381,7 @@ members=yes weight=2500g category=overgrown param=follower_id,follower_overgrown_brown +tradeable=no [overgrown_black] name=Pet cat @@ -390,6 +403,7 @@ members=yes weight=2500g category=overgrown param=follower_id,follower_overgrown_black +tradeable=no [overgrown_greybrown] name=Pet cat @@ -411,6 +425,7 @@ members=yes weight=2500g category=overgrown param=follower_id,follower_overgrown_greybrown +tradeable=no [overgrown_greyblue] name=Pet cat @@ -431,4 +446,5 @@ recol3d=11627 members=yes weight=2500g category=overgrown -param=follower_id,follower_overgrown_greyblue \ No newline at end of file +param=follower_id,follower_overgrown_greyblue +tradeable=no diff --git a/data/src/scripts/quests/quest_gobdip/configs/quest_gobdip.obj b/data/src/scripts/quests/quest_gobdip/configs/quest_gobdip.obj index 963190ae2d..fcffb8352e 100644 --- a/data/src/scripts/quests/quest_gobdip/configs/quest_gobdip.obj +++ b/data/src/scripts/quests/quest_gobdip/configs/quest_gobdip.obj @@ -10,6 +10,7 @@ cost=40 2dxan=608 weight=8lb category=category_528 +tradeable=no [goblin_mail_blue] name=Blue goblin mail @@ -23,6 +24,7 @@ cost=40 2dxan=608 weight=8lb category=category_528 +tradeable=no [goblin_mail] name=Goblin mail @@ -34,4 +36,3 @@ cost=40 2dxan=608 weight=8lb category=category_528 -tradeable=yes diff --git a/data/src/scripts/quests/quest_grail/configs/fisher_realm.npc b/data/src/scripts/quests/quest_grail/configs/fisher_realm.npc index fab98d69c1..8cc96a8a20 100644 --- a/data/src/scripts/quests/quest_grail/configs/fisher_realm.npc +++ b/data/src/scripts/quests/quest_grail/configs/fisher_realm.npc @@ -296,6 +296,7 @@ hitpoints=142 attack=91 strength=100 defence=91 +param=attackrate,7 param=attackbonus,27 param=strengthbonus,22 param=stabdefence,18 @@ -303,11 +304,11 @@ param=slashdefence,27 param=crushdefence,18 param=magicdefence,1000 param=rangedefence,1000 -param=attackrate,7 param=damagetype,^crush_style param=attack_anim,giant_attack param=defend_anim,giant_block param=death_anim,giant_death // param=defend_sound,blade5 // this npc uses human_unarmedpunch and human_death sound for attack and death animations. -// although npc are classified as Giant based on appearance/animations. \ No newline at end of file +// although npc are classified as Giant based on appearance/animations. +// Stats match osrs version but our version Vislvl is different. \ No newline at end of file diff --git a/data/src/scripts/quests/quest_grail/configs/quest_grail.obj b/data/src/scripts/quests/quest_grail/configs/quest_grail.obj index a1dc6c74d0..9e42c02fe6 100644 --- a/data/src/scripts/quests/quest_grail/configs/quest_grail.obj +++ b/data/src/scripts/quests/quest_grail/configs/quest_grail.obj @@ -10,6 +10,7 @@ model=model_2443_obj 2dyan=1932 2dxan=440 weight=1oz +tradeable=no [magic_whistle] name=Magic whistle @@ -23,6 +24,7 @@ model=model_2433_obj 2dxan=152 iop1=Blow weight=5g +tradeable=no [grail_bell] name=Grail bell @@ -38,6 +40,7 @@ recol1d=26425 2dxan=1132 iop1=Ring weight=1oz +tradeable=no [magic_gold_feather] name=Magic gold feather @@ -54,6 +57,7 @@ recol1d=25353 2dxan=428 iop1=Blow-on weight=5g +tradeable=no [holy_grail] name=Holy grail @@ -65,3 +69,4 @@ model=model_2623_obj 2dyan=2044 2dxan=116 weight=3oz +tradeable=no diff --git a/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.npc b/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.npc index 4cee9bd54b..bdd19a4d88 100644 --- a/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.npc +++ b/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.npc @@ -121,11 +121,13 @@ hitpoints=20 attack=20 strength=20 defence=20 +magic=0 +ranged=0 param=slashdefence,1 param=crushdefence,1 param=damagetype,^crush_style // trivia npc sounds - https://oldschool.runescape.wiki/w/Foreman -// osrs +// Stats match osrs version but our version Vislvl is different. [grandtree_shipyard_worker] name=Shipyard worker @@ -150,7 +152,16 @@ model7=model_185_obj_wear head1=model_53_idk_head head2=model_79_idk_head wanderrange=2 +// respawntime= +hitpoints=10 +attack=10 +strength=10 +defence=10 +magic=0 +ranged=0 +param=damagetype,^crush_style category=shipyard_worker +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1430 [femi] name=Femi @@ -207,4 +218,5 @@ param=defend_sound,black_demon_hit param=death_sound,black_demon_death param=death_drop,ashes category=black_demon -timer=20 \ No newline at end of file +timer=20 +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.obj b/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.obj index e8d5d2d6f1..baf2bbdfad 100644 --- a/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.obj +++ b/data/src/scripts/quests/quest_grandtree/configs/quest_grandtree.obj @@ -12,6 +12,7 @@ recol1d=6240 2dyan=76 2dxan=264 weight=15g +tradeable=no [translation_book] name=Translation book @@ -32,6 +33,7 @@ recol3d=7329 2dxan=244 iop1=Read weight=18oz +tradeable=no [gloughs_journal] name=Glough's journal @@ -50,6 +52,7 @@ recol2d=27635 2dxan=276 iop1=Read weight=18oz +tradeable=no [hazelmeres_scroll] name=Hazelmere's scroll @@ -64,6 +67,7 @@ model=model_2600_obj 2dxan=380 iop1=Read weight=20g +tradeable=no [lumber_order] name=Lumber order @@ -78,6 +82,7 @@ model=model_2600_obj 2dxan=380 iop1=Read weight=20g +tradeable=no [gloughs_key] name=Glough's key @@ -90,6 +95,7 @@ model=model_2372_obj 2dyan=20 2dxan=328 weight=10g +tradeable=no [twigs_t] name=Twigs @@ -102,6 +108,7 @@ members=yes 2dyan=88 2dxan=440 weight=20g +tradeable=no [twigs_u] name=Twigs @@ -114,6 +121,7 @@ members=yes 2dyan=2036 2dxan=364 weight=20g +tradeable=no [twigs_z] name=Twigs @@ -124,6 +132,7 @@ members=yes 2dyan=48 2dxan=420 weight=20g +tradeable=no [twigs_o] name=Twigs @@ -135,6 +144,7 @@ members=yes 2dzoom=1500 2dxan=452 weight=20g +tradeable=no [daconia_rock] model=model_2394_obj @@ -148,6 +158,7 @@ desc=An ancient rock with strange magical properties. 2dxan=144 weight=2lb members=yes +tradeable=no [invasion_plans] name=Invasion plans @@ -162,3 +173,4 @@ model=model_2600_obj 2dxan=380 iop1=Read weight=20g +tradeable=no diff --git a/data/src/scripts/quests/quest_haunted/configs/quest_haunted.obj b/data/src/scripts/quests/quest_haunted/configs/quest_haunted.obj index 7f0ba3143d..eafe5f05e8 100644 --- a/data/src/scripts/quests/quest_haunted/configs/quest_haunted.obj +++ b/data/src/scripts/quests/quest_haunted/configs/quest_haunted.obj @@ -7,6 +7,7 @@ model=model_2681_obj 2dyan=1232 2dxan=392 weight=2oz +tradeable=no [fish_food] name=Fish food @@ -18,7 +19,6 @@ model=model_2815_obj 2dyan=1904 2dxan=112 weight=1oz -tradeable=yes [poison] name=Poison @@ -30,7 +30,6 @@ model=model_2714_obj 2dyan=1828 2dxan=132 weight=20g -tradeable=yes [poisoned_fish_good] name=Poisoned fish food @@ -42,6 +41,7 @@ model=model_2815_obj 2dyan=1904 2dxan=112 weight=30g +tradeable=no [key_haunted] name=Key @@ -53,6 +53,7 @@ model=model_2372_obj 2dyan=20 2dxan=328 weight=10g +tradeable=no [rubber_tube] cost=3 @@ -64,6 +65,7 @@ model=model_2463_obj 2dyan=76 2dxan=312 weight=1oz +tradeable=no [oil_can] name=Oil can @@ -76,3 +78,4 @@ model=model_2466_obj 2dyan=1480 2dxan=180 weight=1oz +tradeable=no diff --git a/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.npc b/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.npc index 4702a88d20..21cfc9847c 100644 --- a/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.npc +++ b/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.npc @@ -197,6 +197,7 @@ param=defend_anim,human_sword_defend2 // TODO: param=attack_sound, // https://www.youtube.com/watch?v=ZYPB823IyRk&t=395s // https://www.youtube.com/watch?v=Tm1r7zi4oUY +// TODO monster examine spell [hazeel] vislevel=296 @@ -272,6 +273,7 @@ param=attack_anim,human_stafforb_pound param=defend_anim,human_stafforb_def param=attack_sound,staff_hit // TODO get real animation ids and sound osrs +// TODO monster examine spell // https://www.youtube.com/watch?v=R5MdMtqvxaM&t=418s [hazeel_cultist] @@ -311,5 +313,6 @@ param=crushdefence,8 param=attack_anim,human_staff_pound param=defend_anim,human_staff_def param=attack_sound,staff_hit -// TODO try to get information about the wanderrange/maxrange. +// TODO try to get information about the wanderrange/maxrange +// TODO monster examine spell // https://www.youtube.com/watch?v=tYXi3dBooB4 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.obj b/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.obj index a3945c5f0a..9faebbc718 100644 --- a/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.obj +++ b/data/src/scripts/quests/quest_hazeelcult/configs/quest_hazeelcult.obj @@ -10,6 +10,7 @@ members=yes 2dxan=380 weight=10g param=no_alchemy,1 +tradeable=no [hazeelcult_key] name=Key @@ -23,6 +24,7 @@ model=model_2372_obj 2dxan=328 weight=10g param=no_alchemy,1 +tradeable=no [carnillean_armour] name=Carnillean armour @@ -51,6 +53,7 @@ category=armour_body param=stabdefence,20 param=slashdefence,14 param=crushdefence,8 +tradeable=no [mark_of_hazeel] name=Mark of hazeel @@ -66,4 +69,5 @@ iop2=Wear wearpos=front manwear=model_286_obj_wear,0 womanwear=model_450_obj_wear,0 -weight=12g \ No newline at end of file +weight=12g +tradeable=no diff --git a/data/src/scripts/quests/quest_hero/configs/quest_hero.npc b/data/src/scripts/quests/quest_hero/configs/quest_hero.npc index b712def559..e0be3cb853 100644 --- a/data/src/scripts/quests/quest_hero/configs/quest_hero.npc +++ b/data/src/scripts/quests/quest_hero/configs/quest_hero.npc @@ -27,6 +27,11 @@ model7=model_185_obj_wear model8=model_176_idk head1=model_53_idk_head head2=model_82_idk_head +hitpoints=12 +attack=5 +strength=8 +defence=6 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4916 [trobert] vislevel=hide @@ -57,6 +62,11 @@ model9=model_290_obj_wear model10=model_518_obj_wear model11=model_326_idk head1=model_67_idk_head +hitpoints=13 +attack=4 +strength=3 +defence=5 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4917 [entrana_firebird] name=Entrana Fire Bird @@ -84,6 +94,7 @@ param=death_anim,firebird_death param=attack_sound,terrorbird_attack param=defend_sound,terrorbird_hit param=death_sound,terrorbird_death +// osrs stats and Vislvl match 1:1 [garv] vislevel=hide @@ -108,6 +119,16 @@ model7=model_246_idk model8=model_550_obj_wear head1=model_57_obj_wear wanderrange=1 +hitpoints=104 +attack=95 +defence=91 +strength=94 +param=damagetype,^slash_style +param=attack_anim,human_baxe_slash +param=defend_anim,human_baxe_defend2 +param=attack_sound,baxe_slash +// param=defend_sound, +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4915 [grip] name=Grip @@ -145,8 +166,9 @@ param=damagetype,^slash_style param=attack_anim,human_baxe_slash param=defend_anim,human_baxe_defend2 param=attack_sound,baxe_slash +// param=defend_sound, param=death_drop,grips_keyring -// TODO defend sounds +// Stats match osrs version but our version Vislvl is different. [charlie_the_cook] vislevel=hide @@ -172,3 +194,9 @@ model8=model_249_idk head1=model_67_idk_head head2=model_81_idk_head head3=model_41_obj_wear +hitpoints=3 +attack=10 +strength=10 +defence=10 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_4921 + diff --git a/data/src/scripts/quests/quest_hero/configs/quest_hero.obj b/data/src/scripts/quests/quest_hero/configs/quest_hero.obj index 24e33335c1..8917280c87 100644 --- a/data/src/scripts/quests/quest_hero/configs/quest_hero.obj +++ b/data/src/scripts/quests/quest_hero/configs/quest_hero.obj @@ -11,6 +11,7 @@ recol1d=22945 2dyan=20 2dxan=328 weight=25g +tradeable=no [id_papers] name=Id papers @@ -23,6 +24,7 @@ members=yes 2dyan=120 2dxan=380 weight=10g +tradeable=no [miscellaneous_key] name=Miscellaneous key @@ -37,7 +39,6 @@ recol1d=22945 2dxan=328 weight=10g members=yes -tradeable=yes [thieves_armband] name=Thieves' armband @@ -51,6 +52,7 @@ model=model_2820_obj 2dxan=296 weight=25g members=yes +tradeable=no [petes_candlestick] name=Pete's candlestick @@ -63,7 +65,6 @@ model=model_2505_obj 2dxan=184 weight=500g members=yes -tradeable=yes [fire_feather] name=Fire feather @@ -78,4 +79,5 @@ recol1d=31041 2dyan=692 2dxan=428 weight=2g -members=yes \ No newline at end of file +members=yes +tradeable=no diff --git a/data/src/scripts/quests/quest_hetty/configs/quest_hetty.obj b/data/src/scripts/quests/quest_hetty/configs/quest_hetty.obj index 4e54995dd9..2d70dfb1ef 100644 --- a/data/src/scripts/quests/quest_hetty/configs/quest_hetty.obj +++ b/data/src/scripts/quests/quest_hetty/configs/quest_hetty.obj @@ -8,4 +8,5 @@ model=model_2751_obj 2dzoom=590 2dyan=168 2dxan=340 -weight=3g \ No newline at end of file +weight=3g +tradeable=no diff --git a/data/src/scripts/quests/quest_hunt/configs/quest_hunt.obj b/data/src/scripts/quests/quest_hunt/configs/quest_hunt.obj index c29f77c79b..ea2f943346 100644 --- a/data/src/scripts/quests/quest_hunt/configs/quest_hunt.obj +++ b/data/src/scripts/quests/quest_hunt/configs/quest_hunt.obj @@ -8,6 +8,7 @@ cost=30 weight=2lb name=Karamjan rum desc=A very strong spirit brewed in Karamja. +tradeable=no [hunt_chest_key] model=model_2372_obj @@ -20,6 +21,7 @@ cost=1 weight=10g name=Chest key desc=A key to One eyed Hector's chest. +tradeable=no [pirate_message] model=model_2600_obj @@ -33,3 +35,4 @@ cost=1 weight=20g name=Pirate message desc=Pirates don't have the best handwriting... +tradeable=no diff --git a/data/src/scripts/quests/quest_ikov/configs/quest_ikov.npc b/data/src/scripts/quests/quest_ikov/configs/quest_ikov.npc index 47f06ff405..1e92f683cb 100644 --- a/data/src/scripts/quests/quest_ikov/configs/quest_ikov.npc +++ b/data/src/scripts/quests/quest_ikov/configs/quest_ikov.npc @@ -41,6 +41,8 @@ param=attack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=attack_sound,hacksword_stab // I used Thug npc sound and animation data with this npc +// TODO monster examine spell +// if these stats are correct then they match 1:1 with Vislvl [lucien_ardougne] name=Lucien @@ -121,6 +123,7 @@ param=defend_anim,human_sword_defend2 param=attack_sound,stabsword_slash category=guardian_of_armadyl // TODO param=defend_sound,steel2 +// Stats match osrs version but our version Vislvl is different. [guardian_of_armadyl_female] name=Guardian of Armadyl @@ -173,6 +176,7 @@ param=attack_sound,stabsword_slash // param=defend_sound,steel2 param=death_sound,female_death category=guardian_of_armadyl +// Stats match osrs version but our version Vislvl is different. [winelda] name=Winelda @@ -242,6 +246,7 @@ hitpoints=59 attack=78 strength=78 defence=78 +magic=62 param=attackbonus,-12 param=stabdefence,34 param=slashdefence,37 @@ -250,4 +255,7 @@ param=magicdefence,-7 param=rangedefence,35 param=attack_sound,giant_attack param=defend_sound,giant_hit -param=death_sound,giant_death \ No newline at end of file +param=death_sound,giant_death +// TODO monster examine spell +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_3448 +// Vislvl not match with osrs \ No newline at end of file diff --git a/data/src/scripts/quests/quest_ikov/configs/quest_ikov.obj b/data/src/scripts/quests/quest_ikov/configs/quest_ikov.obj index a94a6eab44..c00f5ad94d 100644 --- a/data/src/scripts/quests/quest_ikov/configs/quest_ikov.obj +++ b/data/src/scripts/quests/quest_ikov/configs/quest_ikov.obj @@ -32,6 +32,7 @@ param=rangebonus,16 param=levelrequire,40 param=proj_launch,ice_arrow_launch param=proj_travel,ice_arrow_travel +tradeable=no [ice_arrow_4] stackable=yes @@ -124,6 +125,7 @@ model=model_2615_obj 2dyan=1704 2dxan=264 weight=2oz +tradeable=no [staff_of_armadyl] name=Staff of armadyl @@ -139,6 +141,7 @@ recol1d=21933 2dyan=1400 2dxan=148 weight=4lb +tradeable=no [shiny_key] name=Shiny key @@ -152,6 +155,7 @@ model=model_2372_obj 2dyan=20 2dxan=328 weight=10g +tradeable=no [pendant_of_lucien] name=Pendant of lucien @@ -171,6 +175,7 @@ cost=12 2dxan=224 iop2=Wear weight=10g +tradeable=no [armadyl_pendant] name=Armadyl pendant @@ -190,6 +195,7 @@ womanwear=model_446_obj_wear,0 2dxan=224 iop2=Wear weight=10g +tradeable=no [boots_of_lightness_inv] wearpos=feet @@ -212,6 +218,7 @@ weight=12oz param=stabdefence,1 param=slashdefence,1 param=crushdefence,1 +tradeable=no [boots_of_lightness_worn] wearpos=feet @@ -234,3 +241,4 @@ weight=-10lb param=stabdefence,1 param=slashdefence,1 param=crushdefence,1 +tradeable=no diff --git a/data/src/scripts/quests/quest_ikov/scripts/quest_ikov.rs2 b/data/src/scripts/quests/quest_ikov/scripts/quest_ikov.rs2 index 65f739eff2..0ca72eb750 100644 --- a/data/src/scripts/quests/quest_ikov/scripts/quest_ikov.rs2 +++ b/data/src/scripts/quests/quest_ikov/scripts/quest_ikov.rs2 @@ -67,6 +67,7 @@ if (npc_finduid($npc) = true) { [queue,ikov_lucien_quest_complete] %ikov_progress = ^ikov_completed_lucien; +inv_del(inv, staff_of_armadyl, 1); stat_advance(ranged, 105000); stat_advance(fletching, 80000); ~send_quest_complete(questlist:ikov, yew_longbow, 250, ^ikov_questpoints, "You have completed the\\nTemple of Ikov Quest for Lucien!"); diff --git a/data/src/scripts/quests/quest_imp/configs/quest_imp.obj b/data/src/scripts/quests/quest_imp/configs/quest_imp.obj index 2e6b074ae7..0cd10115eb 100644 --- a/data/src/scripts/quests/quest_imp/configs/quest_imp.obj +++ b/data/src/scripts/quests/quest_imp/configs/quest_imp.obj @@ -9,7 +9,6 @@ recol1d=30753 2dyan=68 2dxan=68 weight=3g -tradeable=yes [imp_yellow_bead] cost=4 @@ -22,7 +21,6 @@ recol1d=31649 2dyan=68 2dxan=68 weight=3g -tradeable=yes [imp_black_bead] cost=4 @@ -35,7 +33,6 @@ recol1d=0 2dyan=68 2dxan=68 weight=3g -tradeable=yes [imp_white_bead] cost=4 @@ -46,4 +43,3 @@ model=model_2456_obj 2dyan=68 2dxan=68 weight=3g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/configs/quest_itexam.constant b/data/src/scripts/quests/quest_itexam/configs/quest_itexam.constant new file mode 100644 index 0000000000..61d67204ae --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/configs/quest_itexam.constant @@ -0,0 +1,28 @@ +^itexam_questpoints = 2 + +^itexam_stamping = 1 +^itexam_first_exam = 2 +^itexam_second_exam = 3 +^itexam_third_exam = 4 +^itexam_impress_archeological_expert = 5 +^itexam_mineshaft_permit = 6 +^itexam_poured_compound_on_bricks = 7 +^itexam_removed_blockage = 8 +^itexam_complete = 9 + +^itexam_errands_offset = 4 + +^itexam_errand_student1 = 0 +^itexam_errand_student2 = 1 +^itexam_errand_student3 = 2 + +^itexam_bits_offset = 12 + +^itexam_bit_panning_guide_tea_given = 1 +^itexam_bit_winch_rope_attached = 2 +^itexam_bit_private_winch_rope_attached = 3 +^itexam_bit_barrel_open = 4 +^itexam_bit_stone_tablet_taken = 5 +^itexam_bit_searched_bricks = 6 +^itexam_bit_shown_ancient_symbol = 7 +^itexam_bit_stamped_letter = 9 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/configs/quest_itexam.npc b/data/src/scripts/quests/quest_itexam/configs/quest_itexam.npc new file mode 100644 index 0000000000..59fdda6176 --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/configs/quest_itexam.npc @@ -0,0 +1,189 @@ +[digsite_workman] +vislevel=hide +name=Digsite workman +desc=This person is working on the site. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +op3=Steal-from +recol1s=14801 +recol1d=8320 +recol2s=32735 +recol2d=8320 +model1=model_235_idk +model2=model_246_idk +model3=model_302_npc +model4=model_173_npc +model5=model_179_obj_wear +model6=model_274_idk +model7=model_181_idk +model8=model_185_obj_wear +head1=model_67_idk_head + +[digsite_workman_cave] +vislevel=hide +name=Digsite workman +desc=This person is working on the site. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +op3=Steal-from +recol1s=14801 +recol1d=8320 +recol2s=32735 +recol2d=8320 +model1=model_235_idk +model2=model_246_idk +model3=model_302_npc +model4=model_173_npc +model5=model_179_obj_wear +model6=model_274_idk +model7=model_181_idk +model8=model_185_obj_wear +head1=model_67_idk_head + +[student1] +vislevel=hide +name=Student +desc=A student busily digging. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=14724 +recol1d=5636 +recol2s=2340 +recol2d=23171 +model1=model_217_idk +model2=model_249_idk +model3=model_292_idk +model4=model_324_idk +model5=model_151_idk +model6=model_179_obj_wear +model7=model_254_idk +model8=model_185_obj_wear +head1=model_55_idk_head +head2=model_81_idk_head + +[student2] +vislevel=hide +name=Student +desc=A student busily digging. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=24075 +recol1d=14594 +recol2s=14724 +recol2d=23937 +recol3s=2340 +recol3d=3171 +recol4s=24329 +recol4d=3171 +model1=model_215_idk +model2=model_246_idk +model3=model_292_idk +model4=model_322_idk +model5=model_163_idk +model6=model_179_obj_wear +model7=model_257_npc +model8=model_276_npc +head1=model_53_idk_head + +[student3] +vislevel=hide +name=Student +desc=A student busily digging. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=6273 +recol1d=24205 +recol2s=14724 +recol2d=20952 +recol3s=2340 +recol3d=7400 +model1=model_390_idk +model2=model_456_idk +model3=model_447_obj_wear +model4=model_332_idk +model5=model_356_obj_wear +model6=model_429_idk +model7=model_185_obj_wear +head1=model_113_idk_head +param=death_sound,female_death + +[examiner] +vislevel=hide +name=Examiner +desc=Upon examining the examiner you examine it is indeed an examiner! +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=6273 +recol1d=21921 +recol2s=14724 +recol2d=7311 +recol3s=2340 +recol3d=3171 +model1=model_378_idk +model2=model_418_npc +model3=model_470_idk +model4=model_421_idk +model5=model_358_idk +model6=model_348_idk +model7=model_353_idk +head1=model_103_idk_head +head2=model_137_npc_head +param=death_sound,female_death + + + +[archaeological_expert] +vislevel=hide +name=Archaeological expert +desc=An expert on archaeology. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=2340 +recol1d=22627 +recol2s=14801 +recol2d=11457 +recol3s=14724 +recol3d=16912 +recol4s=24075 +recol4d=11457 +model1=model_217_idk +model2=model_250_idk +model3=model_299_npc +model4=model_327_idk +model5=model_159_npc +model6=model_254_idk +model7=model_179_obj_wear +model8=model_185_obj_wear +head1=model_55_idk_head +head2=model_82_idk_head + +[panning_guide] +vislevel=hide +name=Panning guide +desc=A specialist in panning for gold. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_ready +op1=Talk-to +recol1s=7298 +recol1d=3171 +recol2s=2340 +recol2d=11459 +recol3s=14724 +recol3d=14596 +model1=model_215_idk +model2=model_246_idk +model3=model_292_idk +model4=model_170_idk +model5=model_179_obj_wear +model6=model_254_idk +model7=model_276_npc +model8=model_185_obj_wear +model9=model_326_idk +head1=model_53_idk_head \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/configs/quest_itexam.obj b/data/src/scripts/quests/quest_itexam/configs/quest_itexam.obj index 150fafad59..523870b552 100644 --- a/data/src/scripts/quests/quest_itexam/configs/quest_itexam.obj +++ b/data/src/scripts/quests/quest_itexam/configs/quest_itexam.obj @@ -7,6 +7,7 @@ model=model_2371_obj 2dxan=96 weight=2oz members=yes +tradeable=no [specimen_brush] name=Specimen brush @@ -19,8 +20,9 @@ model=model_2385_obj 2dxan=272 weight=2oz members=yes +tradeable=no -[obj_671] +[rock_sample_1] model=model_2393_obj 2dxof=8 2dyof=-15 @@ -31,8 +33,9 @@ weight=3oz name=Rock sample 1 desc=A carefully kept safe rock sample. members=yes +tradeable=no -[obj_672] +[rock_sample_2] model=model_2394_obj name=Rock sample 2 desc=A carefully kept safe rock sample. @@ -42,8 +45,9 @@ desc=A carefully kept safe rock sample. 2dxan=144 weight=3oz members=yes +tradeable=no -[obj_673] +[rock_sample_3] model=model_2396_obj name=Rock sample 3 desc=A carefully kept safe rock sample. @@ -54,8 +58,9 @@ desc=A carefully kept safe rock sample. 2dxan=104 weight=3oz members=yes +tradeable=no -[obj_674] +[cracked_rock_sample] model=model_2393_obj 2dxof=8 2dyof=-37 @@ -66,6 +71,7 @@ weight=3oz name=Rock sample desc=A rough shaped piece of rock. members=yes +tradeable=no [rock_pick] name=Rock pick @@ -78,6 +84,7 @@ model=model_2792_obj 2dxan=476 weight=2oz members=yes +tradeable=no [trowel] name=Trowel @@ -90,8 +97,9 @@ model=model_2630_obj 2dxan=312 weight=2oz members=yes +tradeable=no -[obj_677] +[panning_tray_empty] name=Panning tray desc=An empty tray for panning. model=model_2577_obj @@ -102,8 +110,9 @@ model=model_2577_obj weight=3oz members=yes iop2=Search +tradeable=no -[obj_678] +[panning_tray_gold] name=Panning tray desc=This tray contains gold. model=model_2513_obj @@ -114,8 +123,9 @@ model=model_2513_obj weight=5oz members=yes iop2=Search +tradeable=no -[obj_679] +[panning_tray_mud] name=Panning tray desc=This tray contains mud. model=model_2452_obj @@ -126,8 +136,9 @@ model=model_2452_obj weight=6oz members=yes iop2=Search +tradeable=no -[obj_680] +[nuggets] name=Nuggets desc=Pure, lovely gold! model=model_2812_obj @@ -138,6 +149,7 @@ model=model_2812_obj weight=4oz members=yes stackable=yes +tradeable=no [talisman_of_zaros] name=Talisman of zaros @@ -150,8 +162,9 @@ model=model_2449_obj 2dxan=324 weight=3oz members=yes +tradeable=no -[obj_682] +[unstamped_letter] model=model_2600_obj name=Unstamped letter desc=A scroll waiting to be stamped. @@ -162,8 +175,9 @@ desc=A scroll waiting to be stamped. 2dxan=380 weight=20g members=yes +tradeable=no -[obj_683] +[stamped_letter] model=model_2675_obj name=Stamped letter desc=A stamped scroll of recommendation. @@ -174,8 +188,9 @@ desc=A stamped scroll of recommendation. 2dxan=380 weight=20g members=yes +tradeable=no -[obj_684] +[belt_buckle] model=model_2516_obj name=Belt buckle desc=Used to hold up trousers! @@ -187,6 +202,7 @@ desc=Used to hold up trousers! 2dxan=524 weight=1kg members=yes +tradeable=no [old_boot] name=Old boot @@ -199,6 +215,7 @@ model=model_2683_obj 2dxan=168 weight=2oz members=yes +tradeable=no [rusty_sword] name=Rusty sword @@ -210,6 +227,7 @@ model=model_2608_obj 2dxan=652 weight=5lb members=yes +tradeable=no [broken_arrow] name=Broken arrow @@ -222,6 +240,7 @@ model=model_2512_obj 2dxan=168 weight=15g members=yes +tradeable=no [buttons] name=Buttons @@ -234,6 +253,7 @@ model=model_2549_obj 2dxan=236 weight=1g members=yes +tradeable=no [broken_staff] model=model_2459_obj @@ -246,6 +266,7 @@ desc=I pity the poor person beaten with this! 2dxan=192 weight=4lb members=yes +tradeable=no [broken_glass] name=Broken glass @@ -259,8 +280,9 @@ model=model_2676_obj weight=20g category=category_15 members=yes +tradeable=no -[obj_691] +[level_1_certificate] model=model_2600_obj name=Level 1 certificate desc=The owner has passed earth sciences level 1 exam. @@ -271,8 +293,9 @@ desc=The owner has passed earth sciences level 1 exam. 2dxan=380 weight=20g members=yes +tradeable=no -[obj_692] +[level_2_certificate] model=model_2600_obj name=Level 2 certificate desc=The owner has passed earth sciences level 2 exam. @@ -283,8 +306,9 @@ desc=The owner has passed earth sciences level 2 exam. 2dxan=380 weight=20g members=yes +tradeable=no -[obj_693] +[level_3_certificate] model=model_2600_obj name=Level 3 certificate desc=The owner has passed earth sciences level 3 exam. @@ -295,8 +319,9 @@ desc=The owner has passed earth sciences level 3 exam. 2dxan=380 weight=20g members=yes +tradeable=no -[obj_694] +[ceramic_remains] name=Ceramic remains desc=Smashing! model=model_2493_obj @@ -309,6 +334,7 @@ recol2d=5248 2dxan=168 weight=2oz members=yes +tradeable=no [old_tooth] name=Old tooth @@ -321,8 +347,9 @@ model=model_2522_obj 2dxan=292 weight=1g members=yes +tradeable=no -[obj_696] +[invitation_letter] model=model_2600_obj name=Invitation letter desc=A letter inviting me to use the private digshafts. @@ -334,6 +361,7 @@ desc=A letter inviting me to use the private digshafts. members=yes iop2=Read weight=20g +tradeable=no [damaged_armour] name=Damaged armour @@ -348,8 +376,9 @@ recol1d=8420 2dxan=292 weight=17lb members=yes +tradeable=no -[obj_698] +[broken_armour] name=Broken armour desc=No use to me... model=model_loc_826_0 @@ -362,8 +391,9 @@ recol1d=8420 2dxan=496 weight=17lb members=yes +tradeable=no -[obj_699] +[stone_tablet] name=Stone tablet desc=An old stone slab with writing on it. model=model_2627_obj @@ -374,8 +404,9 @@ model=model_2627_obj members=yes iop2=Read weight=800g +tradeable=no -[obj_700] +[chemical_powder] name=Chemical powder desc=An acrid chemical. model=model_2742_obj @@ -387,8 +418,9 @@ members=yes 2dyan=2008 2dxan=136 weight=1oz +tradeable=no -[obj_701] +[ammonium_nitrate] name=Ammonium nitrate desc=An acrid chemical. model=model_2742_obj @@ -400,8 +432,9 @@ members=yes 2dyan=1892 2dxan=264 weight=15g +tradeable=no -[obj_702] +[unidentified_liquid] name=Unidentified liquid desc=A strong chemical. model=model_2789_obj @@ -413,8 +446,9 @@ recol1d=31201 2dxan=84 weight=25g members=yes +tradeable=no -[obj_703] +[nitroglycerin] name=Nitroglycerin desc=A strong chemical. model=model_2789_obj @@ -426,8 +460,9 @@ recol1d=31201 2dxan=84 weight=25g members=yes +tradeable=no -[obj_704] +[ground_charcoal] name=Ground charcoal desc=Charcoal, crushed to small pieces! model=model_2742_obj @@ -439,8 +474,9 @@ members=yes 2dyan=1892 2dxan=264 weight=8g +tradeable=no -[obj_705] +[mixed_chemicals1] name=Mixed chemicals desc=A mixture of strong chemicals. model=model_2789_obj @@ -452,8 +488,9 @@ recol1d=20929 2dxan=84 weight=30g members=yes +tradeable=no -[obj_706] +[mixed_chemicals2] name=Mixed chemicals desc=A mixture of strong chemicals. model=model_2789_obj @@ -465,8 +502,9 @@ recol1d=16577 2dxan=84 weight=35g members=yes +tradeable=no -[obj_707] +[chemical_compound] name=Chemical compound desc=A mixture of strong chemicals. model=model_2789_obj @@ -478,6 +516,7 @@ recol1d=3171 2dxan=84 weight=35g members=yes +tradeable=no [arcenia_root] name=Arcenia root @@ -490,8 +529,9 @@ model=model_2629_obj 2dxan=456 weight=10g members=yes +tradeable=no -[obj_709] +[digsite_chest_key] name=Chest key desc=This fits a chest. model=model_2372_obj @@ -502,8 +542,9 @@ model=model_2372_obj 2dxan=328 weight=10g members=yes +tradeable=no -[obj_710] +[digsite_vase] name=Vase desc=A vessel for holding plants. model=model_2704_obj @@ -515,8 +556,9 @@ recol1d=13605 2dxan=68 weight=500g members=yes +tradeable=no -[obj_711] +[book_on_chemicals] name=Book on chemicals desc=It's about chemicals, judging from its' cover. model=model_2543_obj @@ -534,6 +576,7 @@ recol3d=3268 members=yes iop2=Read weight=18oz +tradeable=no [obj_712] name=Cup of tea @@ -547,5 +590,7 @@ model=model_2468_obj 2dxan=156 weight=150g members=yes +tradeable=no [obj_713] +tradeable=no diff --git a/data/src/scripts/quests/quest_itexam/scripts/arcaeological_expert.rs2 b/data/src/scripts/quests/quest_itexam/scripts/arcaeological_expert.rs2 new file mode 100644 index 0000000000..2c84b469e9 --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/arcaeological_expert.rs2 @@ -0,0 +1,198 @@ +[opnpc1,archaeological_expert] +def_int $progress = ~itexam_progress; + +if ($progress = ^itexam_complete) { + @archaeological_expert_quest_complete; +} else if ($progress < ^itexam_mineshaft_permit) { + ~chatplayer("Hello. Who are you?"); + ~chatnpc("Good day to you. My name is Terry Balando; I am an expert on digsite finds."); + ~chatnpc("I am employed by the museum in Varrock to oversee all finds at this digsite. Anything you find must be reported to me."); + ~chatplayer("Oh, ok. If I find anything of interest I will bring it here."); + ~chatnpc("Can I help you at all?"); +} else { + ~chatnpc("Hello there, !"); + ~chatnpc("Can I help you at all?"); +} + +if (~itexam_testbit(^itexam_bit_shown_ancient_symbol) = true & inv_total(inv, invitation_letter) = 0) { + // It is intentional that, even after using the invitation letter, you can get another from terry (confirmed on OSRS) + @multi5("I have something I need checking out.", archaeological_expert_checkout, "No thanks.", archaeological_expert_no_thanks, "Can you tell me anything about the digsite?", archaeological_expert_digsite_info, "I lost the letter you gave me.", archaeological_expert_lost_letter, "Can you tell me more about the tools an archaeologist uses?", archaeological_expert_tool_help); +} else { + @multi4("I have something I need checking out.", archaeological_expert_checkout, "No thanks.", archaeological_expert_no_thanks, "Can you tell me anything about the digsite?", archaeological_expert_digsite_info, "Can you tell me more about the tools an archaeologist uses?", archaeological_expert_tool_help); +} + +[label,archaeological_expert_quest_complete] +~chatnpc("Hello again. How goes the archaeology?"); +~chatplayer("Pretty good, thanks."); +~chatnpc("Glad to hear it!"); + +[label,archaeological_expert_checkout] +~chatplayer("I have something I need checking out."); +~chatnpc("Okay, give it to me and I'll have a look for you."); + +[label,archaeological_expert_no_thanks] +~chatplayer("No thanks."); +~chatnpc("Good, let me know if you find anything unusual."); + +[label,archaeological_expert_digsite_info] +~chatplayer("Can you tell me anything about the digsite?"); +~chatnpc("Yes, indeed; I am studying the lives of the settlers. During the end of the third age there used to be a great city at the site."); +~chatnpc("Its inhabitants were humans, supporters of the god Saradomin. It's not recorded what happened to the community here."); +~chatnpc("I suspect nobody has lived here for over a millennium!"); + +def_int $choice = ~p_choice2("Can you tell me more about the tools an archaeologist uses?", 1, "Thank you!", 2); + +if ($choice = 1) { + @archaeological_expert_tool_help; +} else if ($choice = 2) { + ~chatplayer("Thank you!"); +} + +[label,archaeological_expert_lost_letter] +~chatplayer("I lost the letter you gave me."); + +if (inv_total(inv, invitation_letter) > 0) { + ~chatnpc("No you haven't! You have one in your pack!"); +} else if (inv_total(bank, invitation_letter) > 0) { + ~chatnpc("No you haven't! You have one in your bank!"); +} else { + inv_add(inv, invitation_letter, 1); + ~chatnpc("I can't believe it! I go to all the effort of writing you a letter of recommendation and you lose it! Here, I'll write another... Don't lose it again!"); +} + + +[opnpcu,archaeological_expert] +def_obj $item = last_useitem; + +// Not all the mesanims in here are correct +if ($item = talisman_of_zaros) { + if (~itexam_testbit(^itexam_bit_shown_ancient_symbol) = true) { + ~mesbox("The expert has already seen the talisman."); + return; + } + ~chatplayer("Take a look at this talisman."); + ~chatnpc("Unusual... This object doesn't appear right..."); + ~chatnpc("Hmmm..."); + ~chatnpc("I wonder... Let me check my guide... Could it be? Surely not!"); + ~chatnpc("From the markings on it, it seems to be a ceremonial ornament to a god named..."); + ~chatnpc("...Zaros? I haven't heard much about him before. This is a great discovery; we know very little of the pagan gods that people worshipped."); + ~chatnpc("There is some strange writing embossed upon it - it says, 'Zaros will return and wreak his vengeance upon Zamorak the pretender.'"); + ~chatnpc("I wonder what it means by that? Some silly superstition, probably."); + ~chatnpc("Still, I wonder what this is doing around here. I'll tell you what; as you have found this, I will allow you to use the private dig shafts."); + ~chatnpc("You obviously have a keen eye. Take this letter and give it to one of the workmen, and they will allow you to use them."); + // varbit 2550 osrs 0 to 1 + ~itexam_setbit(^itexam_bit_shown_ancient_symbol); + inv_del(inv, talisman_of_zaros, ^max_32bit_int); + inv_add(inv, invitation_letter, 1); + mes("The expert hands you a letter."); +} else if ($item = stone_tablet) { + ~chatplayer("I found this in a hidden cavern beneath the digsite."); + ~chatnpc("Incredible!"); + ~chatplayer("There is an altar down there. The place is crawling with skeletons!"); + ~chatnpc("Yuck!"); + ~chatnpc("This is an amazing discovery! All this while we were convinced that no other race had lived here."); + ~chatnpc("It seems the followers of Saradomin have tried to cover up the evidence of the Zaros altar. This whole city must have been built over it!"); + ~chatnpc("Thanks for your help; your sharp eyes have spotted what many have missed. Here, take this gold as your reward."); + ~objbox(gold_bar, "The expert gives you 2 gold bars as payment.", 250, 0, divide(^objbox_height, 2)); + inv_del(inv, stone_tablet, 1); + queue(itexam_complete, 0); +} else if ($item = unidentified_liquid) { + ~chatplayer("Do you know what this is?"); + ~chatnpc("Where did you get this?"); + ~chatplayer("From one of the barrels at the digsite."); + ~chatnpc("This is a VERY dangerous liquid called nitroglycerin. Be careful how you handle it. Don't drop it or it will explode!"); + inv_del(inv, unidentified_liquid, 1); + inv_add(inv, nitroglycerin, 1); +} else if ($item = chemical_powder) { + ~chatplayer("Do you know what this powder is?"); + ~chatnpc("Really, you do find the most unusual items. I know what this is, it's a strong chemical called ammonium nitrate. Why you want this I'll never know..."); + inv_del(inv, chemical_powder, 1); + inv_add(inv, ammonium_nitrate, 1); +} else if ($item = nitroglycerin) { + ~chatplayer("Can you tell me any more about this?"); + ~chatnpc("Nitroglycerin! This is a dangerous substance. This is normally mixed with other chemicals to produce a potent compound."); + ~chatnpc("Be sure not to drop it! That stuff is highly volatile..."); +} else if ($item = mixed_chemicals1) { + ~chatplayer("Hey, look at this."); + ~chatnpc("Hmm, that looks dangerous. Handle it carefully and don't drop it!"); +} else if ($item = mixed_chemicals2) { + ~chatplayer("See what I have done with the compound now."); + ~chatnpc("Seriously, I think you have a death wish! What on earth are you going to do with that stuff?"); + ~chatplayer("I'll find a use for it!"); +} else if ($item = chemical_compound) { + ~chatplayer("What do you think about this?"); + ~chatnpc("What have you concocted now? Just be careful when playing with chemicals!"); +} else if ($item = nuggets) { + ~chatplayer("I have these gold nuggets..."); + if (inv_total(inv, nuggets) < 3) { + ~chatnpc("I can't do much with these nuggets yet. Come back when you have 3 and I will exchange them for you."); + } else { + inv_del(inv, nuggets, 3); + inv_add(inv, gold_ore, 1); + ~chatnpc("Good – that's three; I can exchange them for normal gold now. You can get this refined and make a profit!"); + ~chatplayer("Excellent!"); + } + +} else if ($item = panning_tray_empty) { + ~chatnpc("I have no need for panning trays!"); +} else if ($item = panning_tray_mud) { + ~chatnpc("Have you searched this tray yet?"); + ~chatplayer("Not that I remember..."); + ~chatnpc("It may contain something; I don't want to get my hands dirty."); + mes("The expert hands the tray back to you."); +} else if ($item = invitation_letter) { + ~chatnpc("There's no point in giving me this back!"); +} else if ($item = rusty_sword) { + ~chatplayer("I found an old sword."); + ~chatnpc("Oh, it's very rusty isn't it? I'm not sure this sword belongs here, it looks very out of place."); +} else if ($item = broken_staff) { + ~chatplayer("Have a look at this staff."); + ~chatnpc("Look at this... Interesting... This appears to belong to a cleric of some kind; certainly not a follower of Saradomin, however."); + ~chatnpc("I wonder if there was another civilization here before the Saradominists?"); +} else if ($item = broken_armour) { + ~chatplayer("I found some armour."); + ~chatnpc("It looks like the wearer of this fought a mighty battle."); +} else if ($item = damaged_armour) { + ~chatplayer("I found some old armour."); + ~chatnpc("How unusual. This armour doesn't seem to match with the other finds. Keep looking."); +} else if ($item = needle) { + ~chatplayer("I found a needle."); + ~chatnpc("Hmm, yes; I wondered why this race were so well dressed! It looks like they had mastery of needlework."); +} else if ($item = broken_glass) { + ~chatplayer("Have a look at this glass."); + ~chatnpc("Hey you should be careful of that. It might cut your fingers, throw it away!"); +} else if ($item = broken_arrow) { + ~chatplayer("Have a look at this arrow."); + ~chatnpc("No doubt this arrow was shot by a strong warrior – it's split in half! It is not a valuable object though."); +} else if ($item = bones) { + ~chatplayer("Have a look at these bones."); + ~chatnpc("Ah, yes – a fine bone example... no noticeable fractures... and in good condition. These are common cow bones, however; they have no archaeological value."); +} else if ($item = buttons) { + ~chatplayer("I found these buttons."); + ~chatnpc("Let's have a look. Ah, I think these are from the nobility, perhaps a royal servant?"); +} else if ($item = cracked_rock_sample) { + ~chatplayer("I found this rock..."); + ~chatnpc("What a shame it's cracked; this looks like it would have been a good sample."); +} else if ($item = old_tooth) { + ~chatplayer("Hey look at this."); + ~chatnpc("Oh, an old tooth. It looks like it has come from a mighty being. Pity there are no tooth fairies around here!"); +} else if ($item = belt_buckle) { + ~chatplayer("Have a look at this unusual item..."); + ~chatnpc("Let me see. This is a belt buckle. Not so unusual - I should imagine it came from a guard."); +} else { + ~displaymessage(^dm_default); +} + +[label,archaeological_expert_tool_help] +~chatplayer("Can you tell me more about the tools an archaeologist uses?"); +~chatnpc("Of course! Let's see now... Rock picks are for splitting rocks or scraping away soil; you can get one from a cupboard in the Education Centre."); +~chatplayer("What about sample jars?"); +~chatnpc("I think you'll find them scattered about pretty much everywhere, but I know you can get one from a cupboard somewhere in the Education Centre, just like the rock pick!"); +~chatplayer("Okay, what about a specimen brush?"); +~chatnpc("We have a bit of a shortage of those at the moment. You could try borrowing one from a workman on the site... but I don't think they'd give it willingly."); +~chatplayer("Sounds like I'll need to be sneaky to get one of those, then... Okay - trowel?"); +~chatnpc("Ahh... that you must earn by passing your exams! The examiner holds those."); +~chatplayer("Ahh, ok thanks."); + +[opheld2,invitation_letter] +~chatplayer("It says, 'I give permission for the bearer... to use the mine shafts on site. - signed Terrance Balando, Archaeological Expert, City of Varrock.'"); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/area_digsite.rs2 b/data/src/scripts/quests/quest_itexam/scripts/area_digsite.rs2 new file mode 100644 index 0000000000..705ab27713 --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/area_digsite.rs2 @@ -0,0 +1,874 @@ +//////////////////////////////////////////////// +// PANNING +//////////////////////////////////////////////// + +[oploc1,digsite_panning_point] +// on osrs, varbit 2544 (varp 135, bit 1) indicates if you've completed the panning guide errand or not +if (~itexam_testbit(^itexam_bit_panning_guide_tea_given) = false) { + if (npc_find(coord, panning_guide, 10, 0) = true) { + @panning_guide_intervene; + } +} + +if (inv_total(inv, panning_tray_empty) > 0) { + strongqueue(panning_action, 0); +} else { + mes("You need a panning tray to pan here!"); +} + +[queue,panning_action] +// The panning anims were seemingly added with the 2006 rework, not sure what happens here, i'm mixing a bit of RSC + osrs behavior. +mes("You scrape the tray along the bottom"); +p_delay(2); +mes("You swirl away the excess water"); +p_delay(1); +inv_del(inv, panning_tray_empty, 1); +inv_add(inv, panning_tray_mud, 1); +stat_advance(mining, 20); +stat_advance(fishing, 20); +~objbox(panning_tray_mud, "You lift the full tray from the water.", 250, 0, divide(^objbox_height, 2)); + +[opheld2,panning_tray_empty] +~chatplayer("Err, why am I searching an empty tray?"); + +[opheld2,panning_tray_mud] +mes("You search the contents of the tray..."); +inv_del(inv, panning_tray_mud, 1); +inv_add(inv, panning_tray_empty, 1); +@search_panning_tray; + +[label,search_panning_tray] +def_int $rand = random(40); + +if ($rand < 3) { + if (~itexam_progress = ^itexam_first_exam & inv_total(inv, rock_sample_2) = 0) { + inv_add(inv, rock_sample_2, 1); + ~objbox(rock_sample_2, "You find a rock sample covered in mud.", 250, 0, divide(^objbox_height, 2)); + } else { + ~objbox(panning_tray_mud, "The tray contains only plain mud.", 250, 0, divide(^objbox_height, 2)); + } +} else if ($rand < 6) { + inv_add(inv, uncut_opal, 1); + ~objbox(uncut_opal, "You find a gem within the mud!", 250, 0, divide(^objbox_height, 2)); +} else if ($rand < 9) { + inv_add(inv, uncut_jade, 1); + ~objbox(uncut_jade, "You find a gem within the mud!", 250, 0, divide(^objbox_height, 2)); +} else if ($rand < 12) { + inv_add(inv, oyster, 1); + ~objbox(oyster, "You find an oyster within the mud!", 250, 0, divide(^objbox_height, 2)); +} else if ($rand < 16) { + inv_add(inv, nuggets, 1); + ~objbox(panning_tray_gold, "You find some gold nuggets within the mud.", 250, 0, divide(^objbox_height, 2)); +} else if ($rand < 20) { + inv_add(inv, coins, calc(1 + random(10))); + ~objbox(coins, "You find some coins within the mud.", 250, 0, divide(^objbox_height, 2)); +} else { + ~objbox(panning_tray_mud, "The tray contains only plain mud.", 250, 0, divide(^objbox_height, 2)); +} + +//////////////////////////////////////////////// +// STUDENT 3 ERRAND 1 +//////////////////////////////////////////////// + +[oploc1,digsite_bush_empty] +anim(human_pickuptable, 0); +mes("You search the bush...You find nothing of interest."); + +[oploc1,digsite_bush_rock_sample] +anim(human_pickuptable, 0); + +if (~itexam_progress > ^itexam_first_exam | inv_total(inv, rock_sample_3) > 0) { + mes("You search the bush..."); + mes("You find nothing of interest."); +} else { + ~chatplayer("Hey, something has been dropped here..."); + // We're inferring the correct sample here because obj 673 in osrs is the teddy bear + inv_add(inv, rock_sample_3, 1); + // From RSC + ~objbox(rock_sample_3, "You find a rock sample!", 250, 0, divide(^objbox_height, 2)); +} + +//////////////////////////////////////////////// +// SKELETON +//////////////////////////////////////////////// + +[oploc1,digsite_buried_skeleton] +mes("You search the skeleton..."); +mes("You find nothing of interest."); + +//////////////////////////////////////////////// +// SACKS +//////////////////////////////////////////////// + +[oploc1,digsite_sacks_empty] +mes("You search the sacks..."); +mes("You find nothing of interest."); + +[oploc1,digsite_sacks_specimen_jars] + +if (inv_total(inv, specimen_jar) > 0) { + mes("You search the sacks..."); + mes("You find nothing of interest."); +} else { + inv_add(inv, specimen_jar, 1); + ~chatplayer("Hey there's something under here."); + ~objbox(specimen_jar, "You find a specimen jar!", 250, 0, divide(^objbox_height, 2)); +} + +//////////////////////////////////////////////// +// SOIL +//////////////////////////////////////////////// + +[oplocu,_digsite_soil] +def_obj $item = last_useitem; + +if ($item = panning_tray_empty) { + ~chatplayer("No, I'd better not. It may damage the tray..."); + return; +} + +if ($item = spade) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Oi! Don't use that spade! What are you trying to do, destroy everything of value?"); + } else { + ~mesbox("You can't use a spade here."); + } + return; +} + +if ($item = specimen_brush) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Use your brush on specimens to clean them, not the dirt!"); + } else { + mes("Use your brush on specimens to clean them, not the dirt!"); + } + return; +} + +// TRAINING SITES +if (inzone(0_52_53_24_4, 0_52_53_29_8, loc_coord) = true | inzone(0_52_53_39_5, 0_52_53_44_8, loc_coord) = true) { + @dig_training_site($item); +} + +// LEVEL 1 SITES +if (inzone(0_52_53_32_10, 0_52_53_35_22, loc_coord) = true | inzone(0_52_53_39_11, 0_52_53_44_22, loc_coord) = true) { + if (~itexam_progress < ^itexam_second_exam) { + @digsite_workman_intervene_site(1); + } + @dig_level_1_site($item); +} + +// LEVEL 2 SITES +if (inzone(0_52_53_22_23, 0_52_53_27_26, loc_coord) = true | inzone(0_52_53_22_32, 0_52_53_35_38, loc_coord) = true | inzone(0_52_53_39_31, 0_52_53_44_38, loc_coord) = true) { + if (~itexam_progress < ^itexam_third_exam) { + @digsite_workman_intervene_site(2); + } + @dig_level_2_site($item); +} + +// LEVEL 3 SITES +if (inzone(0_52_53_22_12, 0_52_53_29_20, loc_coord) = true | inzone(0_52_53_42_45, 0_52_53_49_50, loc_coord) = true) { + if (~itexam_progress < ^itexam_impress_archeological_expert) { + @digsite_workman_intervene_site(1); + } + @dig_level_3_site($item); +} + +//////////////////////////////////////////////// +// TRAINING DIG +//////////////////////////////////////////////// + +[oploc1,digsite_signpost_training_site] +mes("This site is for training purposes only."); + +[label,dig_training_site](obj $item) +if ($item = rock_pick) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("No, no; rock picks should only be used to dig at a level 2 site."); + } else { + mes("Rock picks should only be used at a level 2 site."); + } + return; +} + +if ($item ! trowel) { + return; +} +mes("You dig through the earth..."); +stat_advance(mining, 50); +p_delay(6); + +// I'm not sure why this behaves differently. The osrs training site is incredibly broken in the live game. +if (inv_freespace(inv) = 0) { + mes("You find nothing of interest."); +} else { + @training_dig_loot_table; +} + +[label,training_dig_loot_table] +def_int $rand = random(13); + +if ($rand < 8) { + mes("You find nothing."); +} else if ($rand < 9) { + inv_add(inv, coins, 1); + mes("You find a coin."); +} else if ($rand < 10) { + inv_add(inv, charcoal, 1); + mes("You find some charcoal."); +} else if ($rand < 11) { + inv_add(inv, broken_arrow, 1); + mes("You find a broken arrow."); +} else if ($rand < 12) { + inv_add(inv, ceramic_remains, 1); + mes("You find some pottery."); +} else if ($rand < 13) { + inv_add(inv, cracked_rock_sample, 1); + mes("You find a cracked rock."); +} + +//////////////////////////////////////////////// +// LEVEL 1 DIG +//////////////////////////////////////////////// + +[oploc1,digsite_signpost_level_1_site] +mes("Level 1 digs only."); + +[label,dig_level_1_site](obj $item) +if ($item = rock_pick) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("No, no; rock picks should only be used to dig at a level 2 site."); + } else { + mes("Rock picks should only be used at a level 2 site."); + } + return; +} + +if ($item ! trowel) { + return; +} + +if (inv_freespace(inv) = 0) { + mes("You don't have enough space in your inventory to do that."); + return; +} + +if (inv_getobj(worn, ^wearpos_hands) ! leather_gloves) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Hey, where are your leather gloves?"); + ~chatplayer("Err... I haven't got any."); + ~chatnpcnoturn("Well get some and put them on first!"); + } else { + mes("You need to be wearing leather gloves to dig here."); + } + return; +} + +if (inv_getobj(worn, ^wearpos_feet) ! leather_boots) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Oi! No boots! No leather boots: no digging!"); + } else { + mes("You need to be wearing leather boots to dig here."); + } + return; +} +mes("You dig through the earth..."); +stat_advance(mining, 60); +p_delay(6); +@level_1_dig_loot_table; + +[label,level_1_dig_loot_table] +def_int $rand = random(12); + +if ($rand < 2) { + mes("You find nothing."); +} else if ($rand < 3) { + inv_add(inv, buttons, 1); + mes("You find some buttons."); +} else if ($rand < 4) { + inv_add(inv, digsite_vase, 1); + mes("You find an old vase."); +} else if ($rand < 5) { + inv_add(inv, copper_ore, 1); + mes("You find some copper ore."); +} else if ($rand < 6) { + inv_add(inv, leather_boots, 1); + mes("You find some old boots."); +} else if ($rand < 7) { + inv_add(inv, opal, 1); + mes("You find an opal."); +} else if ($rand < 8) { + inv_add(inv, old_tooth, 1); + mes("You find an old tooth."); +} else if ($rand < 9) { + inv_add(inv, rotten_apples, 1); + mes("You find a rotten apple."); +} else if ($rand < 10) { + inv_add(inv, broken_glass, 1); + mes("You find some broken glass."); +} else if ($rand < 11) { + inv_add(inv, rusty_sword, 1); + mes("You find a rusty sword."); +} else if ($rand < 12) { + inv_add(inv, bones, 1); + mes("You find some bones."); +} + +//////////////////////////////////////////////// +// LEVEL 2 DIG +//////////////////////////////////////////////// + +[oploc1,digsite_signpost_level_2_site] +mes("Level 2 digs only."); + +[label,dig_level_2_site](obj $item) +if ($item = trowel) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Sorry, you must use a rock pick to dig at a level 2 site."); + } else { + mes("You must use a rock pick to dig at a level 2 site."); + } + return; +} + +if ($item ! rock_pick) { + return; +} + +if (inv_freespace(inv) = 0) { + mes("You don't have enough space in your inventory to do that."); + return; +} + +mes("You dig through the earth..."); +stat_advance(mining, 70); +p_delay(6); +@level_2_dig_loot_table; + +[label,level_2_dig_loot_table] +def_int $rand = random(16); + +if ($rand < 3) { + mes("You find nothing."); +} else if ($rand < 5) { + inv_add(inv, bones, 1); + mes("You find some bones."); +} else if ($rand < 6) { + inv_add(inv, damaged_armour, 1); + mes("You find some old armour."); +} else if ($rand < 7) { + inv_add(inv, leather_boots, 1); + mes("You find some old boots."); +} else if ($rand < 8) { + inv_add(inv, bowl_empty, 1); + mes("You find an old bowl."); +} else if ($rand < 9) { + inv_add(inv, broken_staff, 1); + mes("You find a broken staff."); +} else if ($rand < 10) { + inv_add(inv, broken_armour, 1); + mes("You find some old armour."); +} else if ($rand < 11) { + inv_add(inv, uncut_jade, 1); + mes("You find a gem."); +} else if ($rand < 12) { + inv_add(inv, broken_glass, 1); + mes("You find some broken glass."); +} else if ($rand < 13) { + inv_add(inv, jug_empty, 1); + mes("You find an old jug."); +} else if ($rand < 14) { + inv_add(inv, pot_empty, 1); + mes("You find an old pot."); +} else if ($rand < 15) { + inv_add(inv, clay, 1); + mes("You find some clay."); +} else if ($rand < 16) { + inv_add(inv, uncut_opal, 1); + mes("You find a gem."); +} + +//////////////////////////////////////////////// +// LEVEL 3 DIG +//////////////////////////////////////////////// + +[oploc1,digsite_signpost_level_3_site] +mes("Level 3 digs only."); + +[label,dig_level_3_site](obj $item) +if ($item = rock_pick) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("No, no; rock picks should only be used to dig at a level 2 site."); + } else { + mes("Rock picks should only be used at a level 2 site."); + } + return; +} + +if ($item ! trowel) { + return; +} + +if (inv_freespace(inv) = 0) { + mes("You don't have enough space in your inventory to do that."); + return; +} + +if (inv_total(inv, specimen_jar) = 0) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Ahem! I don't see your specimen jar; you must carry one to be able to dig here."); + } else { + mes("You need a sample jar to dig here."); + } + return; +} + +if (inv_total(inv, specimen_brush) = 0) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Wait just a minute. I can't let you dig here unless you have a specimen brush with you. Rules are rules!"); + } else { + mes("You can't dig here unless you have a specimen brush."); + } + return; +} +mes("You dig through the earth..."); +stat_advance(mining, 80); +p_delay(6); +@level_3_dig_loot_table; + +[label,level_3_dig_loot_table] +def_int $rand = random(20); + +if ($rand < 2) { + mes("You find nothing."); +} else if ($rand < 3) { + if (~itexam_testbit(^itexam_bit_shown_ancient_symbol) = false & inv_total(inv, talisman_of_zaros) = 0) { + inv_add(inv, talisman_of_zaros, 1); + ~objbox(talisman_of_zaros, "You find a strange talisman.", 250, 0, divide(^objbox_height, 2)); + } else { + inv_add(inv, coins, 10); + mes("You find some coins."); + } +} else if ($rand < 4) { + inv_add(inv, belt_buckle, 1); + mes("You find a belt buckle."); +} else if ($rand < 5) { + inv_add(inv, black_med_helm, 1); + mes("You find a black helmet."); +} else if ($rand < 6) { + inv_add(inv, bones, 1); + mes("You find some bones."); +} else if ($rand < 7) { + inv_add(inv, broken_armour, 1); + mes("You find some old armour."); +} else if ($rand < 8) { + inv_add(inv, broken_arrow, 1); + mes("You find a broken arrow."); +} else if ($rand < 9) { + inv_add(inv, broken_staff, 1); + mes("You find a broken staff."); +} else if ($rand < 10) { + inv_add(inv, bronze_spear, 1); + mes("You find a bronze spear."); +} else if ($rand < 11) { + inv_add(inv, buttons, 1); + mes("You find some buttons."); +} else if ($rand < 12) { + inv_add(inv, ceramic_remains, 1); + mes("You find some old pottery."); +} else if ($rand < 13) { + inv_add(inv, clay, 1); + mes("You find some clay."); +} else if ($rand < 14) { + inv_add(inv, damaged_armour, 1); + mes("You find some old armour."); +} else if ($rand < 15) { + inv_add(inv, iron_knife, 1); + mes("You find a throwing knife."); +} else if ($rand < 16) { + inv_add(inv, leather_boots, 1); + mes("You find some old boots."); +} else if ($rand < 17) { + inv_add(inv, needle, 1); + mes("You find a needle."); +} else if ($rand < 18) { + inv_add(inv, old_tooth, 1); + mes("You find an old tooth."); +} else if ($rand < 19) { + inv_add(inv, piedish, 1); + mes("You find a pie dish."); +} else if ($rand < 20) { + inv_add(inv, coins, 10); + mes("You find some coins."); +} +mes("You carefully clean your find with the specimen brush."); + +//////////////////////////////////////////////// +// SPECIMEN TRAY +//////////////////////////////////////////////// + +[oploc2,specimen_tray] +if (inv_total(inv, specimen_jar) = 0) { + if (npc_find(coord, digsite_workman, 10, 0) = true) { + @digsite_workman_specimen_tray_intervene; + } else { + // unconfirmed, it is impossible to get far enough from a workman to test this. + mes("You need a sample jar to search this tray."); + } +} else { + if (inv_freespace(inv) = 0) { + mes("You don't have enough space in your inventory to do that."); + return; + } + + mes("You sift through the earth in the tray."); + anim(human_pickupfloor, 0); + stat_advance(mining, 5); + p_delay(3); + + def_int $rand = random(11); + + if ($rand < 2) { + mes("You find nothing."); + } else if ($rand < 4) { + inv_add(inv, bones, 1); + mes("You find some bones."); + } else if ($rand < 5) { + inv_add(inv, coins, 1); + mes("You find a coin."); + } else if ($rand < 6) { + inv_add(inv, iron_dagger, 1); + mes("You find a dagger."); + } else if ($rand < 7) { + inv_add(inv, charcoal, 1); + mes("You find some charcoal."); + } else if ($rand < 8) { + inv_add(inv, broken_arrow, 1); + mes("You find a broken arrow."); + } else if ($rand < 9) { + inv_add(inv, broken_glass, 1); + mes("You find some broken glass."); + } else if ($rand < 10) { + inv_add(inv, ceramic_remains, 1); + mes(" You find some pottery."); + } else if ($rand < 11) { + inv_add(inv, cracked_rock_sample, 1); + mes("You find a cracked rock."); + } +} + +[label,digsite_workman_specimen_tray_intervene] +~chatnpcnoturn("Oi! What are you doing?"); +def_int $choice = ~p_choice2("I am on an errand.", 1, "I am searching this tray.", 2); + +if ($choice = 1) { + ~chatplayer("I am on an errand."); + ~chatnpcnoturn("Oh yeah? And whose errand is that then? Where is your specimen jar?"); + ~chatplayer("Oh I don't have one."); + ~chatnpcnoturn("And you reckon you have been sent on an errand - without a specimen jar? Sorry, I can't let you do that!"); +} else { + ~chatplayer("I am searching this tray."); + ~chatnpcnoturn("Oh you are, are you? Well where's your specimen jar?"); + ~chatplayer("Ah... I don't have one."); + ~chatnpcnoturn("Well how can you handle the specimens without it? As you should know, specimens are to be kept in specimen jars to keep them safe and preserved. Next time bring it along!"); +} + +//////////////////////////////////////////////// +// WINCH +//////////////////////////////////////////////// + +[oploc1,digsite_winch] +if (~itexam_progress < ^itexam_mineshaft_permit) { + @digsite_workman_intervene_winch; +} + +if (~itexam_testbit(^itexam_bit_winch_rope_attached) = false) { + mes("You operate the winch."); + mes("The bucket descends, but does not reach the bottom."); + anim(human_pickuptable, 0); + ~chatplayer("Hey, I think I could fit down here. I need something to help me get all the way down."); +} else { + @digsite_winch_teleport; +} + +[oplocu,digsite_winch] +if (last_useitem = rope) { + if (~itexam_testbit(^itexam_bit_winch_rope_attached) = false) { + // osrs varbit 2545 0 to 1 + mes("You tie the rope to the bucket..."); + ~itexam_setbit(^itexam_bit_winch_rope_attached); + anim(human_pickuptable, 0); + inv_del(inv, rope, 1); + } else { + @digsite_winch_teleport; + } +} else { + ~displaymessage(^dm_default); +} + +[label,digsite_winch_intervene] + +[label,digsite_winch_teleport] +anim(human_pickuptable, 0); + +if (stat(agility) < 10) { + mes("You try to climb down the rope..."); + mes("You need an Agility level of 10 to squeeze down the shaft."); + return; +} +mes("You try to climb down the rope."); +mes("You lower yourself into the shaft."); +stat_advance(agility, 20); +p_delay(1); +mes("You find yourself in a cavern..."); +if (~itexam_progress = ^itexam_removed_blockage) { + p_teleport(0_52_152_42_36); +} else { + p_teleport(0_52_153_42_36); +} + +//////////////////////////////////////////////// +// PRIVATE DIG WINCH +//////////////////////////////////////////////// + +[oploc1,digsite_private_dig_winch] +if (~itexam_progress < ^itexam_mineshaft_permit) { + @digsite_workman_intervene_winch; +} + +if (~itexam_testbit(^itexam_bit_private_winch_rope_attached) = false) { + mes("You operate the winch."); + p_delay(2); + mes("The bucket descends, but does not reach the bottom."); + anim(human_pickuptable, 0); + ~chatplayer("Hey, I think I could fit down here. I need something to help me get all the way down."); +} else { + @digsite_private_winch_teleport; +} + +[oplocu,digsite_private_dig_winch] +if (last_useitem = rope) { + if (~itexam_testbit(^itexam_bit_private_winch_rope_attached) = false) { + // osrs varbit 2546 0 to 1 + mes("You tie the rope to the bucket..."); + ~itexam_setbit(^itexam_bit_private_winch_rope_attached); + anim(human_pickuptable, 0); + inv_del(inv, rope, 1); + } else { + @digsite_winch_teleport; + } +} else { + ~displaymessage(^dm_default); +} + +[label,digsite_private_winch_teleport] +anim(human_pickuptable, 0); + +if (stat(agility) < 10) { + mes("You try to climb down the rope..."); + mes("You need an Agility level of 10 to squeeze down the shaft."); + return; +} +mes("You try to climb down the rope."); +mes("You lower yourself into the shaft."); +stat_advance(agility, 20); +p_delay(1); +mes("You find yourself in a cavern."); +if (~itexam_progress = ^itexam_removed_blockage) { + p_teleport(0_52_152_25_26); +} else { + p_teleport(0_52_153_25_26); +} + +//////////////////////////////////////////////// +// PRIVATE DIG +//////////////////////////////////////////////// + +[oploc1,digsite_signpost_private_site] +mes("Private dig."); + +[oploc1,digsite_private_dig_exit_rope] +anim(human_pickuptable, 0); +p_teleport(0_52_53_42_35); +facesquare(0_52_53_42_34); + +//////////////////////////////////////////////// +// ALTAR CAVE +//////////////////////////////////////////////// + +[oploc1,digsite_blocked_altar_exit_rope] +anim(human_pickuptable, 0); +p_teleport(0_52_53_26_25); +facesquare(0_52_53_25_25); + +[oploc1,digsite_blocked_altar_brick] +if (~itexam_progress = ^itexam_poured_compound_on_bricks) { + ~chatplayer("The brick is covered with the chemicals I made."); +} else { + ~itexam_setbit(^itexam_bit_searched_bricks); + ~chatplayer("Hmmm, there's a room past these bricks. If I could move them out of the way then I could find out what's inside. Maybe there's someone around here who can help..."); +} + +[oplocu,digsite_blocked_altar_brick] +def_obj $item = last_useitem; + +if ($item = chemical_compound) { + mes("You pour the compound over the bricks..."); + anim(human_pickupfloor, 0); + inv_del(inv, chemical_compound, 1); + ~itexam_set_progress(^itexam_poured_compound_on_bricks); + ~chatplayer("Okay, the mixture is all over the bricks. I need some way to ignite this compound."); +} + +if ($item = tinderbox) { + if (~itexam_progress ! ^itexam_poured_compound_on_bricks) { + say("Now, what am I trying to achieve here?"); + return; + } + mes("You strike the tinderbox..."); + mes("Fizz..."); + ~chatplayer("Whoa! This is going to blow! I'd better run!"); + strongqueue(digsite_blockage_run_sequence, 0); +} + +[queue,digsite_blockage_run_sequence] +if (coord ! 0_52_153_51_34) { + mes("Eep! Eep! Unexpected player coord!"); + return; +} +p_teleport(0_52_153_51_36); +p_delay(0); +p_teleport(0_52_153_51_37); +p_delay(0); +p_teleport(0_52_153_49_38); +p_delay(0); +p_teleport(0_52_153_47_38); +p_delay(0); +p_teleport(0_52_153_45_39); +p_delay(0); +p_teleport(0_52_153_43_39); +p_delay(0); +p_teleport(0_52_153_41_39); +p_delay(0); +p_teleport(0_52_153_40_39); +p_delay(0); + +cam_shake(0, 20, 0, 0); +cam_shake(1, 20, 0, 0); +cam_shake(2, 20, 0, 0); +cam_shake(3, 20, 0, 0); +cam_shake(4, 20, 0, 0); +p_delay(2); +cam_reset; +p_teleport(0_52_152_40_39); +~itexam_set_progress(^itexam_removed_blockage); +~chatplayer("Wow, that was a big explosion! What's that noise I can hear? Sounds like bones moving or something..."); + +[opheld2,stone_tablet] +~chatplayer("It says: Tremble mortal, before the altar of our dread lord Zaros."); + +//////////////////////////////////////////////// +// DIGSITE CHEST +//////////////////////////////////////////////// + +[oploc1,digsite_chest] +mes("The chest is locked."); + +[oplocu,digsite_chest] +if (last_useitem = digsite_chest_key) { + mes("You use the key in the chest."); + anim(human_openchest, 0); + inv_del(inv, digsite_chest_key, 1); + p_delay(0); + loc_change(digsite_chest_open, 300); +} else { + ~displaymessage(^dm_default); +} + +[oploc1,digsite_chest_open] +// There's no quest state check on osrs, anyone can search the chest and get the powder at any time +inv_add(inv, chemical_powder, 1); +~objbox(chemical_powder, "You find some unusual powder inside...", 250, 0, divide(^objbox_height, 2)); + +//////////////////////////////////////////////// +// NITROGLYCERIN BARREL +//////////////////////////////////////////////// + +[oploc1,digsite_sealed_barrel] +~chatplayer("Mmmm... The lid is shut tight; I'll have to find something to lever it off."); + +[oploc2,digsite_sealed_barrel] +if (~itexam_testbit(^itexam_bit_barrel_open) = true) { + mes("You search the barrel..."); + mes("The barrel has a foul-smelling liquid inside."); + ~chatplayer("I can't pick this up with my bare hands! I'll need something to put it in. It looks and smells rather dangerous though, so it'll need to be something small and capable of containing dangerous chemicals."); +} else { + ~chatplayer("It's closed tight."); +} + +[oplocu,digsite_sealed_barrel] +def_obj $item = last_useitem; + +if ($item = trowel) { + // osrs varbit 2547 0 to 1 + ~itexam_setbit(^itexam_bit_barrel_open); + ~chatplayer("Great! It's opened it."); +} else if ($item = vial_empty) { + if (~itexam_testbit(^itexam_bit_barrel_open) = true) { + inv_del(inv, vial_empty, 1); + inv_add(inv, unidentified_liquid, 1); + ~objbox(unidentified_liquid, "You fill the vial with the liquid.", 250, 0, divide(^objbox_height, 2)); + } else { + ~chatplayer("It's not open!"); + } +} + +[opheld5,unidentified_liquid] +anim(human_pickupfloor, 0); +inv_delslot(inv, last_slot); +cam_shake(0, 5, 0, 0); +p_delay(3); +cam_reset; +~damage_self(25); +mes("You were injured by the burning liquid."); +say("Ow! The liquid exploded!"); + +[opheld5,nitroglycerin] +anim(human_pickupfloor, 0); +inv_delslot(inv, last_slot); +cam_shake(0, 5, 0, 0); +p_delay(3); +cam_reset; +~damage_self(35); +mes("You were injured by the burning liquid."); +say("Ow! The nitroglycerin exploded!"); + +[opheld5,mixed_chemicals1] +anim(human_pickupfloor, 0); +inv_delslot(inv, last_slot); +cam_shake(0, 5, 0, 0); +p_delay(3); +cam_reset; +~damage_self(45); +mes("You were quite badly injured by the burning liquid."); +say("Ow! The chemicals exploded!"); + +[opheld5,mixed_chemicals2] +anim(human_pickupfloor, 0); +inv_delslot(inv, last_slot); +cam_shake(0, 5, 0, 0); +p_delay(3); +cam_reset; +~damage_self(55); +mes("You were badly by the burning liquid."); +say("Ow! The mixture exploded!"); + +[opheld5,chemical_compound] +anim(human_pickupfloor, 0); +inv_delslot(inv, last_slot); +cam_shake(0, 5, 0, 0); +p_delay(3); +cam_reset; +~damage_self(65); +mes("You were very badly injured by the burning liquid."); +say("Ow! That really hurt!"); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/area_exam_centre.rs2 b/data/src/scripts/quests/quest_itexam/scripts/area_exam_centre.rs2 new file mode 100644 index 0000000000..0b9c9d8292 --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/area_exam_centre.rs2 @@ -0,0 +1,50 @@ +[oploc1,exam_centre_cupboard_rock_pick] +anim(human_openchest, 0); +mes("You open the cupboard."); +p_delay(0); +loc_change(exam_centre_cupboard_rock_pick_open, 300); + +[oploc1,exam_centre_cupboard_rock_pick_open] +if (inv_total(inv, rock_pick) = 0) { + inv_add(inv, rock_pick, 1); + ~objbox(rock_pick, "You find a rock pick.", 250, 0, divide(^objbox_height, 2)); +} else { + mes("You find nothing of interest."); +} + +[oploc2,exam_centre_cupboard_rock_pick_open] +anim(human_openchest, 0); +p_delay(0); +loc_change(exam_centre_cupboard_rock_pick, 300); + +[label,exam_centre_cupboard_jar] +if (inv_total(inv, specimen_jar) = 0) { + inv_add(inv, specimen_jar, 1); + ~objbox(specimen_jar, "You find a specimen jar.", 250, 0, divide(^objbox_height, 2)); +} else { + mes("You find nothing of interest."); +} + +[oploc1,exam_centre_bookcase_chemicals] +~objbox(book_on_chemicals, "You find a book on chemicals.", 250, 0, divide(^objbox_height, 2)); + +if (inv_total(inv, book_on_chemicals) = 0) { + inv_add(inv, book_on_chemicals, 1); +} + +[label,exam_centre_bookcase] +mes("You search through the bookcase..."); +p_delay(0); +~mesbox("The label on this shelf reads 'Earth Sciences'; however, the helpful books have been taken. It looks like the other students got to them first."); + +[opheld2,book_on_chemicals] +%book_page = 0; +%open_book = book_on_chemicals; +@book_flip_page(0, 0, 2, book_on_chemicals); + +// Not an exact copy of OSRS line breaks because their book modal seems to be able to handle more characters per line +[proc,book_on_chemicals] +switch_int (%book_page) { + case 0 : ~book("Volatile chemicals - Experimental Test Notes.", "Volatile chemicals -|Experimental Test Notes.||In order to ease the mining process, my colleagues and I decided we needed something stronger than picks to delve under the surface of the digsite. As I already had an intermediate knowledge of Herblore, I experimented with certain chemicals and invented a compound of tremendous power that, if subjected to a spark, would literally explode. We used vials of this compound with great effect, as it enabled us"); + case 1 : ~book("Volatile chemicals - Experimental Test Notes.", "to reach further than ever before. Here is what I have left of the compound's recipe:||1 measure of ammonium nitrate powder;|1 measure of nitroglycerin;|1 measure of ground charcoal;|1 measure of ?|Unfortunately the last ingredient was not noted down, but we understand that a certain root grows around these parts that was used to very good effect..."); +} \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/digsite_workman.rs2 b/data/src/scripts/quests/quest_itexam/scripts/digsite_workman.rs2 new file mode 100644 index 0000000000..e0052c1466 --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/digsite_workman.rs2 @@ -0,0 +1,145 @@ +[opnpc1,digsite_workman] + +switch_int (~itexam_progress) { + case default : @digsite_workman_default; + case ^itexam_complete : @digsite_workman_quest_complete; +} + +[label,digsite_workman_default] +~chatnpc("Why hello there! What can I do you for?"); +def_int $choice = ~p_choice3("What do you do here?", 1, "I'm not sure...", 2, "Can I dig around here?", 3); + +if ($choice = 1) { + ~chatplayer("What do you do here?"); + ~chatnpc("I am involved in various stages of the dig, from the initial investigation to the installation of the mine shafts."); + ~chatplayer("Oh, okay, thanks."); +} else if ($choice = 2) { + ~chatplayer("I'm not sure..."); + ~chatnpc("Well, let me know when you are."); +} else { + ~chatplayer("Can I dig around here?"); + ~chatnpc("You can only use a site you have the appropriate exam level for."); + + $choice = ~p_choice2("Appropriate exam level?", 1, "I am already skilled in digging.", 2); + + if ($choice = 1) { + ~chatplayer("Appropriate exam level?"); + ~chatnpc("Yea, only people who have passed level 1 certificate can dig in a level 1 site and so on and so forth."); + ~chatplayer("Ah, yes; I understand."); + } else { + ~chatplayer("I am already skilled in digging."); + ~chatnpc("Well that's nice for you. But regulations say you can't dig around here without a certificate."); + ~chatplayer("Oh right."); + ~chatnpc("The examiner up at the education centre can help you there."); + ~chatplayer("Thanks; I'll talk to her."); + } +} + +// Each workman variant has a different dialogue, in our version of the quest we do not have variants so i just picked one from osrs since i cannot find what the original did +[label,digsite_workman_quest_complete] +~chatplayer("Hello!"); +~chatnpc("Oh wow! You're the archaeologist who found that altar in the mines aren't you!"); +~chatplayer("Um, yes."); +~chatnpc("So glad to meet you! Well done!"); + +[opnpc3,digsite_workman] +if(%stunned > map_clock) { + return; +} + +if (%action_delay > map_clock) { + p_opnpc(3); + return; +} + +mes("You attempt to pick the workman's pocket..."); +p_delay(2); + +// From osrs (used the quest speedrunning worlds) +if (stat(thieving) < 25) { + mes("You need to be at level 25 Thieving to pick the workman's pocket."); + return; +} + +// TODO: we need to investigate this success rate a bit, for now this is the warrior woman success rate +if(stat_random(stat(thieving), 100, 240) = false) { + npc_say("What do you think you're doing?"); + mes("You fail to pick the workman's pocket."); + npc_setmode(playerface); + p_delay(0); + spotanim_pl(stunned_thieving, 124, 0); + anim(%com_defendanim, 0); + ~damage_self(1); + %action_delay = calc(map_clock + 13); + %stunned = calc(map_clock + 13); + walktrigger(stunned); +} else { + anim(human_pickpocket, 0); + sound_synth(pick, 0, 0); + stat_advance(thieving, 104); + + def_int $rand = random(11); + + if ($rand < 3) { + if (~itexam_progress = ^itexam_first_exam & inv_total(inv, rock_sample_1) = 0) { + inv_add(inv, rock_sample_1, 1); + ~objbox(rock_sample_1, "You steal a rock sample.", 250, 0, divide(^objbox_height, 2)); + } else { + inv_add(inv, coins, 10); + mes("You steal some money."); + } + } else if ($rand < 4) { + inv_add(inv, spade, 1); + mes("You steal a spade."); + } else if ($rand < 5) { + inv_add(inv, leather_gloves, 1); + mes("You steal a pair of leather gloves."); + } else if ($rand < 6) { + inv_add(inv, bucket_empty, 1); + mes("You steal a bucket."); + } else if ($rand < 7) { + inv_add(inv, rope, 1); + mes("You steal some rope."); + } else if ($rand < 10) { + inv_add(inv, specimen_brush, 1); + mes("You find a specimen brush."); + } else { + inv_add(inv, coins, 10); + mes("You steal some money."); + } +} + +[opnpcu,digsite_workman] +if (last_useitem = invitation_letter) { + inv_del(inv, invitation_letter, 1); + ~itexam_set_progress(^itexam_mineshaft_permit); + ~chatplayer("Here, have a look at this..."); + ~chatnpc("I give permission... blah de blah... etc. Okay, that's all in order; you may use the mineshaft now. I'll hang onto this scroll, shall I?"); +} else { + ~displaymessage(^dm_default); +} + + +[label,digsite_workman_intervene] +if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Oi! What do you think you're doing? There's fragile specimens around here!"); +} else { + mes("There needs to be a workman present when you dig."); +} + +[label,digsite_workman_intervene_winch] +if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Sorry, this area is private. The only way you'll get to use these is by impressing the archaeological expert up at the centre."); + ~chatnpcnoturn("Find something worthwhile and he might let you use the winches. Until then, get lost!"); +} else { + mes("There is a sign on the winch."); + p_delay(0); + mes("Private area - invitation only."); +} + +[label,digsite_workman_intervene_site](int $exam_level) +if (npc_find(coord, digsite_workman, 10, 0) = true) { + ~chatnpcnoturn("Sorry, you haven't passed the level Earth Sciences exam; I can't let you dig here."); +} else { + mes("You haven't passed the level Earth Sciences exam; You can't dig here."); +} \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/examiner.rs2 b/data/src/scripts/quests/quest_itexam/scripts/examiner.rs2 new file mode 100644 index 0000000000..ac1480282a --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/examiner.rs2 @@ -0,0 +1,546 @@ +[opnpc1,examiner] +def_int $progress = ~itexam_progress; + +switch_int ($progress) { + case 0 : @itexam_examiner_quest_start; + case ^itexam_stamping : @itexam_examiner_deliver_stamped_letter; + case ^itexam_first_exam : @itexam_examiner_take_first_exam; + case ^itexam_second_exam : @itexam_examiner_take_second_exam; + case ^itexam_third_exam : @itexam_examiner_take_third_exam; + case ^itexam_complete : @itexam_examiner_after_quest; + case default : @itexam_examiner_go_digging; +} + +//////////////////////////////////////////////// +// QUEST START +//////////////////////////////////////////////// + +[label,itexam_examiner_quest_start] +~chatplayer("Hello."); +~chatnpc("Ah hello there! I am the resident lecturer on antiquities and artefacts. I also set the Earth Sciences exams."); +~chatplayer("Earth Sciences?"); +~chatnpc("That is right dear, the world of RuneScape holds many wonders beneath its surface. Students come to me to take exams so that they may join in on the archeological dig going on just north of here."); +~chatplayer("So if they don't pass the exams they can't dig at all?"); +~chatnpc("That's right! We have to make sure that students know enough to be able to dig safely and not damage the artefacts."); + +def_int $choice = ~p_choice2("Can I take an exam?", 1, "Interesting...", 2); + +if ($choice = 1) { + ~chatplayer("Can I take an exam?"); + inv_add(inv, unstamped_letter, 1); + ~itexam_set_progress(^itexam_stamping); + ~send_quest_progress(questlist:itexam, ~itexam_progress, ^itexam_complete); + ~chatnpc("You can if you get this letter stamped by the Curator of Varrock's museum."); + ~chatplayer("Why's that then?"); + ~chatnpc("Because he is a very knowledgable man and employs our archeological expert. I'm sure he knows a lot about your exploits and can judge whenever you'd make a good archeologist or not."); + ~chatnpc("Besides, the museum contributes funds to the dig."); +} else { + ~chatplayer("Interesting..."); + ~chatnpc("You could gain much with an understanding of the world below."); +} + +//////////////////////////////////////////////// +// DELIVER STAMP +//////////////////////////////////////////////// + +[label,itexam_examiner_deliver_stamped_letter] +~chatplayer("Hello."); +~chatnpc("Hello again."); + +if (inv_total(inv, stamped_letter) > 0) { + ~chatplayer("Here is the stamped letter you asked for."); + ~chatnpc("Good, good. We will begin the exam..."); + inv_del(inv, stamped_letter, ^max_32bit_int); + ~itexam_set_progress(^itexam_first_exam); + @itexam_examiner_first_exam; +} else { + if (inv_total(bank, stamped_letter) > 0) { + ~mesbox("Perhaps you should fetch the Letter of Recommendation from your bank before talking to the examiner."); + return; + } + ~chatnpc("I am still waiting for your letter of recommendation."); + def_int $choice = ~p_choice2("I have lost the letter you gave me.", 1, "Alright I'll try and get it.", 2); + + if ($choice = 1) { + ~chatplayer("I have lost the letter you gave me."); + if (inv_total(inv, unstamped_letter) > 0) { + ~chatnpc("Oh now come on. You have it with you!"); + } else if (inv_total(bank, unstamped_letter) > 0) { + ~chatnpc("You already have the letter in your bank."); + } else { + inv_add(inv, unstamped_letter, 1); + ~chatnpc("That was foolish. Take this one and don't lose it!"); + } + } else { + ~chatplayer("Alright I'll try and get it."); + ~chatnpc("I am sure you won't get any problems. Speak to the Curator of Varrock's museum."); + } +} + +//////////////////////////////////////////////// +// TAKE FIRST EXAM +//////////////////////////////////////////////// + +[label,itexam_examiner_take_first_exam] +~chatplayer("Hello."); +~chatnpc("Hello again. Are you ready for another shot at the exam?"); +def_int $choice = ~p_choice2("Yes, I certainly am.", 1, "No, not at the moment.", 2); + +if ($choice = 1) { + ~chatplayer("Yes, I certainly am."); + @itexam_examiner_first_exam; +} else { + ~chatplayer("No, not at the moment."); + ~chatnpc("Okay, take your time if you wish."); +} + +//////////////////////////////////////////////// +// TAKE SECOND EXAM +//////////////////////////////////////////////// + +[label,itexam_examiner_take_second_exam] +~chatplayer("Hello."); +~chatnpc("Hi there!"); +def_int $choice = ~p_choice4("I am ready for the next exam.", 1, "I am stuck on a question.", 2, "Sorry, I didn't mean to disturb you.", 3, "I have lost my trowel.", 4); + +if ($choice = 1) { + ~chatplayer("I am ready for the next exam."); + @itexam_examiner_second_exam; +} else if ($choice = 2) { + ~chatplayer("I am stuck on a question."); + ~chatnpc("Well, well, have you not been doing any studies? I am not giving you the answers, talk to the other students and remember the answers."); +} else if ($choice = 3) { + ~chatplayer("Sorry, I didn't mean to disturb you."); + ~chatnpc("Oh, no problem at all."); +} else { + @itexam_examiner_lost_trowel; +} + +//////////////////////////////////////////////// +// TAKE THIRD EXAM +//////////////////////////////////////////////// + +[label,itexam_examiner_take_third_exam] +~chatplayer("Hello."); +~chatnpc("Hi there!"); +def_int $choice = ~p_choice4("I am ready for the last exam...", 1, "I am stuck on a question.", 2, "Sorry, I didn't mean to disturb you.", 3, "I have lost my trowel.", 4); + +if ($choice = 1) { + ~chatplayer("I am ready for the last exam..."); + @itexam_examiner_third_exam; +} else if ($choice = 2) { + ~chatplayer("I am stuck on a question."); + ~chatnpc("Well, well, have you not been doing any studies? I am not giving you the answers, talk to the other students and remember the answers."); +} else if ($choice = 3) { + ~chatplayer("Sorry, I didn't mean to disturb you."); + ~chatnpc("Oh, no problem at all."); +} else { + ~chatplayer("I have lost my trowel."); + // TODO: There's probably a bank check here too + if (inv_total(inv, trowel) > 0) { + ~chatnpc("Really? Look in your backpack and make sure first."); + } else { + ~chatnpc("Deary me... That was a good one as well. It's a good job I have another. Here you go..."); + inv_add(inv, trowel, 1); + } +} + +//////////////////////////////////////////////// +// FIRST EXAM +//////////////////////////////////////////////// + +[label,itexam_examiner_first_exam] +def_int $q1choice; +def_int $q2choice; +def_int $q3choice; + +~chatnpc("Okay, we will start with the first exam: Earth Sciences level 1 - Beginner."); +~chatnpc("Question 1 - Earth Sciences overview. Can you tell me what Earth Science is?"); + +if (~itexam_errand_progress(^itexam_errand_student1) = 2) { + $q1choice = ~p_choice3("The study of the earth, its contents, and history.", 1, "The study of planets and the history of the worlds.", 2, "The combination of archaeology and vegetarianism.", 3); + + if ($q1choice = 1) { + ~chatplayer("The study of the earth, its contents, and history."); + } else if ($q1choice = 2) { + ~chatplayer("The study of planets and the history of the worlds."); + } else { + ~chatplayer("The combination of archaeology and vegetarianism."); + } +} else { + $q1choice = ~p_choice3("The study of gardening, planting and fruiting vegetation.", 1, "The study of planets and the history of the worlds.", 2, "The combination of archaeology and vegetarianism.", 3); + + if ($q1choice = 1) { + ~chatplayer("The study of gardening, planting and fruiting vegetation."); + } else if ($q1choice = 2) { + ~chatplayer("The study of planets and the history of the worlds."); + } else { + ~chatplayer("The combination of archaeology and vegetarianism."); + } +} + +~chatnpc("Okay, next question..."); +~chatnpc("Earth Sciences level 1, question 2 - Eligibility. Can you tell me which people are allowed to use the digsite?"); + +if (~itexam_errand_progress(^itexam_errand_student2) = 2) { + $q2choice = ~p_choice3("Professors, students and workmen only.", 1, "Local residents, contractors and small pink fish.", 2, "All that have passed the appropriate Earth Sciences exam.", 3); + + if ($q2choice = 1) { + ~chatplayer("Professors, students and workmen only."); + } else if ($q2choice = 2) { + ~chatplayer("Local residents, contractors and small pink fish."); + } else { + ~chatplayer("All that have passed the appropriate Earth Sciences exam."); + } +} else { + $q2choice = ~p_choice3("Magic users, miners and their escorts.", 1, "Professors, students and workmen only.", 2, "Local residents, contractors and small pink fish.", 3); + + if ($q2choice = 1) { + ~chatplayer("Magic users, miners and their escorts."); + } else if ($q2choice = 2) { + ~chatplayer("Professors, students and workmen only."); + } else { + ~chatplayer("Local residents, contractors and small pink fish."); + } +} + +~chatnpc("Okay, next question..."); +~chatnpc("Earth Sciences level 1, question 3 - Health and safety. Can you tell me the proper safety points when working on a digsite?"); + +if (~itexam_errand_progress(^itexam_errand_student3) = 2) { + $q3choice = ~p_choice3("Rubber chickens to be worn on the head at all times.", 1, "Gloves and boots to be worn at all times; proper tools must be used.", 2, "Protective clothing to be worn; tools kept away from site.", 3); + + if ($q3choice = 1) { + ~chatplayer("Rubber chickens to be worn on the head at all times."); + } else if ($q3choice = 2) { + ~chatplayer("Gloves and boots to be worn at all times; proper tools must be used."); + } else { + ~chatplayer("Protective clothing to be worn; tools kept away from site."); + } +} else { + $q3choice = ~p_choice3("Heat-resistant clothing to be worn at all times.", 1, "Rubber chickens to be worn on the head at all times.", 2, "Protective clothing to be worn; tools kept away from site.", 3); + + if ($q3choice = 1) { + ~chatplayer("Heat-resistant clothing to be worn at all times."); + } else if ($q3choice = 2) { + ~chatplayer("Rubber chickens to be worn on the head at all times."); + } else { + ~chatplayer("Protective clothing to be worn; tools kept away from site."); + } +} +~chatnpc("That concludes the exam for Earth Sciences level 1."); +~chatnpc("Let's see how you did..."); + +def_int $correct_answer_count = 0; + +if (~itexam_errand_progress(^itexam_errand_student1) = 2 & $q1choice = 1) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if (~itexam_errand_progress(^itexam_errand_student2) = 2 & $q2choice = 3) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if (~itexam_errand_progress(^itexam_errand_student3) = 2 & $q3choice = 2) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if ($correct_answer_count = 3) { + ~itexam_set_progress(^itexam_second_exam); + ~itexam_reset_student_errands; + inv_add(inv, trowel, 1); + inv_add(inv, level_1_certificate, 1); + ~chatnpc("You got all the questions correct. Well done!"); + ~chatplayer("Hey! Excellent!"); + ~chatnpc("You have now passed the Earth Sciences level 1 general exam. Here is your certificate to prove it. You also get a decent trowel to dig with. Of course, you'll want to get studying for your next exam now!"); + // TODO: open certificate modal? likely didn't exist in 2004 +} else if ($correct_answer_count = 2) { + ~chatnpc("You got 2 questions correct. Not bad, just a little more revision needed."); + ~chatplayer("Oh well..."); +} else if ($correct_answer_count = 1) { + ~chatnpc("You got 1 question correct. Better luck next time."); + ~chatplayer("Oh bother!"); + ~chatnpc("Do some more research. I'm sure other students could help you out."); +} else { + ~chatnpc("Deary me! This is appalling, none correct at all! I suggest you go and study properly."); + ~chatplayer("Oh dear..."); + ~chatnpc("Why don't you use the resources here? There are the researchers, and you could even ask other students who are also studying for these exams."); +} + +//////////////////////////////////////////////// +// SECOND EXAM +//////////////////////////////////////////////// + +[label,itexam_examiner_second_exam] +def_int $q1choice; +def_int $q2choice; +def_int $q3choice; + +~chatnpc("Okay, this is the next part of the Earth Sciences exam: Earth Sciences level 2 - Intermediate."); +~chatnpc("Question 1 - Sample transportation. Can you tell me how we transport samples?"); + +if (~itexam_errand_progress(^itexam_errand_student1) = 2) { + $q1choice = ~p_choice3("Samples ground and suspended in an acid solution.", 1, "Samples to be given to the melon-collecting monkey.", 2, "Samples taken in rough form; kept only in sealed containers.", 3); + + if ($q1choice = 1) { + ~chatplayer("Samples ground and suspended in an acid solution."); + } else if ($q1choice = 2) { + ~chatplayer("Samples to be given to the melon-collecting monkey."); + } else { + ~chatplayer("Samples taken in rough form; kept only in sealed containers."); + } +} else { + $q1choice = ~p_choice3("Samples cut and cleaned before transportation.", 1, "Samples ground and suspended in an acid solution.", 2, "Samples to be given to the melon-collecting monkey.", 3); + + if ($q1choice = 1) { + ~chatplayer("Samples cut and cleaned before transportation."); + } else if ($q1choice = 2) { + ~chatplayer("Samples ground and suspended in an acid solution."); + } else { + ~chatplayer("Samples to be given to the melon-collecting monkey."); + } +} + +~chatnpc("Okay, next question..."); +~chatnpc("Earth Sciences level 2, question 2 - Handling of finds. What is the proper way to handle finds?"); + +if (~itexam_errand_progress(^itexam_errand_student2) = 2) { + $q2choice = ~p_choice3("Finds must be carefully handled, and gloves worn.", 1, "Finds to be given to the site workmen.", 2, "Drop them on the floor and jump on them.", 3); + + if ($q2choice = 1) { + ~chatplayer("Finds must be carefully handled, and gloves worn."); + } else if ($q2choice = 2) { + ~chatplayer("Finds to be given to the site workmen."); + } else { + ~chatplayer("Drop them on the floor and jump on them."); + } +} else { + $q2choice = ~p_choice3("Finds must not be handled by anyone.", 1, "Finds to be given to the site workmen.", 2, "Drop them on the floor and jump on them.", 3); + + if ($q2choice = 1) { + ~chatplayer("Finds must not be handled by anyone."); + } else if ($q2choice = 2) { + ~chatplayer("Finds to be given to the site workmen."); + } else { + ~chatplayer("Drop them on the floor and jump on them."); + } +} + +~chatnpc("Okay, next question..."); +~chatnpc("Earth Sciences level 2, question 3 - Rock pick usage. Can you tell me the proper use for a rock pick?"); + +if (~itexam_errand_progress(^itexam_errand_student3) = 2) { + $q3choice = ~p_choice3("Rock pick must be used flat and with a strong force.", 1, "Always handle with care; strike cleanly on its cleaving point.", 2, "Rock picks are to be used to milk cows on a rainy morning.", 3); + + if ($q3choice = 1) { + ~chatplayer("Rock pick must be used flat and with a strong force."); + } else if ($q3choice = 2) { + ~chatplayer("Always handle with care; strike cleanly on its cleaving point."); + } else { + ~chatplayer("Rock picks are to be used to milk cows on a rainy morning."); + } +} else { + $q3choice = ~p_choice3("Strike rock repeatedly until powdered.", 1, "Rock pick must be used flat and with a strong force.", 2, "Rock picks are to be used to milk cows on a rainy morning.", 3); + + if ($q3choice = 1) { + ~chatplayer("Strike rock repeatedly until powdered."); + } else if ($q3choice = 2) { + ~chatplayer("Rock pick must be used flat and with a strong force."); + } else { + ~chatplayer("Rock picks are to be used to milk cows on a rainy morning."); + } +} +~chatnpc("Okay, that covers the level 2 Earth Sciences exam."); +~chatnpc("Let me add up your total.."); + +def_int $correct_answer_count = 0; + +if (~itexam_errand_progress(^itexam_errand_student1) = 2 & $q1choice = 3) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if (~itexam_errand_progress(^itexam_errand_student2) = 2 & $q2choice = 1) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if (~itexam_errand_progress(^itexam_errand_student3) = 2 & $q3choice = 2) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if ($correct_answer_count = 3) { + ~itexam_set_progress(^itexam_third_exam); + ~itexam_reset_student_errands; + inv_add(inv, level_2_certificate, 1); + ~chatnpc("You got all the questions correct, well done!"); + ~chatplayer(" Great, I'm getting good at this."); + ~chatnpc("You have now passed the Earth Sciences level 2 intermediate exam. Here is your certificate. Of course, you'll want to get studying for your next exam now!"); + // TODO: open certificate modal? likely didn't exist in 2004 +} else if ($correct_answer_count = 2) { + ~chatnpc("You got 2 questions correct. Not too bad, but you can do better..."); + ~chatplayer("Nearly got it."); +} else if ($correct_answer_count = 1) { + ~chatnpc("You got 1 question correct. At least it's a start."); + ~chatplayer("Oh well..."); + ~chatnpc("Get out and explore the digsite, talk to people and learn!"); +} else { + ~chatnpc("No, no, no! This will not do. They are all wrong; start again!"); + ~chatplayer("Oh no!"); + ~chatnpc("More studying for you my ."); +} + +//////////////////////////////////////////////// +// THIRD EXAM +//////////////////////////////////////////////// + +[label,itexam_examiner_third_exam] +def_int $q1choice; +def_int $q2choice; +def_int $q3choice; + +~chatnpc("Attention, this is the final part of the Earth Sciences exam: Earth Sciences level 3 - Advanced."); +~chatnpc("Question 1 - Sample preparation. Can you tell me how we prepare samples?"); + +if (~itexam_errand_progress(^itexam_errand_student3) = 2) { + $q1choice = ~p_choice3("Samples cleaned, and carried only in specimen jars.", 1, "Sample types catalogued and carried by hand only.", 2, "Samples to be spread thickly with mashed banana.", 3); + + if ($q1choice = 1) { + ~chatplayer("Samples cleaned, and carried only in specimen jars."); + } else if ($q1choice = 2) { + ~chatplayer("Sample types catalogued and carried by hand only."); + } else { + ~chatplayer("Samples to be spread thickly with mashed banana."); + } +} else { + $q1choice = ~p_choice3("Samples may be mixed together safely.", 1, "Sample types catalogued and carried by hand only.", 2, "Samples to be spread thickly with mashed banana.", 3); + + if ($q1choice = 1) { + ~chatplayer("Samples may be mixed together safely."); + } else if ($q1choice = 2) { + ~chatplayer("Sample types catalogued and carried by hand only."); + } else { + ~chatplayer("Samples to be spread thickly with mashed banana."); + } +} + +~chatnpc("Okay, next question..."); +~chatnpc("Earth Sciences level 3, question 2 - Specimen brush use. What is the proper way to use a specimen brush?"); + +if (~itexam_errand_progress(^itexam_errand_student1) = 2) { + $q2choice = ~p_choice3("Brush carefully and slowly using short strokes.", 1, "Dipped in glue and stuck to a sheep's back.", 2, "Brush quickly and with force.", 3); + + if ($q2choice = 1) { + ~chatplayer("Brush carefully and slowly using short strokes."); + } else if ($q2choice = 2) { + ~chatplayer("Dipped in glue and stuck to a sheep's back."); + } else { + ~chatplayer("Brush quickly and with force."); + } +} else { + $q2choice = ~p_choice3("Brush quickly using a wet brush.", 1, "Dipped in glue and stuck to a sheep's back.", 2, "Brush quickly and with force.", 3); + + if ($q2choice = 1) { + ~chatplayer("Brush quickly using a wet brush."); + } else if ($q2choice = 2) { + ~chatplayer("Dipped in glue and stuck to a sheep's back."); + } else { + ~chatplayer("Brush quickly and with force."); + } +} + +~chatnpc("Okay, next question..."); +~chatnpc("Earth Sciences level 3, question 3 - Advanced techniques. Can you describe the technique for handling bones?"); + +if (~itexam_errand_progress(^itexam_errand_student2) = 2) { + $q3choice = ~p_choice3("Feed to hungry dogs.", 1, "Bones to be ground and tested for mineral content.", 2, "Handle bones very carefully and keep them away from other samples.", 3); + + if ($q3choice = 1) { + ~chatplayer("Feed to hungry dogs."); + } else if ($q3choice = 2) { + ~chatplayer("Bones to be ground and tested for mineral content."); + } else { + ~chatplayer("Handle bones very carefully and keep them away from other samples."); + } +} else { + $q3choice = ~p_choice3("Bones must not be taken from the digsite.", 1, "Feed to hungry dogs.", 2, "Samples to be given to the melon-collecting monkey.", 3); + + if ($q3choice = 1) { + ~chatplayer("Bones must not be taken from the digsite."); + } else if ($q3choice = 2) { + ~chatplayer("Feed to hungry dogs."); + } else { + ~chatplayer("Bones to be ground and tested for mineral content."); + } +} + +~chatnpc("Okay, that concludes the level 3 Earth Sciences exam."); +~chatnpc("Let me add up the results..."); + +def_int $correct_answer_count = 0; + +if (~itexam_errand_progress(^itexam_errand_student1) = 2 & $q1choice = 1) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if (~itexam_errand_progress(^itexam_errand_student2) = 2 & $q2choice = 1) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if (~itexam_errand_progress(^itexam_errand_student3) = 2 & $q3choice = 3) { + $correct_answer_count = calc($correct_answer_count + 1); +} + +if ($correct_answer_count = 3) { + ~itexam_set_progress(^itexam_impress_archeological_expert); + ~itexam_reset_student_errands; + inv_add(inv, level_3_certificate, 1); + ~chatnpc("You got all the questions correct, well done!"); + ~chatplayer("Hooray!"); + ~chatnpc("Congratulations! You have now passed the Earth Sciences level 3 exam. Here is your level 3 certificate."); + ~chatplayer("I can dig wherever I want now!"); + ~chatnpc("Perhaps you should use your newfound skills to find an artefact on the digsite that will impress the archaeological expert."); + // TODO: open certificate modal? likely didn't exist in 2004 +} else if ($correct_answer_count = 2) { + ~chatnpc("You got 2 questions correct. A little more study and you will pass it."); + ~chatplayer("I'm nearly there..."); +} else if ($correct_answer_count = 1) { + ~chatnpc("You got 1 question correct. Try harder!"); + ~chatplayer("Oh bother!"); +} else { + ~chatnpc("I cannot believe this! Absolutely none right at all. I doubt you did any research before you took this exam..."); + ~chatplayer("Ah... Yes... Erm.... I think I had better go and revise first!"); +} + +//////////////////////////////////////////////// +// DIGGING STAGE +//////////////////////////////////////////////// + +[label,itexam_examiner_go_digging] +~chatnpc("Well, what are you doing here? Get digging!"); +if (inv_total(inv, trowel) = 0) { + @itexam_examiner_lost_trowel; +} + +//////////////////////////////////////////////// +// AFTER QUEST +//////////////////////////////////////////////// + +[label,itexam_examiner_after_quest] +~chatnpc("Hello there! My colleague tells me you helped to uncover a hidden altar to the god Zaros."); +~chatnpc("A great scholar and archaeologist indeed! Good health and prosperity to you. "); + +def_int $choice = ~p_choice2("Thanks.", 1, "I have lost my trowel.", 2); + +if ($choice = 1) { + ~chatplayer("Thanks."); +} else { + @itexam_examiner_lost_trowel; +} + +[label,itexam_examiner_lost_trowel] +~chatplayer("I have lost my trowel."); +if (inv_total(inv, trowel) > 0) { + ~chatnpc("Really? Look in your backpack and make sure first."); +} else { + ~chatnpc("Deary me... That was a good one as well. It's a good job I have another. Here you go..."); + inv_add(inv, trowel, 1); +} \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/itexam_chemistry.rs2 b/data/src/scripts/quests/quest_itexam/scripts/itexam_chemistry.rs2 new file mode 100644 index 0000000000..894768199e --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/itexam_chemistry.rs2 @@ -0,0 +1,73 @@ +[opheldu,ammonium_nitrate] +switch_obj (last_useitem) { + case nitroglycerin : @itexam_mixed_chemicals1; + case default : ~displaymessage(^dm_default); +} + +[opheldu,charcoal] +switch_obj (last_useitem) { + case pestle_and_mortar : @grind_charcoal; + case default : ~displaymessage(^dm_default); +} + +[opheldu,mixed_chemicals1] +switch_obj (last_useitem) { + case ground_charcoal : @itexam_mixed_chemicals2; + case default : ~displaymessage(^dm_default); +} + +[opheldu,mixed_chemicals2] + +if (stat(herblore) < 10) { + // TODO: Unconfirmed message + mes("You need a Herblore level of 10 to mix this potion."); + return; +} +switch_obj (last_useitem) { + case arcenia_root : @itexam_explosive; + case default : ~displaymessage(^dm_default); +} + +[label,itexam_mixed_chemicals1] +inv_del(inv, ammonium_nitrate, 1); +inv_del(inv, nitroglycerin, 1); +inv_add(inv, mixed_chemicals1, 1); +stat_advance(herblore, 25); +mes("You mix the nitrate powder into the liquid."); +mes("It has produced a foul mixture."); + +[label,itexam_mixed_chemicals2] + +if (stat(herblore) < 10) { + // TODO: Unconfirmed message + mes("You need a Herblore level of 10 to mix this potion."); + return; +} +inv_del(inv, ground_charcoal, 1); +inv_del(inv, mixed_chemicals1, 1); +inv_add(inv, mixed_chemicals2, 1); +stat_advance(herblore, 25); +mes("You mix the charcoal into the liquid."); +mes("It has produced an even fouler mixture."); + +[label,itexam_explosive] + +if (stat(herblore) < 10) { + // TODO: Unconfirmed message + mes("You need a Herblore level of 10 to mix this potion."); + return; +} +mes("You mix the root into the mixture."); +mes("You produce a potentially explosive compound."); +anim(human_herbing_vial, 0); +sound_synth(grind, 0, 0); +~chatplayer("Excellent! This looks just right!"); +inv_del(inv, arcenia_root, 1); +inv_del(inv, mixed_chemicals2, 1); +inv_add(inv, chemical_compound, 1); +stat_advance(herblore, 25); + +[label,grind_charcoal] +inv_del(inv, charcoal, 1); +inv_add(inv, ground_charcoal, 1); +mes("You grind the charcoal to a powder."); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/panning_guide.rs2 b/data/src/scripts/quests/quest_itexam/scripts/panning_guide.rs2 new file mode 100644 index 0000000000..4c8f86863b --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/panning_guide.rs2 @@ -0,0 +1,65 @@ +[opnpc1,panning_guide] +~chatplayer("Hello, who are you?"); + +if (~itexam_testbit(^itexam_bit_panning_guide_tea_given) = false) { + ~chatnpc("Hello, I am the panning guide. I teach students how to pan in these waters. They're not permitted to do so until after they've had training and, of course, they must be invited to pan here too."); + @panning_guide_tea_errand; +} else { + ~chatnpc("Hello, I am the panning guide. I'm here to teach you how to pan for gold."); + ~chatplayer("Excellent!"); + ~chatnpc("Let me explain how panning works. First you need a panning tray. Use the tray in the panning points in the water and then search your tray."); + ~chatnpc("If you find any gold, take it to the archaeological expert up in the museum storage facility. He will calculate its value for you."); + @panning_guide_tell_me_more; +} + +[label,panning_guide_tea_errand] +~chatplayer("So how do I become invited then?"); +~chatnpc("I'm not supposed to let people pan here unless they have permission from the authorities first. Mind you, I could let you have a go if you're willing to do me a favour."); +~chatplayer("What's that?"); +~chatnpc("Well, to be honest, what I would really like is... a nice cup of tea!"); + +if (inv_total(inv, cup_of_tea) > 0) { + ~chatplayer("I've some here that you can have."); + inv_del(inv, cup_of_tea, 1); + ~chatnpc("Ah! Lovely! You can't beat a good cuppa... You're free to pan all you want."); + ~itexam_setbit(^itexam_bit_panning_guide_tea_given); +} else { + ~chatplayer("Tea?!"); + ~chatnpc("Absolutely, I'm parched!"); + ~chatnpc("If you could bring me one of those, I would be more than willing to let you pan here. I usually get some from Varrock but I'm busy at the moment."); +} + +[label,panning_guide_intervene] +~chatnpcnoturn("Hey! You can't pan yet!"); +~chatplayer("Why not?"); +~chatnpcnoturn("We do not allow the uninvited to pan here."); + +def_int $choice = ~p_choice2("OK, forget it.", 1, "So how do I become invited then?", 2); + +if ($choice = 1) { + ~chatplayer("Okay, forget it."); + ~chatnpc("You can of course use this place when you know what you are doing..."); + @panning_guide_tell_me_more; +} else { + @panning_guide_tea_errand; +} + +[label,panning_guide_tell_me_more] +def_int $choice = ~p_choice2("Can you tell me more about the tools an archaeologist uses?", 1, "Thank you!", 2); + +if ($choice = 1) { + ~chatplayer("Can you tell me more about the tools an archaeologist uses?"); + ~chatnpc("Of course! Let's see now... Rock picks are for splitting rocks or scraping away soil; you can get one from a cupboard in the Education Centre."); + ~chatplayer("What about sample jars?"); + ~chatnpc("I think you'll find them scattered about pretty much everywhere, but I know you can get one from a cupboard somewhere in the Education Centre, just like the rock pick!"); + ~chatplayer("Okay, what about a specimen brush?"); + ~chatnpc("We have a bit of a shortage of those at the moment. You could try borrowing one from a workman on the site... but I don't think they'd give it willingly."); + ~chatplayer("Sounds like I'll need to be sneaky to get one of those, then... Okay - trowel?"); + ~chatnpc("Ahh... that you must earn by passing your exams! The examiner holds those."); + ~chatplayer("Anything else?"); + ~chatnpc("If you need something identified or are not sure about something, give it to Terry; he's the archaeological expert in the next room."); + ~chatplayer("Ahh, ok thanks."); + +} else { + ~chatplayer("Thank you!"); +} \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/private_dig_worker.rs2 b/data/src/scripts/quests/quest_itexam/scripts/private_dig_worker.rs2 new file mode 100644 index 0000000000..a5a90ec153 --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/private_dig_worker.rs2 @@ -0,0 +1,49 @@ +[opnpc1,digsite_workman_cave] +switch_int (~itexam_progress) { + case ^itexam_complete : @digsite_workman_cave_quest_complete; + case default : @digsite_workman_cave_default; +} + +[label,digsite_workman_cave_default] +~chatplayer("Hello."); +~chatnpc("Well, well... I have a visitor. What are you doing here?"); + +if (~itexam_testbit(^itexam_bit_searched_bricks) = true) { + @multi4("I have been invited to research here.", digsite_workman_cave_invited_to_research, "I am not sure really.", digsite_workman_cave_not_sure, "I'm here to get rich, rich, rich!", digsite_workman_cave_not_rich_rich, "How could I move a large pile of rocks?", digsite_workman_cave_move_pile_of_rocks); +} else { + @multi3("I have been invited to research here.", digsite_workman_cave_invited_to_research, "I am not sure really.", digsite_workman_cave_not_sure, "I'm here to get rich, rich, rich!", digsite_workman_cave_not_rich_rich); +} + +[label,digsite_workman_cave_invited_to_research] +~chatplayer("I have been invited to research here."); +~chatnpc("Indeed, you must be someone special to be allowed down here."); + +def_int $choice = ~p_choice2("Do you know where to find a specimen jar?", 1, "I have things to do...", 2); + +if ($choice = 1) { + ~chatplayer("Do you know where to find a specimen jar?"); + ~chatnpc("Hmmm, let me think... Nope, can't help you there I'm afraid."); +} else { + ~chatplayer("I have things to do..."); + ~chatnpc("Of course, don't let me keep you."); +} + +[label,digsite_workman_cave_not_sure] +~chatplayer("I am not sure really."); +~chatnpc("A miner without a clue - how funny!"); + +[label,digsite_workman_cave_not_rich_rich] +~chatplayer("I'm here to get rich, rich, rich!"); +~chatnpc("Oh, well, don't forget that wealth and riches aren't everything."); + +[label,digsite_workman_cave_move_pile_of_rocks] +~chatplayer("How do you move a large pile of rocks?"); +~chatnpc("There used to be this chap that worked in the other shaft. He was working on an explosive chemical mixture to be used for clearing blocked areas underground."); +~chatnpc("He left in a hurry one day; something in the shaft scared him to death, but he didn't say what."); +~chatplayer("Oh?"); +~chatnpc("Rumour has it he'd been writing a book on his chemical mixture. I'm not sure what goes in it but I'm sure you'll find the stuff he was using scattered around the digsite. He left so quickly he didn't take anything with him. In fact, I still have a chest key he gave me to look after; perhaps it's more useful to you."); +inv_add(inv, digsite_chest_key, 1); +~objbox(digsite_chest_key, "Doug hands you a key.", 250, 0, divide(^objbox_height, 2)); + +[label,digsite_workman_cave_quest_complete] +~chatnpc("Well, hello again. Congratulations on your finds"); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/quest_itexam.rs2 b/data/src/scripts/quests/quest_itexam/scripts/quest_itexam.rs2 new file mode 100644 index 0000000000..e68feb82dd --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/quest_itexam.rs2 @@ -0,0 +1,41 @@ +// References: +// https://www.youtube.com/watch?v=TrSlu4__Rt4 +// https://www.youtube.com/watch?v=gqY4Azhtghg +// https://chisel.weirdgloop.org/varbs/display?varplayer=131 + +// workaround procs because varps 132-138 are likely being misused +// varps 132-134 are likely the student errand varps +// varp 135 is a multi bitflag for various quest states that is referenced by post qip (quest improvement project) varbits +// (see https://chisel.weirdgloop.org/varbs/display?varplayer=135) +[proc,itexam_reset_student_errands] +~itexam_set_errand_progress(^itexam_errand_student1, 0); +~itexam_set_errand_progress(^itexam_errand_student2, 0); +~itexam_set_errand_progress(^itexam_errand_student3, 0); + +[proc,itexam_progress]()(int) +return (getbit_range(%itexam_progress, 0, 3)); + +[proc,itexam_set_progress](int $progress); +%itexam_progress = setbit_range_toint(%itexam_progress, $progress, 0, 3); + +[proc,itexam_errand_progress](int $errand)(int) +// we're reserving 2 bits for each errand, 0 = not started, 1 = in progress, 2 = complete +def_int $bit_start = calc(^itexam_errands_offset + $errand * 2); +return (getbit_range(%itexam_progress, $bit_start, calc($bit_start + 1))); + +[proc,itexam_set_errand_progress](int $errand, int $progress) +def_int $bit_start = calc(^itexam_errands_offset + $errand * 2); +%itexam_progress = setbit_range_toint(%itexam_progress, $progress, $bit_start, calc($bit_start + 1)); + +[proc,itexam_testbit](int $bit)(boolean) +return (testbit(%itexam_progress, calc(^itexam_bits_offset + $bit))); + +[proc,itexam_setbit](int $bit) +%itexam_progress = setbit(%itexam_progress, calc(^itexam_bits_offset + $bit)); + +[queue,itexam_complete] +~itexam_set_progress(^itexam_complete); +stat_advance(mining, 153000); +stat_advance(herblore, 20000); +inv_add(inv, gold_bar, 2); +~send_quest_complete(questlist:itexam, trowel, 200, ^itexam_questpoints, "You have finished the Digsite Quest!"); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/student1.rs2 b/data/src/scripts/quests/quest_itexam/scripts/student1.rs2 new file mode 100644 index 0000000000..398ec41f3e --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/student1.rs2 @@ -0,0 +1,85 @@ +[opnpc1,student1] +// https://youtu.be/TrSlu4__Rt4?t=438 +def_int $itexam_progress = ~itexam_progress; +switch_int ($itexam_progress) { + case ^itexam_first_exam : @itexam_student1_errand; + case ^itexam_second_exam : @itexam_student1_second_exam_tips; + case ^itexam_third_exam : @itexam_student1_third_exam_tips; + case default : @student1_pre_quest; +} + +[opnpcu,student1] +def_obj $item = last_useitem; + +if ($item = cracked_rock_sample) { + ~chatplayer("Is this yours?"); + ~chatnpc("This? Oh no...."); +} else if ($item = rock_sample_1) { + @itexam_student1_deliver_sample; +} else { + ~displaymessage(^dm_default); +} + +[label,student1_pre_quest] +~chatplayer("Hello there."); +~chatnpc("Oh, hi. I'm studying hard for an exam."); +~chatplayer("What exam is that?"); +~chatnpc("It's the Earth Sciences exam."); +~chatplayer("Interesting...."); + +[label,itexam_student1_errand] +def_int $errand_state = ~itexam_errand_progress(^itexam_errand_student1); + +if ($errand_state = 0) { + ~chatplayer("Hello there."); + ~chatplayer("Can you help me with the Earth Sciences exams at all?"); + ~chatnpc("Well... Maybe I will if you help me with something."); + ~chatplayer("What's that?"); + ~chatnpc("I have lost my rock sample."); + ~chatplayer("What does it look like?"); + ~chatnpc("Err... Like a rock!"); + ~chatplayer("Well, that's not too helpful, there are lots of those around here; can you remember where you last had it?"); + ~chatnpc("It was around here for sure. Maybe someone picked it up?"); + ~chatplayer("Okay, I'll have a look for you."); + ~itexam_set_errand_progress(^itexam_errand_student1, 1); +} else if ($errand_state = 1) { + if (inv_total(inv, rock_sample_1) > 0) { + ~chatplayer("Hello there."); + @itexam_student1_deliver_sample; + } else { + ~chatplayer("How's the study going?"); + ~chatnpc("Very well thanks. Have you found my rock sample yet?"); + ~chatplayer("No sorry, not yet."); + ~chatnpc("Oh well, I am sure it's been picked up. Couldn't you try looking through some pockets?"); + } +} else { + ~chatnpc("How's it going?"); + ~chatplayer("I need more help with the exam."); + ~chatnpc("Well ok, this is what I have learned since I last spoke to you..."); + ~chatnpc("The study of Earth Sciences is: The study of the earth, its contents and history."); + ~chatplayer("Okay, I'll remember that."); +} + +[label,itexam_student1_deliver_sample] +~chatplayer("Is this your rock sample?"); +inv_del(inv, rock_sample_1, ^max_32bit_int); +~itexam_set_errand_progress(^itexam_errand_student1, 2); +~chatnpc("Oh wow! You've found it! Thank you so much. I'll be glad to tell you what I know about the exam."); +~chatnpc("The study of Earth Sciences is: The study of the earth, its contents and history."); +~chatplayer("Okay, I'll remember that."); + +[label,itexam_student1_second_exam_tips] +~chatnpc("How's it going?"); +~chatplayer("I need more help with the exam."); +~chatnpc("Well ok, this is what I have learned since I last spoke to you..."); +~itexam_set_errand_progress(^itexam_errand_student1, 2); +~chatnpc("Correct rock pick usage: Always handle with care; strike the rock cleanly on its cleaving point."); +~chatplayer("Okay, I'll remember that."); + +[label,itexam_student1_third_exam_tips] +~chatnpc("How's it going?"); +~chatplayer("I need more help with the exam."); +~chatnpc("Well ok, this is what I have learned since I last spoke to you..."); +~itexam_set_errand_progress(^itexam_errand_student1, 2); +~chatnpc("Specimen brush use: Brush carefully and slowly using short strokes."); +~chatplayer("Okay, I'll remember that. Thanks for all your help."); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/student2.rs2 b/data/src/scripts/quests/quest_itexam/scripts/student2.rs2 new file mode 100644 index 0000000000..f58f05ece6 --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/student2.rs2 @@ -0,0 +1,86 @@ +[opnpc1,student2] +// https://youtu.be/TrSlu4__Rt4?t=470 +def_int $itexam_progress = ~itexam_progress; +switch_int ($itexam_progress) { + case ^itexam_first_exam : @itexam_student2_errand; + case ^itexam_second_exam : @itexam_student2_second_exam_tips; + case ^itexam_third_exam : @itexam_student2_third_exam_tips; + case default : @student2_pre_quest; +} + +[opnpcu,student2] +def_obj $item = last_useitem; + +if ($item = cracked_rock_sample) { + ~chatplayer("Is this yours?"); + ~chatnpc("This broken rock? I hope not!"); +} else if ($item = rock_sample_2) { + @itexam_student2_deliver_sample; +} else { + ~displaymessage(^dm_default); +} + +[label,student2_pre_quest] +~chatplayer("Hello there."); +~chatnpc("Hello there; as you can see I am a student."); +~chatplayer("What are you doing here?"); +~chatnpc("Oh, I'm studying for the Earth Sciences exam."); +~chatplayer("Interesting... Perhaps I should study it as well."); + +[label,itexam_student2_errand] +def_int $errand_state = ~itexam_errand_progress(^itexam_errand_student2); + +~chatplayer("Hello there."); +if ($errand_state = 0) { + ~chatplayer("Can you help me with the Earth Sciences exams at all?"); + ~chatnpc("I can't do anything unless I find my rock sample."); + ~chatplayer("Hey this rings a bell."); + ~chatnpc("?"); + ~chatplayer("So if I find it you'll help me?"); + ~chatnpc("I sure will!"); + ~chatplayer("Any ideas where it may be?"); + ~chatnpc("All I remember is that I was working near the tents when I lost it."); + ~chatplayer("Okay, I'll see what I can do."); + ~itexam_set_errand_progress(^itexam_errand_student2, 1); +} else if ($errand_state = 1) { + if (inv_total(inv, rock_sample_2) > 0) { + @itexam_student2_deliver_sample; + } else { + ~chatplayer("How's the study going?"); + ~chatnpc("I'm getting there. Have you found my rock sample yet?"); + ~chatplayer("No sorry, not yet."); + ~chatnpc("Oh dear, I hope it didn't fall into the stream; I might never find it again."); + } +} else { + ~chatnpc("How's it going?"); + ~chatplayer("There are more exam questions I'm stuck on."); + ~chatnpc("Hey, I'll tell you what I've learned. That may help."); + ~chatnpc("The people eligible to use the digsite are: All that have passed the appropriate Earth Sciences exams."); + ~chatplayer("Thanks for the information."); +} + +[label,itexam_student2_deliver_sample] +~chatplayer("Look what I found!"); +inv_del(inv, rock_sample_2, ^max_32bit_int); +~itexam_set_errand_progress(^itexam_errand_student2, 2); +~chatnpc("Excellent! I'm so happy. Let me now help you with your exams..."); +~chatnpc("The people eligible to use the digsite are: All that have passed the appropriate Earth Sciences exams."); +~chatplayer("Thanks for the information."); + +[label,itexam_student2_second_exam_tips] +~chatplayer("Hello there."); +~chatnpc("How's it going?"); +~chatplayer("There are more exam questions I'm stuck on."); +~chatnpc("Hey, I'll tell you what I've learned. That may help."); +~itexam_set_errand_progress(^itexam_errand_student2, 2); +~chatnpc("Correct sample transportation: Samples taken in rough form; kept only in sealed containers."); +~chatplayer("Thanks for the information."); + +[label,itexam_student2_third_exam_tips] +~chatplayer("Hello there."); +~chatnpc("How's it going?"); +~chatplayer("There are more exam questions I'm stuck on."); +~chatnpc("Hey, I'll tell you what I've learned. That may help."); +~itexam_set_errand_progress(^itexam_errand_student2, 2); +~chatnpc("The proper technique for handling bones is: Handle bones carefully and keep them away from other samples."); +~chatplayer("Thanks for the information."); \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itexam/scripts/student3.rs2 b/data/src/scripts/quests/quest_itexam/scripts/student3.rs2 new file mode 100644 index 0000000000..00a11842ae --- /dev/null +++ b/data/src/scripts/quests/quest_itexam/scripts/student3.rs2 @@ -0,0 +1,113 @@ +[opnpc1,student3] +// https://youtu.be/TrSlu4__Rt4?t=508 +def_int $itexam_progress = ~itexam_progress; +switch_int ($itexam_progress) { + case ^itexam_first_exam : @itexam_student3_first_exam_tips; + case ^itexam_second_exam : @itexam_student3_second_exam_tips; + case ^itexam_third_exam : @itexam_student3_third_exam_tips; + case default : @student3_pre_quest; +} + +[opnpcu,student3] +def_obj $item = last_useitem; + +if ($item = cracked_rock_sample) { + ~chatnpc("Uh? That's not mine!"); +} else if ($item = rock_sample_3) { + @itexam_student3_deliver_sample; +} else { + ~displaymessage(^dm_default); +} + +[label,student3_pre_quest] +~chatplayer("Hello there."); +~chatnpc("Hi there. I'm studying for the Earth Sciences exam."); +~chatplayer("Interesting... This exam seems to be a popular one!"); + +[label,itexam_student3_first_exam_tips] +def_int $errand_state = ~itexam_errand_progress(^itexam_errand_student3); + +if ($errand_state = 0) { + ~chatplayer("Can you help me with the Earth Sciences exams at all?"); + ~chatnpc("I can if you help me..."); + ~chatplayer("How can I do that?"); + ~chatnpc("I have lost my rock sample."); + ~chatplayer("Do you know where you dropped it?"); + ~chatnpc("Well, I was doing a lot of walking that day... Oh yes, that's right - we were studying ceramics in fact, near the edge of the digsite."); + ~chatnpc("I found some pottery that seemed to match the design on those large urns."); + ~chatnpc("I was in the process of checking this out, and when we got back to the centre my rock sample had gone!"); + ~chatplayer("Leave it to me, I'll find it."); + ~chatnpc("Oh great! Thanks!"); + ~itexam_set_errand_progress(^itexam_errand_student3, 1); +} else if ($errand_state = 1) { + if (inv_total(inv, rock_sample_3) > 0) { + @itexam_student3_deliver_sample; + } else { + ~chatplayer("How's the study going?"); + ~chatnpc("Very well thanks. Have you found my lucky mascot yet?"); + ~chatplayer("No sorry, not yet."); + ~chatnpc("I'm sure it's just outside the digsite somewhere..."); + } +} else { + ~chatnpc("How's it going?"); + ~chatplayer("I am stuck on some more exam questions."); + ~chatnpc("Okay, I'll tell you my latest notes..."); + ~chatnpc("The proper health and safety points are: Leather gloves and boots to be worn at all times; proper tools must be used."); + ~chatplayer("Great, thanks for your advice."); +} + +[label,itexam_student3_deliver_sample] +~chatplayer("Guess what I found."); +inv_del(inv, rock_sample_3, ^max_32bit_int); +~itexam_set_errand_progress(^itexam_errand_student3, 2); +~chatnpc("Hey! My sample! Thanks ever so much. Let me help you with those questions now."); +~chatnpc("The proper health and safety points are: Leather gloves and boots to be worn at all times; proper tools must be used."); +~chatplayer("Great, thanks for your advice."); + +[label,itexam_student3_second_exam_tips] +~chatnpc("How's it going?"); +~chatplayer("I am stuck on some more exam questions."); +~chatnpc("Okay, I'll tell you my latest notes..."); +~itexam_set_errand_progress(^itexam_errand_student3, 2); +~chatnpc("Finds handling: Finds must be carefully handled, and gloves worn."); +~chatplayer("Great, thanks for your advice."); + +[label,itexam_student3_third_exam_tips] +def_int $errand_state = ~itexam_errand_progress(^itexam_errand_student3); + +if ($errand_state = 0) { + ~chatplayer("Hello there."); + ~chatnpc("What, you want more help?"); + ~chatplayer("Err... Yes please!"); + ~chatnpc("Well... It's going to cost you..."); + ~chatplayer("Oh, well how much?"); + ~chatnpc("I'll tell you what I would like: a precious stone. I don't find many of them. My favourites are opals; they are beautiful."); + ~chatnpc("Just like me! Tee hee hee!"); + ~chatplayer("Err... OK I'll see what I can do, but I'm not sure where I'd get one."); + ~chatnpc("Well, I have seen people get them from panning occasionally."); + ~chatplayer("OK, I'll see what I can turn up for you."); + ~itexam_set_errand_progress(^itexam_errand_student3, 1); +} else if ($errand_state = 1) { + ~chatplayer("Hello there."); + ~chatnpc("Oh, hi again. Did you bring me the opal?"); + + if (inv_total(inv, opal) > 0) { + ~chatplayer("Would an opal look like this by any chance?"); + ~chatnpc("Wow, great, you've found one. This will look beautiful set in my necklace. Thanks for that; now I'll tell you what I know..."); + inv_del(inv, opal, 1); + ~itexam_set_errand_progress(^itexam_errand_student3, 2); + ~chatnpc("Sample preparation: Samples cleaned, and carried only in specimen jars."); + ~chatplayer("Great, thanks for your advice."); + } else { + ~chatplayer("I haven't found one yet."); + ~chatnpc("Oh well, tell me when you do. Remember that they can be found around the digsite; perhaps try panning the river."); + } +} else { + ~chatnpc("How's it going?"); + ~chatplayer("I am stuck on some more exam questions."); + ~chatnpc("Okay, I'll tell you my latest notes..."); + ~chatnpc("Sample preparation: Samples cleaned, and carried only in specimen jars."); + ~chatplayer("Great, thanks for your advice."); +} + + diff --git a/data/src/scripts/quests/quest_itgronigen/configs/grave_of_scorpius.npc b/data/src/scripts/quests/quest_itgronigen/configs/grave_of_scorpius.npc index 221db42fd3..b1ce3cff5a 100644 --- a/data/src/scripts/quests/quest_itgronigen/configs/grave_of_scorpius.npc +++ b/data/src/scripts/quests/quest_itgronigen/configs/grave_of_scorpius.npc @@ -16,6 +16,7 @@ hitpoints=20 attack=23 strength=20 defence=23 +param=damagetype,^crush_style param=attack_anim,ghost_attack param=defend_anim,ghost_block param=death_anim,ghost_death @@ -24,6 +25,7 @@ param=defend_sound,ghost_hit param=death_sound,ghost_death param=death_drop,null param=undead,^true +// osrs stats and Vislvl match 1:1 [spirit_of_scorpius] vislevel=hide @@ -66,4 +68,5 @@ param=death_anim,smallscorpion_death param=attack_sound,insect_attack param=defend_sound,insect_hit param=death_sound,insect_death -param=death_drop,null \ No newline at end of file +param=death_drop,null +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.npc b/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.npc index 3f696a35fb..025bdfbf6e 100644 --- a/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.npc +++ b/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.npc @@ -83,6 +83,7 @@ param=death_anim,goblin_death param=attack_sound,goblin_attack param=defend_sound,goblin_hit param=death_sound,goblin_death +// osrs stats and Vislvl match 1:1 [observatory_professor_tower] vislevel=hide diff --git a/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.obj b/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.obj index b3807e7c92..b6d55305de 100644 --- a/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.obj +++ b/data/src/scripts/quests/quest_itgronigen/configs/quest_itgronigen.obj @@ -8,6 +8,7 @@ members=yes 2dzoom=840 2dyan=152 2dxan=256 +tradeable=no [keep_key] name=Keep key @@ -20,6 +21,7 @@ model=model_2372_obj 2dxan=328 weight=10g members=yes +tradeable=no [lens_mould] name=Lens mould @@ -31,6 +33,7 @@ model=model_2773_obj 2dxan=196 weight=1kg members=yes +tradeable=no [lens] name=Lens @@ -43,3 +46,4 @@ weight=3g 2dyan=84 2dxan=388 members=yes +tradeable=no diff --git a/data/src/scripts/quests/quest_itwatchtower/configs/quest_itwatchtower.obj b/data/src/scripts/quests/quest_itwatchtower/configs/quest_itwatchtower.obj index 65bee59b72..606a10ece5 100644 --- a/data/src/scripts/quests/quest_itwatchtower/configs/quest_itwatchtower.obj +++ b/data/src/scripts/quests/quest_itwatchtower/configs/quest_itwatchtower.obj @@ -12,6 +12,7 @@ recol1d=19937 2dxan=196 weight=4lb members=yes +tradeable=no [explodingvial] model=model_552_obj_wear @@ -32,6 +33,7 @@ weight=15g name=Vial desc=An infusion of water and jangerberries. members=yes +tradeable=no [mixture_guam_jangerberries] model=model_2789_obj @@ -45,6 +47,7 @@ desc=A mixture of jangerberries and guam leaves in a vial. 2dxan=84 weight=25g members=yes +tradeable=no [ogre_potion] name=Potion @@ -59,6 +62,7 @@ recol1d=23492 2dxan=84 weight=25g members=yes +tradeable=no [magic_ogre_potion] name=Magic ogre potion @@ -73,6 +77,7 @@ recol1d=17399 2dxan=84 weight=25g members=yes +tradeable=no [spell_scroll] name=Spell scroll @@ -87,6 +92,7 @@ model=model_2600_obj iop1=Read weight=10g members=yes +tradeable=no [shaman_robe] name=Shaman robe @@ -102,3 +108,4 @@ model=model_2786_obj iop1=Search weight=4lb members=yes +tradeable=no diff --git a/data/src/scripts/quests/quest_legends/configs/quest_legends.obj b/data/src/scripts/quests/quest_legends/configs/quest_legends.obj index 03ddf0bc53..795169cb5a 100644 --- a/data/src/scripts/quests/quest_legends/configs/quest_legends.obj +++ b/data/src/scripts/quests/quest_legends/configs/quest_legends.obj @@ -15,6 +15,7 @@ recol2d=17441 iop1=Read iop2=Complete weight=20g +tradeable=no [obj_715] name=Radimus notes @@ -32,6 +33,7 @@ recol2d=512 2dxan=380 iop1=Read weight=20g +tradeable=no [bullroarer] name=Bull roarer @@ -43,6 +45,7 @@ members=yes 2dxan=176 iop1=Swing weight=20g +tradeable=no [obj_717] name=Scrawled note @@ -68,6 +71,7 @@ womanwear=model_532_obj_wear,6 2dxan=248 iop1=Read weight=20g +tradeable=no [obj_718] name=A scribbled note @@ -93,6 +97,7 @@ womanwear=model_532_obj_wear,6 2dxan=248 iop1=Read weight=20g +tradeable=no [obj_719] name=Scrumpled note @@ -118,6 +123,7 @@ womanwear=model_532_obj_wear,6 2dxan=248 iop1=Read weight=20g +tradeable=no [obj_720] name=Sketch @@ -136,6 +142,7 @@ recol2d=17441 2dxan=380 iop1=Look weight=20g +tradeable=no [obj_721] name=Gold bowl @@ -151,6 +158,7 @@ recol2d=31528 2dyan=1856 2dxan=204 weight=800g +tradeable=no [obj_722] name=Blessed gold bowl @@ -166,6 +174,7 @@ recol2d=31528 2dyan=1856 2dxan=204 weight=800g +tradeable=no [obj_723] name=Golden bowl @@ -180,6 +189,7 @@ recol1d=31528 2dxan=204 iop1=Empty weight=1kg +tradeable=no [obj_724] name=Golden bowl @@ -194,6 +204,7 @@ recol1d=31528 2dxan=204 iop1=Empty weight=1kg +tradeable=no [obj_725] name=Golden bowl @@ -208,6 +219,7 @@ recol1d=31528 2dxan=204 iop1=Empty weight=1kg +tradeable=no [obj_726] name=Golden bowl @@ -222,6 +234,7 @@ recol1d=31528 2dxan=204 iop1=Empty weight=1kg +tradeable=no [obj_727] cost=2 @@ -237,7 +250,6 @@ womanwear=model_515_obj_wear,0 2dyan=940 2dxan=212 weight=12g -tradeable=yes [obj_729] name=Shamans tome @@ -253,6 +265,7 @@ recol2d=13889 members=yes iop1=Read weight=18oz +tradeable=no [obj_730] name=Book of binding @@ -275,6 +288,7 @@ recol5d=9151 members=yes iop1=Read weight=18oz +tradeable=no [obj_731] name=Enchanted vial @@ -288,6 +302,7 @@ members=yes manwear=model_561_obj_wear,0 womanwear=model_561_obj_wear,6 weight=10g +tradeable=no [holy_water] name=Holy water @@ -316,6 +331,7 @@ param=defend_anim,human_unarmedblock param=proj_launch,holy_water_launch param=proj_travel,holy_water_travel param=rangeattack_sound,thrown +tradeable=no [obj_733] name=Smashed glass @@ -329,7 +345,6 @@ model=model_2676_obj 2dyan=32 2dxan=412 weight=2g -tradeable=yes [obj_735] name=Yommi tree seeds @@ -346,6 +361,7 @@ members=yes stackable=yes op1=Look weight=1g +tradeable=no [obj_736] name=Yommi tree seeds @@ -362,6 +378,7 @@ members=yes stackable=yes op1=Look weight=1g +tradeable=no [obj_737] name=Snakeweed mixture @@ -375,6 +392,7 @@ recol1d=14273 2dxan=84 weight=25g members=yes +tradeable=no [obj_738] name=Ardrigal mixture @@ -388,6 +406,7 @@ members=yes 2dyan=1996 2dxan=84 weight=25g +tradeable=no [obj_739] name=Bravery potion @@ -402,6 +421,7 @@ members=yes 2dxan=84 iop1=Drink weight=25g +tradeable=no [obj_740] name=Blue hat @@ -423,6 +443,7 @@ womanhead=model_102_obj_wear weight=1lb param=magicattack,3 param=magicdefence,3 +tradeable=no [obj_741] name=Chunk of crystal @@ -433,6 +454,7 @@ members=yes 2dyof=1 2dzoom=660 weight=50g +tradeable=no [obj_742] name=Hunk of crystal @@ -443,6 +465,7 @@ members=yes 2dyof=1 2dzoom=660 weight=50g +tradeable=no [obj_743] name=Lump of crystal @@ -454,6 +477,7 @@ members=yes 2dzoom=510 2dyan=60 weight=50g +tradeable=no [obj_744] name=Heart crystal @@ -465,6 +489,7 @@ members=yes 2dzoom=660 weight=150g iop1=Look-at +tradeable=no [obj_745] name=Heart crystal @@ -476,6 +501,7 @@ members=yes 2dzoom=660 weight=150g iop1=Look-at +tradeable=no [obj_746] model=model_2614_obj @@ -503,6 +529,7 @@ param=slashattack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=stab_sound,stabsword_stab param=slash_sound,stabsword_slash +tradeable=no [obj_747] model=model_2733_obj @@ -529,6 +556,7 @@ param=slashattack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=stab_sound,stabsword_stab param=slash_sound,stabsword_slash +tradeable=no [obj_748] name=Holy force @@ -541,6 +569,7 @@ members=yes 2dxan=272 iop1=Cast Spell weight=20g +tradeable=no [obj_749] name=Yommi totem @@ -553,6 +582,7 @@ model=model_loc_870_8 2dyan=132 2dzan=1780 weight=3kg +tradeable=no [obj_750] name=Gilded totem @@ -573,3 +603,4 @@ recol4d=31554 2dzan=1780 weight=3kg members=yes +tradeable=no diff --git a/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.npc b/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.npc index f67a454f47..e1bf0602f2 100644 --- a/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.npc +++ b/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.npc @@ -35,10 +35,10 @@ param=damagetype,^stab_style param=attack_anim,dwarf_attack param=defend_anim,dwarf_block param=death_anim,dwarf_death -param=attack_sound,baxe_crush +param=attack_sound,gnome_hit // param=defend_sound,brassclash2 +param=death_sound,gnome_death // osrs side this npc use somereason gnome sound datas (notice but npc is graphical updated) -// sounds attack gnome_hit , defend brassclash2, death gnome_death [dwarf_youngster] vislevel=hide @@ -58,6 +58,8 @@ model4=model_2983_npc model5=model_2985_npc head1=model_5_npc_head param=death_anim,dwarf_death +hitpoints=6 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_5190 [dwarf_commander] vislevel=hide @@ -75,6 +77,8 @@ model4=model_2983_npc model5=model_2985_npc head1=model_0_npc_head param=death_anim,dwarf_death +hitpoints=16 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_5191 [nulodion] vislevel=hide diff --git a/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.obj b/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.obj index bf0f9ff962..565bbb0292 100644 --- a/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.obj +++ b/data/src/scripts/quests/quest_mcannon/configs/quest_mcannon.obj @@ -9,6 +9,7 @@ model=model_2595_obj 2dxan=320 weight=16kg members=yes +tradeable=no [tool_kit] name=Tool kit @@ -21,6 +22,7 @@ model=model_2679_obj 2dxan=432 weight=1lb members=yes +tradeable=no [mcannonball] name=Cannonball @@ -35,7 +37,6 @@ weight=8lb category=category_1176 members=yes cost=5 -tradeable=yes [nulodions_notes] name=Nulodion's notes. @@ -48,6 +49,7 @@ model=model_2600_obj iop1=Read weight=1oz members=yes +tradeable=no [ammo_mould] name=Ammo mould @@ -60,6 +62,7 @@ model=model_2706_obj cost=5 weight=10lb members=yes +tradeable=no [instruction_manual] name=Instruction manual @@ -72,6 +75,7 @@ iop1=Read cost=10 weight=18oz members=yes +tradeable=no [cannon_base] name=Cannon base @@ -87,7 +91,6 @@ iop1=Set-up weight=10kg category=cannon_parts members=yes -tradeable=yes [cannon_stand] name=Cannon stand @@ -101,7 +104,6 @@ cost=187500 weight=2lb category=cannon_parts members=yes -tradeable=yes [cannon_barrels] name=Cannon barrels @@ -114,7 +116,6 @@ cost=187500 weight=15kg category=cannon_parts members=yes -tradeable=yes [cannon_furnace] name=Cannon furnace @@ -129,7 +130,6 @@ cost=187500 weight=5kg category=cannon_parts members=yes -tradeable=yes [mcannon_railing] name=Railing @@ -142,3 +142,4 @@ weight=2kg 2dyan=280 2dxan=236 members=yes +tradeable=no diff --git a/data/src/scripts/quests/quest_murder/configs/quest_murder.obj b/data/src/scripts/quests/quest_murder/configs/quest_murder.obj index a5d9dd8043..77b3841882 100644 --- a/data/src/scripts/quests/quest_murder/configs/quest_murder.obj +++ b/data/src/scripts/quests/quest_murder/configs/quest_murder.obj @@ -19,6 +19,7 @@ category=murder_proofobj param=product,murder_flournecklace param=game_message,You sprinkle the flour on Anna's necklace. param=game_message2,The necklace is now coated with a thin layer of flour. +tradeable=no [murder_flournecklace] name=Silver necklace @@ -42,6 +43,7 @@ param=product,annas_print param=changesto,murder_necklace param=game_message,You use the flypaper on the flour covered necklace. param=game_message2,You have a clean impression of Anna's finger prints. +tradeable=no [murder_cup] name=Silver cup @@ -58,6 +60,7 @@ category=murder_proofobj param=product,murder_flourcup param=game_message,You sprinkle the flour on Bob's cup. param=game_message2,The cup is now coated with a thin layer of flour. +tradeable=no [murder_flourcup] name=Silver cup @@ -77,6 +80,7 @@ param=product,bobs_print param=changesto,murder_cup param=game_message,You use the flypaper on the flour covered cup. param=game_message2,You have a clean impression of Bob's finger prints. +tradeable=no [murder_bottle] name=Silver bottle @@ -94,6 +98,7 @@ category=murder_proofobj param=product,murder_flourbottle param=game_message,You sprinkle the flour on Carol's bottle. param=game_message2,The bottle is now coated with a thin layer of flour. +tradeable=no [murder_flourbottle] name=Silver bottle @@ -111,6 +116,7 @@ param=product,carols_print param=changesto,murder_bottle param=game_message,You use the flypaper on the flour covered bottle. param=game_message2,You have a clean impression of Carol's finger prints. +tradeable=no [murder_book] name=Silver book @@ -127,6 +133,7 @@ category=murder_proofobj param=product,murder_flourbook param=game_message,You sprinkle the flour on David's book. param=game_message2,The Book is now coated with a thin layer of flour. +tradeable=no [murder_flourbook] name=Silver book @@ -144,6 +151,7 @@ param=product,davids_print param=changesto,murder_book param=game_message,You use the flypaper on the flour covered book. param=game_message2,You have a clean impression of David's finger prints. +tradeable=no [murder_needle] name=Silver needle @@ -162,6 +170,7 @@ category=murder_proofobj param=product,murder_flourneedle param=game_message,You sprinkle the flour on Elizabeth's needle. param=game_message2,The Needle is now coated with a thin layer of flour. +tradeable=no [murder_flourneedle] name=Silver needle @@ -181,6 +190,7 @@ param=product,elizabeths_print param=changesto,murder_needle param=game_message,You use the flypaper on the flour covered needle. param=game_message2,You have a clean impression of Elizabeth's finger prints. +tradeable=no [murder_pot] name=Silver pot @@ -199,6 +209,7 @@ category=murder_proofobj param=product,murder_flourpot param=game_message,You sprinkle the flour on Frank's pot. param=game_message2,The Pot is now coated with a thin layer of flour. +tradeable=no [murder_flourpot] name=Silver pot @@ -218,6 +229,7 @@ param=product,franks_print param=changesto,murder_pot param=game_message,You use the flypaper on the flour covered pot. param=game_message2,You have a clean impression of Frank's finger prints. +tradeable=no [murder_red_thread] name=Criminals' thread @@ -232,6 +244,7 @@ recol1d=30753 2dyan=1872 2dxan=148 weight=2g +tradeable=no [murder_green_thread] name=Criminals' thread @@ -246,6 +259,7 @@ recol1d=992 2dyan=1872 2dxan=148 weight=2g +tradeable=no [murder_blue_thread] name=Criminals' thread @@ -260,6 +274,7 @@ recol1d=31 2dyan=1872 2dxan=148 weight=2g +tradeable=no [flypaper] name=Flypaper @@ -272,6 +287,7 @@ model=model_2350_obj 2dxan=320 members=yes weight=10g +tradeable=no [pungent_pot] name=Pungent pot @@ -286,6 +302,7 @@ recol1d=18529 2dyan=8 2dxan=112 weight=2lb +tradeable=no [criminals_dagger] name=Criminals' dagger @@ -303,6 +320,7 @@ category=murder_proofobj param=product,murder_flourdagger param=game_message,You sprinkle a small amount of flour on the murderweapon. param=game_message2,The murderweapon is now coated with a thin layer of flour. +tradeable=no [murder_flourdagger] name=Criminals' dagger @@ -321,6 +339,7 @@ param=product,unknown_print param=changesto,criminals_dagger param=game_message,You use the flypaper on the floury dagger. param=game_message2,You have a clean impression of the murderer's finger prints. +tradeable=no [killers_print] name=Killers' print @@ -333,6 +352,7 @@ desc=The fingerprints of the murderer. members=yes model=model_2416_obj weight=10g +tradeable=no [annas_print] name=Annas' print @@ -347,6 +367,7 @@ model=model_2416_obj weight=10g category=murder_printobj param=murder_id_value,1 +tradeable=no [bobs_print] name=Bobs' print @@ -361,6 +382,7 @@ model=model_2416_obj weight=10g category=murder_printobj param=murder_id_value,2 +tradeable=no [carols_print] name=Carols' print @@ -375,6 +397,7 @@ model=model_2416_obj weight=10g category=murder_printobj param=murder_id_value,3 +tradeable=no [davids_print] name=Davids' print @@ -389,6 +412,7 @@ model=model_2416_obj weight=10g category=murder_printobj param=murder_id_value,4 +tradeable=no [elizabeths_print] name=Elizabeths' print @@ -403,6 +427,7 @@ model=model_2416_obj weight=10g category=murder_printobj param=murder_id_value,5 +tradeable=no [franks_print] name=Franks' print @@ -417,6 +442,7 @@ model=model_2416_obj weight=10g category=murder_printobj param=murder_id_value,6 +tradeable=no [unknown_print] name=Unknown print @@ -428,4 +454,5 @@ model=model_2416_obj 2dzoom=1380 2dyan=84 2dxan=320 -weight=10g \ No newline at end of file +weight=10g +tradeable=no diff --git a/data/src/scripts/quests/quest_priest/configs/quest_priest.npc b/data/src/scripts/quests/quest_priest/configs/quest_priest.npc index 820e887c9b..75f42402e8 100644 --- a/data/src/scripts/quests/quest_priest/configs/quest_priest.npc +++ b/data/src/scripts/quests/quest_priest/configs/quest_priest.npc @@ -57,3 +57,4 @@ param=attack_sound,skeleton_attack param=defend_sound,skelly_hit param=death_sound,skeleton_death param=undead,^true +// TODO monster examine spell diff --git a/data/src/scripts/quests/quest_priest/configs/quest_priest.obj b/data/src/scripts/quests/quest_priest/configs/quest_priest.obj index 761d5c3b7f..94f59c3f47 100644 --- a/data/src/scripts/quests/quest_priest/configs/quest_priest.obj +++ b/data/src/scripts/quests/quest_priest/configs/quest_priest.obj @@ -15,6 +15,7 @@ wearpos=front manwear=model_280_obj_wear,0 womanwear=model_444_obj_wear,0 weight=10g +tradeable=no [ghost_skull] name=Skull @@ -28,3 +29,4 @@ model=model_2388_obj 2dxan=160 weight=80g param=no_alchemy,1 +tradeable=no diff --git a/data/src/scripts/quests/quest_priest/scripts/restless_ghost.rs2 b/data/src/scripts/quests/quest_priest/scripts/restless_ghost.rs2 index 8a31e6943d..4847e8b6fa 100644 --- a/data/src/scripts/quests/quest_priest/scripts/restless_ghost.rs2 +++ b/data/src/scripts/quests/quest_priest/scripts/restless_ghost.rs2 @@ -86,7 +86,7 @@ switch_int ($option) { ~chatplayer("My brother had EXACTLY the same problem."); ~chatnpc("Woo Wooooo!"); ~chatnpc("Wooooo Woo woo woo!"); - switch_int (~p_choice2("Goodbye. Thanks for the chat.", 1, "ou'll have to give me the recipe some time...", 2)) { + switch_int (~p_choice2("Goodbye. Thanks for the chat.", 1, "You'll have to give me the recipe some time...", 2)) { case 1 : @priest_ghost_goodbye; case 2 : ~chatplayer("You'll have to give me the recipe some time..."); diff --git a/data/src/scripts/quests/quest_prince/configs/quest_prince.obj b/data/src/scripts/quests/quest_prince/configs/quest_prince.obj index f9f0566675..3e1f712c44 100644 --- a/data/src/scripts/quests/quest_prince/configs/quest_prince.obj +++ b/data/src/scripts/quests/quest_prince/configs/quest_prince.obj @@ -7,6 +7,7 @@ model=model_2389_obj 2dyan=1988 2dxan=268 weight=10g +tradeable=no [wig_grey] model=model_2783_obj @@ -20,6 +21,7 @@ recol1d=23252 weight=10g name=Wig desc=A grey woollen wig. +tradeable=no [wig_blonde] model=model_2783_obj @@ -31,6 +33,7 @@ model=model_2783_obj weight=1lb name=Wig desc=A wig that has been dyed slightly blonde. +tradeable=no [paste] name=Paste @@ -44,6 +47,7 @@ recol1d=30385 2dyan=1920 2dxan=124 weight=15g +tradeable=no [bronze_key] name=Bronze key @@ -56,4 +60,5 @@ recol1d=8354 2dzoom=700 2dyan=20 2dxan=328 -weight=10g \ No newline at end of file +weight=10g +tradeable=no diff --git a/data/src/scripts/quests/quest_romeojuliet/configs/quest_romeojuliet.obj b/data/src/scripts/quests/quest_romeojuliet/configs/quest_romeojuliet.obj index 26fb395a0c..2fb33335c9 100644 --- a/data/src/scripts/quests/quest_romeojuliet/configs/quest_romeojuliet.obj +++ b/data/src/scripts/quests/quest_romeojuliet/configs/quest_romeojuliet.obj @@ -10,7 +10,6 @@ recol1d=30967 2dyan=668 2dxan=404 weight=7g -tradeable=yes [juliet_message] name=Message @@ -23,6 +22,7 @@ model=model_2600_obj 2dyan=120 2dxan=380 weight=20g +tradeable=no [cadaver] name=Cadaver @@ -35,3 +35,4 @@ recol1d=30967 2dyan=1996 2dxan=84 weight=25g +tradeable=no diff --git a/data/src/scripts/quests/quest_runemysteries/configs/quest_runemysteries.obj b/data/src/scripts/quests/quest_runemysteries/configs/quest_runemysteries.obj index 26c1a47084..c69a79079d 100644 --- a/data/src/scripts/quests/quest_runemysteries/configs/quest_runemysteries.obj +++ b/data/src/scripts/quests/quest_runemysteries/configs/quest_runemysteries.obj @@ -13,6 +13,7 @@ recol2d=10410 2dxan=160 weight=2lb param=no_alchemy,1 +tradeable=no [notes] name=Notes @@ -26,3 +27,4 @@ model=model_2600_obj 2dxan=380 weight=1oz param=no_alchemy,1 +tradeable=no diff --git a/data/src/scripts/quests/quest_scorpcatcher/configs/quest_scorpcatcher.obj b/data/src/scripts/quests/quest_scorpcatcher/configs/quest_scorpcatcher.obj index 8d674756d2..22631542f5 100644 --- a/data/src/scripts/quests/quest_scorpcatcher/configs/quest_scorpcatcher.obj +++ b/data/src/scripts/quests/quest_scorpcatcher/configs/quest_scorpcatcher.obj @@ -10,6 +10,7 @@ weight=150g name=Scorpion cage desc=It's empty! category=scorpcage +tradeable=no [scorpion_cage_first] members=yes @@ -23,6 +24,7 @@ weight=175g name=Scorpion cage desc=There is 1 scorpion inside. category=scorpcage +tradeable=no [scorpion_cage_first_second] members=yes @@ -36,6 +38,7 @@ weight=200g name=Scorpion cage desc=There are 2 scorpions inside. category=scorpcage +tradeable=no [scorpion_cage_first_third] cost=10 @@ -49,6 +52,7 @@ weight=200g name=Scorpion cage desc=There are 2 scorpions inside. category=scorpcage +tradeable=no [scorpion_cage_second] cost=10 @@ -62,6 +66,7 @@ weight=175g name=Scorpion cage desc=There is 1 scorpion inside. category=scorpcage +tradeable=no [scorpion_cage_second_third] name=Scorpion cage @@ -75,6 +80,7 @@ model=model_2703_obj 2dxan=156 weight=200g category=scorpcage +tradeable=no [scorpion_cage_third] cost=10 @@ -88,6 +94,7 @@ weight=175g name=Scorpion cage desc=There is 1 scorpion inside. category=scorpcage +tradeable=no [scorpion_cage_all] members=yes @@ -100,4 +107,5 @@ cost=10 weight=225g name=Scorpion cage desc=There are 3 scorpions inside. -category=scorpcage \ No newline at end of file +category=scorpcage +tradeable=no diff --git a/data/src/scripts/quests/quest_sheepherder/configs/quest_sheepherder.obj b/data/src/scripts/quests/quest_sheepherder/configs/quest_sheepherder.obj index 3e336fc0a3..e29831bcf3 100644 --- a/data/src/scripts/quests/quest_sheepherder/configs/quest_sheepherder.obj +++ b/data/src/scripts/quests/quest_sheepherder/configs/quest_sheepherder.obj @@ -25,6 +25,7 @@ param=slashattack_anim,human_sword_slash param=defend_anim,human_sword_defend2 param=stab_sound,stabsword_stab param=slash_sound,stabsword_slash +tradeable=no [poisoned_feed] name=Feed @@ -37,6 +38,7 @@ members=yes 2dyan=1936 2dxan=120 weight=5lb +tradeable=no [red_sheep_bones] name=Bones @@ -48,6 +50,7 @@ model=model_2674_obj 2dyan=368 2dxan=400 weight=3lb +tradeable=no [green_sheep_bones] name=Bones @@ -59,6 +62,7 @@ model=model_2674_obj 2dyan=368 2dxan=400 weight=3lb +tradeable=no [blue_sheep_bones] name=Bones @@ -70,6 +74,7 @@ model=model_2674_obj 2dyan=368 2dxan=400 weight=3lb +tradeable=no [yellow_sheep_bones] name=Bones @@ -81,6 +86,7 @@ model=model_2674_obj 2dyan=368 2dxan=400 weight=3lb +tradeable=no [plague_jacket] name=Plague jacket @@ -102,6 +108,7 @@ manwear2=model_150_obj_wear womanwear=model_459_obj_wear,0 womanwear2=model_331_obj_wear weight=6lb +tradeable=no [plague_trousers] name=Plague trousers @@ -120,3 +127,4 @@ wearpos2=feet manwear=model_273_obj_wear,0 womanwear=model_436_obj_wear,0 weight=5lb +tradeable=no diff --git a/data/src/scripts/quests/quest_squire/configs/quest_squire.obj b/data/src/scripts/quests/quest_squire/configs/quest_squire.obj index 11dc82a7f9..32601e13b3 100644 --- a/data/src/scripts/quests/quest_squire/configs/quest_squire.obj +++ b/data/src/scripts/quests/quest_squire/configs/quest_squire.obj @@ -7,6 +7,7 @@ model=model_2425_obj 2dyan=80 2dxan=288 weight=3lb +tradeable=no [blurite_sword] name=Blurite sword @@ -37,6 +38,7 @@ param=stabattack_anim,human_sword_stab param=defend_anim,human_sword_defend2 param=slash_sound,hacksword_slash param=stab_sound,hacksword_stab +tradeable=no [blurite_ore] cost=3 @@ -52,3 +54,4 @@ recol1d=15871 2dxan=368 weight=5lb category=category_91 +tradeable=no diff --git a/data/src/scripts/quests/quest_totem/configs/quest_totem.obj b/data/src/scripts/quests/quest_totem/configs/quest_totem.obj index 40bbda4d00..8cec88b190 100644 --- a/data/src/scripts/quests/quest_totem/configs/quest_totem.obj +++ b/data/src/scripts/quests/quest_totem/configs/quest_totem.obj @@ -10,6 +10,7 @@ members=yes 2dyan=108 2dxan=188 weight=3kg +tradeable=no [address_label] name=Address label @@ -23,6 +24,7 @@ members=yes 2dyan=1116 2dxan=244 weight=10g +tradeable=no [guide_book] name=Guide book @@ -35,4 +37,5 @@ recol1d=6342 2dzoom=840 2dyan=152 2dxan=256 -weight=16lb \ No newline at end of file +weight=16lb +tradeable=no diff --git a/data/src/scripts/quests/quest_tree/configs/gnome_battlefield.npc b/data/src/scripts/quests/quest_tree/configs/gnome_battlefield.npc index 478859f67b..049c557ce0 100644 --- a/data/src/scripts/quests/quest_tree/configs/gnome_battlefield.npc +++ b/data/src/scripts/quests/quest_tree/configs/gnome_battlefield.npc @@ -22,9 +22,9 @@ hitpoints=22 attack=17 strength=18 defence=12 -param=attackrate,6 -param=attackbonus,8 -param=strengthbonus,10 +param=attackrate,5 +param=attackbonus,9 +param=strengthbonus,5 param=stabdefence,33 param=slashdefence,34 param=crushdefence,29 @@ -36,6 +36,7 @@ param=defend_anim,human_blunt_defend2 param=attack_sound,baxe_crush // osrs param=defend_sound,blade2 // osrs attack sound warhammer_crush +// osrs stats and Vislvl match 1:1 [khazard_trooper_spear] name=Khazard trooper @@ -58,21 +59,22 @@ wanderrange=8 maxrange=10 hitpoints=22 attack=17 -strength=18 -defence=12 +strength=16 +defence=13 param=attackrate,6 param=attackbonus,8 param=strengthbonus,10 -param=stabdefence,33 -param=slashdefence,34 -param=crushdefence,29 +param=stabdefence,25 +param=slashdefence,25 +param=crushdefence,22 param=magicdefence,-7 -param=rangedefence,33 +param=rangedefence,-25 param=damagetype,^stab_style param=attack_anim,human_spear_pound param=defend_anim,human_spear_block param=attack_sound,staff_stab // param=defend_sound,blade5 +// osrs stats and Vislvl match 1:1 [khazard_warlord] name=Khazard warlord @@ -112,6 +114,7 @@ param=defend_anim,human_blunt_defend2 param=attack_sound,baxe_crush // osrs param=defend_sound,blade2 // osrs attack sound warhammer_crush +// osrs stats and Vislvl match 1:1 [khazard_commander] name=Khazard commander @@ -146,4 +149,5 @@ param=defend_anim,human_spear_def param=attack_sound,staff_stab // osrs param=defend_sound,blade2 huntmode=cowardly -huntrange=1 \ No newline at end of file +huntrange=1 +// osrs stats and Vislvl match 1:1 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_tree/configs/quest_tree.obj b/data/src/scripts/quests/quest_tree/configs/quest_tree.obj index 0fb71c5cf9..5af242a6ac 100644 --- a/data/src/scripts/quests/quest_tree/configs/quest_tree.obj +++ b/data/src/scripts/quests/quest_tree/configs/quest_tree.obj @@ -9,6 +9,7 @@ recol1d=15337 2dxan=48 weight=1kg code9=yes +tradeable=no [orbs_of_protection] name=Orb of protection @@ -22,6 +23,7 @@ recol1d=15337 2dxan=92 weight=2kg code9=yes +tradeable=no [gnome_amulet] name=Gnome amulet @@ -43,3 +45,4 @@ weight=10g param=stabdefence,13 param=slashdefence,13 param=crushdefence,13 +tradeable=no diff --git a/data/src/scripts/quests/quest_upass/configs/upass.npc b/data/src/scripts/quests/quest_upass/configs/upass.npc index 6a76d4b5f4..623a197ccd 100644 --- a/data/src/scripts/quests/quest_upass/configs/upass.npc +++ b/data/src/scripts/quests/quest_upass/configs/upass.npc @@ -89,7 +89,7 @@ model8=model_326_idk head1=model_48_npc_head head2=model_81_idk_head -[npc_977] +[blessed_spider] walkanim=giantspider_walk readyanim=giantspider_ready name=Blessed spider @@ -118,8 +118,10 @@ param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null huntmode=cowardly +// Stats match osrs version but our version Vislvl is different. +// wander and maxrange data taken rs3. -[npc_978] +[blessed_giant_rat] size=2 walkanim=giantrat_walk readyanim=giantrat_ready @@ -147,8 +149,9 @@ param=attack_sound,rat_attack param=defend_sound,rat_hit param=death_sound,rat_death huntmode=cowardly +// osrs stats and Vislvl match 1:1 -[npc_979] +[slave1_upass] vislevel=hide walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready @@ -170,7 +173,7 @@ model6=model_181_idk model7=model_176_idk head1=model_63_idk_head -[npc_980] +[slave2_upass] vislevel=hide walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready @@ -192,7 +195,7 @@ model6=model_181_idk model7=model_176_idk head1=model_52_idk_head -[npc_981] +[slave3_upass] vislevel=hide walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready @@ -214,7 +217,7 @@ model6=model_181_idk model7=model_176_idk head1=model_49_idk_head -[npc_982] +[slave4_upass] vislevel=hide walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready @@ -236,7 +239,7 @@ model6=model_181_idk model7=model_176_idk head1=model_47_npc_head -[npc_983] +[slave5_upass] vislevel=hide walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready @@ -260,7 +263,7 @@ model6=model_181_idk model7=model_176_idk head1=model_45_idk_head -[npc_984] +[slave6_upass] vislevel=hide walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready @@ -282,7 +285,7 @@ model6=model_181_idk model7=model_176_idk head1=model_48_npc_head -[npc_985] +[slave7_upass] vislevel=hide walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r readyanim=human_ready @@ -326,6 +329,11 @@ desc=The animal is caged here. vislevel=15 model1=model_2933_npc wanderrange=1 +hitpoints=19 +attack=11 +strength=13 +defence=13 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_9209 [sir_jerro] name=Sir Jerro @@ -371,6 +379,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 // TODO sounds // TODO sounds +// TODO monster examine spell [sir_carl] name=Sir Carl @@ -414,6 +423,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 // TODO sounds // TODO sounds +// TODO monster examine spell [sir_harry] name=Sir Harry @@ -457,6 +467,7 @@ param=attack_anim,human_sword_slash param=defend_anim,human_sword_defend2 // TODO sounds // TODO sounds +// TODO monster examine spell [half_souless] size=2 @@ -630,7 +641,9 @@ param=attack_sound,insect_attack param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null +huntrange=5 huntmode=cowardly +// TODO monster examine spell [othainian] size=3 @@ -658,7 +671,9 @@ param=attack_sound,demon_attack param=defend_sound,demon_hit param=death_sound,demon_death param=death_drop,ashes +huntrange=3 huntmode=cowardly +// TODO monster examine spell [doomion] size=3 @@ -686,7 +701,9 @@ param=attack_sound,demon_attack param=defend_sound,demon_hit param=death_sound,demon_death param=death_drop,ashes +huntrange=3 huntmode=cowardly +// TODO monster examine spell [holthion] size=3 @@ -714,7 +731,9 @@ param=attack_sound,demon_attack param=defend_sound,demon_hit param=death_sound,demon_death param=death_drop,ashes +huntrange=3 huntmode=cowardly +// TODO monster examine spell [iban_disciple] walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r @@ -746,6 +765,7 @@ attack=8 strength=8 defence=12 param=damagetype,^crush_style +// TODO monster examine spell [lord_iban] vislevel=hide @@ -775,10 +795,15 @@ model6=model_286_obj_wear model7=model_251_idk model8=model_265_obj_wear head1=model_83_idk_head -respawnrate=100 wanderrange=0 -timer=10 moverestrict=nomove +respawnrate=100 +hitpoints=87 +attack=76 +strength=78 +defence=77 +timer=10 +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_8998 [spider_upass] walkanim=spider_walk @@ -808,6 +833,7 @@ param=attack_sound,insect_attack param=defend_sound,insect_hit param=death_sound,insect_death param=death_drop,null +// osrs stats and Vislvl match 1:1 [bat_upass] name=Giant bat diff --git a/data/src/scripts/quests/quest_upass/configs/upass.obj b/data/src/scripts/quests/quest_upass/configs/upass.obj index 274efd6ccd..bef955fead 100644 --- a/data/src/scripts/quests/quest_upass/configs/upass.obj +++ b/data/src/scripts/quests/quest_upass/configs/upass.obj @@ -12,6 +12,7 @@ desc=Some rocks. model=model_2394_obj weight=1g members=yes +tradeable=no [obj_1481] name=Orb of light @@ -25,6 +26,7 @@ weight=1lb members=yes param=no_alchemy,1 param=orb_bit,^upass_orb1_bit +tradeable=no [obj_1482] name=Orb of light @@ -38,6 +40,7 @@ weight=1lb members=yes param=no_alchemy,1 param=orb_bit,^upass_orb2_bit +tradeable=no [obj_1483] name=Orb of light @@ -51,6 +54,7 @@ weight=1lb members=yes param=no_alchemy,1 param=orb_bit,^upass_orb3_bit +tradeable=no [obj_1484] name=Orb of light @@ -64,6 +68,7 @@ weight=1lb members=yes param=no_alchemy,1 param=orb_bit,^upass_orb4_bit +tradeable=no [damp_cloth] name=Damp cloth @@ -77,6 +82,7 @@ recol1d=8388 2dxan=368 weight=12g members=yes +tradeable=no [piece_of_railing] name=Piece of railing @@ -90,6 +96,7 @@ model=model_2826_obj 2dxan=240 weight=2kg members=yes +tradeable=no [upass_unicorn_horn] name=Unicorn horn @@ -103,6 +110,7 @@ model=model_2495_obj members=yes cost=20 weight=7g +tradeable=no [upass_jerro_badge] name=Paladin's badge @@ -116,6 +124,7 @@ model=model_2759_obj 2dxan=444 weight=12g members=yes +tradeable=no [upass_carl_badge] name=Paladin's badge @@ -131,6 +140,7 @@ recol1d=5474 2dxan=444 weight=12g members=yes +tradeable=no [upass_harry_badge] name=Paladin's badge @@ -146,6 +156,7 @@ recol1d=15556 2dxan=444 weight=12g members=yes +tradeable=no [upass_witches_cat] name=Witches cat @@ -161,6 +172,7 @@ recol1d=4228 2dxan=32 weight=1200g members=yes +tradeable=no [doll_of_iban] name=Doll of iban @@ -175,6 +187,7 @@ iop1=Search 2dyan=1736 2dxan=364 weight=300g +tradeable=no [old_journal] name=Old journal @@ -192,6 +205,7 @@ recol2d=23186 weight=8oz members=yes iop1=Read +tradeable=no [history_of_iban] name=History of iban @@ -205,6 +219,7 @@ model=model_2794_obj weight=8oz members=yes iop1=Read +tradeable=no [klanks_gauntlets] name=Klank's gauntlets @@ -232,6 +247,7 @@ param=stabdefence,8 param=slashdefence,9 param=crushdefence,7 param=strengthbonus,2 +tradeable=no [ibans_dove] name=Iban's dove @@ -244,6 +260,7 @@ model=model_2793_obj 2dxan=472 weight=100g members=yes +tradeable=no [amulet_of_othanian] name=Amulet of othanian @@ -261,6 +278,7 @@ recol2d=10240 2dxan=424 weight=10g members=yes +tradeable=no [amulet_of_doomion] name=Amulet of doomion @@ -278,6 +296,7 @@ recol2d=10240 2dxan=424 weight=10g members=yes +tradeable=no [amulet_of_holthion] name=Amulet of holthion @@ -295,6 +314,7 @@ recol2d=10240 2dxan=424 weight=10g members=yes +tradeable=no [ibans_shadow] name=Iban's shadow @@ -305,6 +325,7 @@ model=model_2811_obj 2dxan=92 weight=25g members=yes +tradeable=no [dwarf_brew] cost=2 @@ -319,6 +340,7 @@ recol1d=23073 weight=150g name=Dwarf brew desc=Smells stronger than most spirits. +tradeable=no [ibans_ashes] name=Iban's ashes @@ -332,4 +354,5 @@ recol1d=7399 2dyan=1892 2dxan=264 weight=2oz -members=yes \ No newline at end of file +members=yes +tradeable=no diff --git a/data/src/scripts/quests/quest_upass/scripts/kalrag.rs2 b/data/src/scripts/quests/quest_upass/scripts/kalrag.rs2 index aa6238fd54..2f6a2ab6f4 100644 --- a/data/src/scripts/quests/quest_upass/scripts/kalrag.rs2 +++ b/data/src/scripts/quests/quest_upass/scripts/kalrag.rs2 @@ -8,7 +8,7 @@ if (npc_findhero = true) { [queue,defeat_kalrag] npc_huntall(coord, 5, 0); while (npc_huntnext = true) { - if (npc_type = npc_977) { + if (npc_type = blessed_spider) { npc_setmode(opplayer2); } } @@ -32,7 +32,7 @@ if(%upass_progress = ^upass_found_doll) { } // Could you originally attack multiple spiders? -[ai_opplayer2,npc_977] ~blessedspider_attack; +[ai_opplayer2,blessed_spider] ~blessedspider_attack; [proc,blessedspider_attack] if (stat(hitpoints) = 0) { diff --git a/data/src/scripts/quests/quest_upass/scripts/upass_slave.rs2 b/data/src/scripts/quests/quest_upass/scripts/upass_slave.rs2 index 47e2f4fc8e..631269a403 100644 --- a/data/src/scripts/quests/quest_upass/scripts/upass_slave.rs2 +++ b/data/src/scripts/quests/quest_upass/scripts/upass_slave.rs2 @@ -1,10 +1,10 @@ -[opnpc1,npc_979] +[opnpc1,slave1_upass] mes("The man seems to be in a weak state of mind."); p_delay(2); ~chatplayer("Hello."); ~chatnpc("Eating me... they keep eating me! Eating me from the inside! Please stop them! I can feel them wriggling around inside me right now... please stop them!"); -[opnpc1,npc_980] +[opnpc1,slave2_upass] mes("The man seems to be in a weak state of mind."); p_delay(2); ~chatplayer("Hi."); @@ -13,7 +13,7 @@ p_delay(2); ~chatnpc("Blood is important. We must offer it to Zamorak every day as proof of our devotion. I just hope I don't run out!"); mes("The prisoner has clearly been here too long."); -[opnpc1,npc_981] +[opnpc1,slave3_upass] mes("The man seems to be in a weak state of mind."); p_delay(2); ~chatplayer("Hello, are you okay?"); @@ -23,7 +23,7 @@ p_delay(2); ~chatplayer("Actually I do."); ~chatnpc("You're welcome to have some with me of course..."); -[opnpc1,npc_982] +[opnpc1,slave4_upass] mes("The man seems to be in a weak state of mind."); p_delay(2); ~chatplayer("Hello there."); @@ -33,7 +33,7 @@ p_delay(2); ~chatplayer("Sorry, I don't under.."); ~chatnpc("Mwaarrr fnnntchh. Gbpp dng sktd delp? GBPP DNG SKTD DELP!"); -[opnpc1,npc_983] +[opnpc1,slave5_upass] mes("The man seems to be in a weak state of mind."); p_delay(2); ~chatplayer("Hello..."); @@ -41,14 +41,14 @@ p_delay(2); ~chatplayer("You're ill!"); ~chatnpc("What's that? You've never smelt it before? Well, let's just say that it's an acquired taste..."); -[opnpc1,npc_984] +[opnpc1,slave6_upass] mes("The man seems to be in a weak state of mind."); p_delay(2); ~chatplayer("Hello."); ~chatnpc("Danger, everywhere danger! But not from man nor beast! This is the danger that is inside you."); ~chatnpc("Bring it out, nurture it, cherish it. Stroke it like you would stroke a wounded bird... then strangle it before it takes hold of your very being. Don't say I didn't warn you."); -[opnpc1,npc_985] +[opnpc1,slave7_upass] mes("The man seems to be in a weak state of mind."); p_delay(2); ~chatplayer("Hello."); diff --git a/data/src/scripts/quests/quest_vampire/configs/quest_vampire.npc b/data/src/scripts/quests/quest_vampire/configs/quest_vampire.npc index 1f6dc289ce..b5cea0d49c 100644 --- a/data/src/scripts/quests/quest_vampire/configs/quest_vampire.npc +++ b/data/src/scripts/quests/quest_vampire/configs/quest_vampire.npc @@ -30,10 +30,12 @@ hitpoints=35 attack=30 strength=25 defence=30 -timer=1 param=stabdefence,2 param=slashdefence,1 param=crushdefence,3 +param=damagetype,^crush_style +timer=1 +// Stats match osrs version but our version Vislvl is different. [harlow] vislevel=hide diff --git a/data/src/scripts/quests/quest_vampire/configs/stake.obj b/data/src/scripts/quests/quest_vampire/configs/stake.obj index 1fc996f094..6e752f3b73 100644 --- a/data/src/scripts/quests/quest_vampire/configs/stake.obj +++ b/data/src/scripts/quests/quest_vampire/configs/stake.obj @@ -8,3 +8,4 @@ model=model_2680_obj weight=3oz name=Stake desc=A very pointy stick. +tradeable=no diff --git a/data/src/scripts/quests/quest_waterfall/configs/waterfall.obj b/data/src/scripts/quests/quest_waterfall/configs/waterfall.obj index 9778420c04..ae8266868f 100644 --- a/data/src/scripts/quests/quest_waterfall/configs/waterfall.obj +++ b/data/src/scripts/quests/quest_waterfall/configs/waterfall.obj @@ -11,6 +11,7 @@ recol1d=7456 members=yes iop1=Read weight=18oz +tradeable=no [golrie_key] name=A key @@ -23,6 +24,7 @@ model=model_2372_obj 2dxan=328 weight=10g members=yes +tradeable=no [glarials_pebble] name=Glarials pebble @@ -33,6 +35,7 @@ model=model_2701_obj 2dxan=236 weight=10g members=yes +tradeable=no [glarials_amulet] name=Glarials amulet @@ -51,6 +54,7 @@ manwear=model_283_obj_wear,0 womanwear=model_447_obj_wear,0 weight=10g members=yes +tradeable=no [glarials_urn_full] name=Glarials urn @@ -62,6 +66,7 @@ model=model_2704_obj 2dxan=68 weight=5oz members=yes +tradeable=no [glarials_urn_empty] name=Glarials urn @@ -73,6 +78,7 @@ model=model_2704_obj 2dxan=68 weight=3oz members=yes +tradeable=no [waterfall_key] name=A key @@ -85,6 +91,7 @@ model=model_2372_obj 2dxan=328 weight=10g members=yes +tradeable=no [mithril_seeds] name=Mithril seeds @@ -102,4 +109,3 @@ members=yes stackable=yes iop1=Plant weight=1oz -tradeable=yes diff --git a/data/src/scripts/quests/quest_zanaris/configs/quest_zanaris.obj b/data/src/scripts/quests/quest_zanaris/configs/quest_zanaris.obj index 1517a52316..2ca8b617bf 100644 --- a/data/src/scripts/quests/quest_zanaris/configs/quest_zanaris.obj +++ b/data/src/scripts/quests/quest_zanaris/configs/quest_zanaris.obj @@ -10,6 +10,7 @@ members=yes 2dyan=152 2dxan=268 weight=5lb +tradeable=no [dramenstaff] name=Dramen staff @@ -41,3 +42,4 @@ param=ready_baseanim,human_staffready param=crushattack_anim,human_staff_pound param=defend_anim,human_staff_def param=crush_sound,staff_hit +tradeable=no diff --git a/data/src/scripts/quests/quest_zanaris/configs/shamus.npc b/data/src/scripts/quests/quest_zanaris/configs/shamus.npc index bc997ed574..6e0985c568 100644 --- a/data/src/scripts/quests/quest_zanaris/configs/shamus.npc +++ b/data/src/scripts/quests/quest_zanaris/configs/shamus.npc @@ -10,5 +10,15 @@ model2=model_2896_npc model3=model_2915_npc head1=model_24_npc_head wanderrange=15 +hitpoints=16 +attack=10 +strength=10 +defence=7 +param=damagetype,^crush_style +param=attack_anim,midget_attackunarmed +param=defend_anim,midget_block param=death_anim,midget_death -param=death_sound,gnome_death \ No newline at end of file +param=attack_sound,gnome_attack +param=defend_sound,gnome_hit +param=death_sound,gnome_death +// https://raw.githubusercontent.com/Joshua-F/osrs-dumps/refs/heads/master/config/dump.npc npc_1162 \ No newline at end of file diff --git a/data/src/scripts/quests/quest_zanaris/configs/tree_spirit.npc b/data/src/scripts/quests/quest_zanaris/configs/tree_spirit.npc index 3043d03e64..1c1e4e5afe 100644 --- a/data/src/scripts/quests/quest_zanaris/configs/tree_spirit.npc +++ b/data/src/scripts/quests/quest_zanaris/configs/tree_spirit.npc @@ -27,3 +27,4 @@ param=defend_sound,ghost_hit param=death_sound,ghost_death param=death_drop,null param=undead,^true +// osrs stats and Vislvl match 1:1 diff --git a/data/src/scripts/quests/quest_zombiequeen/configs/quest_zombiequeen.npc b/data/src/scripts/quests/quest_zombiequeen/configs/quest_zombiequeen.npc new file mode 100644 index 0000000000..3ce1f3736a --- /dev/null +++ b/data/src/scripts/quests/quest_zombiequeen/configs/quest_zombiequeen.npc @@ -0,0 +1,328 @@ +[npc_500] +vislevel=hide +name=Mosol Rei +desc=Slightly under dressed. +walkanim=human_walk_f,human_walk_b,human_walk_l,human_walk_r +readyanim=human_staffready +op1=Talk-to +recol1s=14801 +recol1d=20804 +recol2s=24075 +recol2d=20804 +recol3s=24075 +recol3d=20804 +model1=model_206_idk +model2=model_249_idk +model3=model_315_npc +model4=model_173_npc +model5=model_176_idk +model6=model_279_npc +model7=model_181_idk +model8=model_553_npc +head1=model_46_idk_head +head2=model_81_idk_head + +[npc_501] +vislevel=hide +name=Zadimus' spirit. +desc=The animated spirit of a soul not at rest. +hasalpha=yes +walkanim=ghost_walk +readyanim=ghost_ready +hasalpha=yes +op1=Talk-to +model1=model_2962_npc +model2=model_2964_npc +model3=model_2965_npc +head1=model_27_npc_head +param=undead,^true +param=death_anim,ghost_death +param=death_sound,ghost_death + +[npc_502] +name=Undead One +desc=It rattles when it walks. +walkanim=skeleton_walk +readyanim=skeleton_ready +op2=Attack +vislevel=55 +recol1s=29562 +recol1d=22218 +model1=model_2944_npc +wanderrange=3 +maxrange=20 +respawnrate=100 +hitpoints=47 +attack=63 +strength=63 +defence=63 +magic=0 +ranged=0 +param=damagetype,^slash_style +param=attack_anim,skeleton_attack +param=defend_anim,skeleton_block +param=death_anim,skeleton_death +param=attack_sound,skeleton_attack +param=defend_sound,skelly_hit +param=death_sound,skeleton_death +param=undead,^true +huntmode=cowardly +huntrange=1 +category=undead_one +// Stats match osrs version but our version Vislvl is different. + +[npc_503] +name=Undead One +desc=A minion of Rashiliyia. +walkanim=skeleton_walk +readyanim=skeleton_ready +op2=Attack +vislevel=47 +recol1s=29562 +recol1d=26515 +model1=model_2944_npc +model2=model_2946_npc +wanderrange=3 +maxrange=20 +respawnrate=100 +hitpoints=47 +attack=55 +strength=55 +defence=55 +magic=0 +ranged=0 +param=attackbonus,7 +param=strengthbonus,5 +param=stabdefence,5 +param=slashdefence,5 +param=crushdefence,3 +param=magicdefence,1 +param=rangedefence,4 +param=damagetype,^slash_style +param=attack_anim,skeleton_attack +param=defend_anim,skeleton_block +param=death_anim,skeleton_death +param=attack_sound,skeleton_attack +param=defend_sound,skelly_hit +param=death_sound,skeleton_death +param=undead,^true +huntmode=cowardly +huntrange=1 +category=undead_one +// Stats match osrs version but our version Vislvl is different. + +[npc_504] +name=Undead One +desc=The animated dead, one of Rashiliyias' minions. +walkanim=zombie_walk +readyanim=zombie_ready +op2=Attack +vislevel=50 +recol1s=4526 +recol1d=12777 +recol2s=4322 +recol2d=8417 +recol3s=10240 +recol3d=7142 +recol4s=28538 +recol4d=24393 +recol5s=2081 +recol5d=9408 +model1=model_2931_npc +respawnrate=100 +hitpoints=47 +attack=63 +strength=63 +defence=63 +magic=0 +ranged=0 +param=damagetype,^slash_style +param=attack_anim,zombie_attack +param=defend_anim,zombie_block +param=death_anim,zombie_death +param=attack_sound,zombie_attack +param=defend_sound,zombie_hit +param=death_sound,zombie_death +param=undead,^true +param=death_drop,null +huntmode=cowardly +huntrange=1 +category=undead_one +// Stats match osrs version but our version Vislvl is different. + +[npc_505] +name=Undead One +desc=The animated dead, one of Rashiliyias' minions. +walkanim=zombie_walk +readyanim=zombie_ready +op2=Attack +vislevel=62 +recol1s=4526 +recol1d=11690 +recol2s=4322 +recol2d=8417 +recol3s=10240 +recol3d=26545 +recol4s=28538 +recol4d=24393 +recol5s=2081 +recol5d=9408 +model1=model_2931_npc +model2=model_2932_npc +wanderrange=3 +maxrange=20 +respawnrate=100 +hitpoints=59 +attack=65 +strength=65 +defence=65 +magic=0 +ranged=0 +param=attackbonus,4 +param=strengthbonus,5 +param=damagetype,^slash_style +param=attack_anim,zombie_attack +param=defend_anim,zombie_block +param=death_anim,zombie_death +param=attack_sound,zombie_attack +param=defend_sound,zombie_hit +param=death_sound,zombie_death +param=undead,^true +param=death_drop,null +huntmode=cowardly +huntrange=1 +category=undead_one +// Stats match osrs version but our version Vislvl is different. + +[npc_506] +vislevel=hide +name=Rashiliyia +desc=The animated spirit of Rashiliyia the Zombie Queen. +walkanim=ghost_walk +readyanim=ghost_ready +hasalpha=yes +op1=Talk-to +recol1s=6144 +recol1d=3363 +recol2s=15855 +recol2d=14724 +recol3s=24075 +recol3d=15979 +recol4s=6273 +recol4d=20104 +recol5s=20870 +recol5d=8712 +recol6s=12352 +recol6d=3363 +model1=model_2960_npc +model2=model_2963_npc +model3=model_2965_npc +head1=model_113_idk_head +param=undead,^true +param=death_anim,ghost_death +param=death_sound,ghost_death + +[npc_507] +name=Nazastarool +desc=A giant zombie of huge strength and devastating power. +walkanim=zombie_walk +readyanim=zombie_ready +resizev=190 +resizeh=190 +op2=Attack +vislevel=86 +recol1s=4526 +recol1d=11690 +recol2s=4322 +recol2d=8417 +recol3s=10240 +recol3d=26545 +recol4s=28538 +recol4d=24393 +recol5s=2081 +recol5d=9408 +model1=model_2931_npc +hitpoints=70 +attack=85 +strength=80 +defence=80 +magic=0 +ranged=0 +param=damagetype,^slash_style +param=attack_anim,zombie_attack +param=defend_anim,zombie_block +param=death_anim,zombie_death +param=attack_sound,zombie_attack +param=defend_sound,zombie_hit +param=death_sound,zombie_death +param=undead,^true +param=death_drop,null +// Stats match osrs version but our version Vislvl is different. + +[npc_508] +name=Nazastarool +desc=A giant skeleton of huge strength and devastating power. +walkanim=skeleton_walk +readyanim=skeleton_ready +resizev=190 +resizeh=190 +op2=Attack +vislevel=65 +recol1s=29562 +recol1d=26515 +model1=model_2944_npc +model2=model_2946_npc +hitpoints=70 +attack=58 +strength=54 +defence=58 +magic=0 +ranged=0 +param=attackbonus,15 +param=strengthbonus,15 +param=stabdefence,5 +param=slashdefence,5 +param=crushdefence,5 +param=magicdefence,5 +param=rangedefence,5 +param=damagetype,^slash_style +param=attack_anim,skeleton_attack +param=defend_anim,skeleton_block +param=death_anim,skeleton_death +param=attack_sound,skeleton_attack +param=defend_sound,skelly_hit +param=death_sound,skeleton_death +param=undead,^true +param=death_drop,null +// Stats match osrs version but our version Vislvl is different. + +[npc_509] +name=Nazastarool +desc=A giant ghost of huge strength and devastating power. +hasalpha=yes +walkanim=ghost_walk +readyanim=ghost_ready +resizev=190 +resizeh=190 +op2=Attack +vislevel=88 +model1=model_2961_npc +model2=model_2964_npc +model3=model_2965_npc +head1=model_10_npc_head +hitpoints=80 +attack=85 +strength=80 +defence=80 +magic=0 +ranged=0 +param=damagetype,^slash_style +param=attack_anim,ghost_attack +param=defend_anim,ghost_block +param=death_anim,ghost_death +param=attack_sound,ghost_attack +param=defend_sound,ghost_hit +param=death_sound,ghost_death +param=undead,^true +param=death_drop,null +// Stats match osrs version but our version Vislvl is different. \ No newline at end of file diff --git a/data/src/scripts/quests/quest_zombiequeen/configs/quest_zombiequeen.obj b/data/src/scripts/quests/quest_zombiequeen/configs/quest_zombiequeen.obj index b5efc51c15..1619a6a6b0 100644 --- a/data/src/scripts/quests/quest_zombiequeen/configs/quest_zombiequeen.obj +++ b/data/src/scripts/quests/quest_zombiequeen/configs/quest_zombiequeen.obj @@ -10,6 +10,7 @@ model=model_2654_obj members=yes iop1=Inspect weight=10g +tradeable=no [bone_key] name=Bone key @@ -24,6 +25,7 @@ recol1d=32767 2dxan=328 members=yes weight=10g +tradeable=no [stoneplaque] name=Stone-plaque @@ -37,6 +39,7 @@ model=model_2510_obj iop1=Read weight=800g members=yes +tradeable=no [tattered_scroll] name=Tattered scroll @@ -52,6 +55,7 @@ recol1d=29398 iop1=Read weight=20g members=yes +tradeable=no [crumpled_scroll] name=Crumpled scroll @@ -67,6 +71,7 @@ recol1d=16015 iop1=Read weight=20g members=yes +tradeable=no [rashiliya_corpse] name=Rashiliya corpse @@ -79,6 +84,7 @@ model=model_2595_obj 2dxan=320 weight=300g members=yes +tradeable=no [zadimus_corpse] name=Zadimus corpse @@ -92,6 +98,7 @@ model=model_2595_obj iop1=Bury weight=500g members=yes +tradeable=no [zqcrystal] name=Locating crystal @@ -105,6 +112,7 @@ model=model_2744_obj members=yes iop1=Activate weight=2lb +tradeable=no [zqcrystal_blue] name=Locating crystal @@ -119,6 +127,7 @@ recol1d=8443 2dxan=120 weight=2lb members=yes +tradeable=no [zqcrystal_red] name=Locating crystal @@ -134,6 +143,7 @@ recol1d=26889 2dxan=120 weight=2lb members=yes +tradeable=no [zqcrystal_yellow] name=Locating crystal @@ -149,6 +159,7 @@ recol1d=27594 2dxan=120 weight=2lb members=yes +tradeable=no [zqcrystal_white] name=Locating crystal @@ -164,6 +175,7 @@ recol1d=32767 2dxan=120 weight=2lb members=yes +tradeable=no [zqbeadsofthedead] name=Beads of the dead @@ -194,6 +206,7 @@ param=magicdefence,1 param=rangedefence,1 param=strengthbonus,1 param=prayerbonus,1 +tradeable=no [zqcoins] cost=1 @@ -206,6 +219,7 @@ model=model_2667_obj 2dxan=184 weight=2g members=yes +tradeable=no [zqbonebeads] name=Bone beads @@ -217,6 +231,7 @@ model=model_2561_obj 2dxan=304 weight=1g members=yes +tradeable=no [zqpommel] name=Sword pommel @@ -230,6 +245,7 @@ cost=1 2dxan=604 weight=3oz members=yes +tradeable=no [bervirius_notes] name=Bervirius notes @@ -246,6 +262,7 @@ recol1d=16919 iop1=Read weight=20g members=yes +tradeable=no [wampum_belt] name=Wampum belt @@ -257,3 +274,4 @@ model=model_3155_obj 2dxan=436 weight=1lb members=yes +tradeable=no diff --git a/data/src/scripts/skill_combat/configs/magic/battlestaves.obj b/data/src/scripts/skill_combat/configs/magic/battlestaves.obj index 79e6f3774e..af04c05af4 100644 --- a/data/src/scripts/skill_combat/configs/magic/battlestaves.obj +++ b/data/src/scripts/skill_combat/configs/magic/battlestaves.obj @@ -14,7 +14,6 @@ manwear=model_534_obj_wear,0 womanwear=model_534_obj_wear,6 category=weapon_staff weight=5lb -tradeable=yes param=stabattack,7 param=slashattack,-1 param=crushattack,25 @@ -51,7 +50,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,7 param=slashattack,-1 param=crushattack,28 @@ -88,7 +86,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,7 param=slashattack,-1 param=crushattack,28 @@ -123,7 +120,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,7 param=slashattack,-1 param=crushattack,28 @@ -160,7 +156,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,7 param=slashattack,-1 param=crushattack,28 diff --git a/data/src/scripts/skill_combat/configs/magic/mysticstaves.obj b/data/src/scripts/skill_combat/configs/magic/mysticstaves.obj index b0749f25c7..560fbc759f 100644 --- a/data/src/scripts/skill_combat/configs/magic/mysticstaves.obj +++ b/data/src/scripts/skill_combat/configs/magic/mysticstaves.obj @@ -19,7 +19,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,10 param=slashattack,-1 param=crushattack,40 @@ -56,7 +55,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,10 param=slashattack,-1 param=crushattack,40 @@ -91,7 +89,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,10 param=slashattack,-1 param=crushattack,40 @@ -128,7 +125,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,10 param=slashattack,-1 param=crushattack,40 diff --git a/data/src/scripts/skill_combat/configs/magic/staves.obj b/data/src/scripts/skill_combat/configs/magic/staves.obj index 7384c4f4cd..2ec464d67d 100644 --- a/data/src/scripts/skill_combat/configs/magic/staves.obj +++ b/data/src/scripts/skill_combat/configs/magic/staves.obj @@ -13,7 +13,6 @@ manwear=model_534_obj_wear,0 womanwear=model_534_obj_wear,6 category=weapon_staff weight=4lb -tradeable=yes param=slashattack,-1 param=crushattack,7 param=magicattack,4 @@ -46,7 +45,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=slashattack,-1 param=crushattack,7 param=magicattack,10 @@ -81,7 +79,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=slashattack,-1 param=crushattack,7 param=magicattack,10 @@ -116,7 +113,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes respawnrate=2000 param=stabattack,1 param=slashattack,-1 @@ -153,7 +149,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,3 param=slashattack,-1 param=crushattack,9 @@ -188,7 +183,6 @@ womanwear=model_534_obj_wear,6 womanwear2=model_567_obj_wear category=weapon_staff weight=5lb -tradeable=yes param=stabattack,2 param=slashattack,-1 param=crushattack,10 diff --git a/data/src/scripts/skill_combat/configs/melee/2hswords.obj b/data/src/scripts/skill_combat/configs/melee/2hswords.obj index 2f2902d70e..d7c200fdf8 100644 --- a/data/src/scripts/skill_combat/configs/melee/2hswords.obj +++ b/data/src/scripts/skill_combat/configs/melee/2hswords.obj @@ -17,7 +17,6 @@ manwear=model_546_obj_wear,0 womanwear=model_546_obj_wear,6 category=weapon_2h_sword weight=8lb -tradeable=yes param=stabattack,-4 param=slashattack,9 param=crushattack,8 @@ -51,7 +50,6 @@ manwear=model_546_obj_wear,0 womanwear=model_546_obj_wear,6 category=weapon_2h_sword weight=8lb -tradeable=yes param=stabattack,-4 param=slashattack,13 param=crushattack,10 @@ -83,7 +81,6 @@ manwear=model_546_obj_wear,0 womanwear=model_546_obj_wear,6 category=weapon_2h_sword weight=8lb -tradeable=yes param=stabattack,-4 param=slashattack,21 param=crushattack,16 @@ -117,7 +114,6 @@ manwear=model_546_obj_wear,0 womanwear=model_546_obj_wear,6 category=weapon_2h_sword weight=8lb -tradeable=yes param=stabattack,-4 param=slashattack,27 param=crushattack,21 @@ -151,7 +147,6 @@ manwear=model_546_obj_wear,0 womanwear=model_546_obj_wear,6 category=weapon_2h_sword weight=7lb -tradeable=yes param=stabattack,-4 param=slashattack,30 param=crushattack,24 @@ -185,7 +180,6 @@ manwear=model_546_obj_wear,0 womanwear=model_546_obj_wear,6 category=weapon_2h_sword weight=9lb -tradeable=yes param=stabattack,-4 param=slashattack,43 param=crushattack,30 @@ -219,7 +213,6 @@ manwear=model_546_obj_wear,0 womanwear=model_546_obj_wear,6 category=weapon_2h_sword weight=8lb -tradeable=yes param=stabattack,-4 param=slashattack,69 param=crushattack,50 diff --git a/data/src/scripts/skill_combat/configs/melee/battleaxes.obj b/data/src/scripts/skill_combat/configs/melee/battleaxes.obj index d3305034ce..1e608d7683 100644 --- a/data/src/scripts/skill_combat/configs/melee/battleaxes.obj +++ b/data/src/scripts/skill_combat/configs/melee/battleaxes.obj @@ -16,7 +16,6 @@ manwear=model_550_obj_wear,0 womanwear=model_550_obj_wear,6 category=weapon_axe weight=6lb -tradeable=yes param=stabattack,-2 param=slashattack,8 param=crushattack,5 @@ -45,7 +44,6 @@ manwear=model_550_obj_wear,0 womanwear=model_550_obj_wear,6 category=weapon_axe weight=6lb -tradeable=yes param=stabattack,-2 param=slashattack,16 param=crushattack,11 @@ -76,7 +74,6 @@ manwear=model_550_obj_wear,0 womanwear=model_550_obj_wear,6 category=weapon_axe weight=6lb -tradeable=yes param=stabattack,-2 param=slashattack,20 param=crushattack,15 @@ -107,7 +104,6 @@ manwear=model_550_obj_wear,0 womanwear=model_550_obj_wear,6 category=weapon_axe weight=5lb -tradeable=yes param=stabattack,-2 param=slashattack,22 param=crushattack,17 @@ -138,7 +134,6 @@ manwear=model_550_obj_wear,0 womanwear=model_550_obj_wear,6 category=weapon_axe weight=7lb -tradeable=yes param=stabattack,-2 param=slashattack,31 param=crushattack,26 @@ -169,7 +164,6 @@ manwear=model_550_obj_wear,0 womanwear=model_550_obj_wear,6 category=weapon_axe weight=6lb -tradeable=yes param=stabattack,-2 param=slashattack,48 param=crushattack,43 @@ -200,7 +194,6 @@ manwear=model_550_obj_wear,0 womanwear=model_550_obj_wear,6 category=weapon_axe weight=6lb -tradeable=yes param=stabattack,-2 param=slashattack,6 param=crushattack,3 @@ -230,7 +223,6 @@ manwear=model_559_obj_wear,0 womanwear=model_559_obj_wear,6 category=weapon_axe weight=6lb -tradeable=yes param=stabattack,-2 param=slashattack,70 param=crushattack,65 diff --git a/data/src/scripts/skill_combat/configs/melee/chainbodies.obj b/data/src/scripts/skill_combat/configs/melee/chainbodies.obj index 5e9658d460..421a80ea1f 100644 --- a/data/src/scripts/skill_combat/configs/melee/chainbodies.obj +++ b/data/src/scripts/skill_combat/configs/melee/chainbodies.obj @@ -14,7 +14,6 @@ manwear=model_301_obj_wear,0 womanwear=model_464_obj_wear,0 category=armour_body weight=15lb -tradeable=yes param=magicattack,-15 param=stabdefence,10 param=slashdefence,15 @@ -38,7 +37,6 @@ manwear=model_301_obj_wear,0 womanwear=model_464_obj_wear,0 category=armour_body weight=15lb -tradeable=yes respawnrate=700 param=magicattack,-15 param=stabdefence,7 @@ -60,7 +58,6 @@ manwear=model_294_obj_wear,0 womanwear=model_458_obj_wear,0 category=armour_body weight=15lb -tradeable=yes param=magicattack,-15 param=stabdefence,17 param=slashdefence,25 @@ -83,7 +80,6 @@ manwear=model_301_obj_wear,0 womanwear=model_464_obj_wear,0 category=armour_body weight=15lb -tradeable=yes param=magicattack,-15 param=stabdefence,22 param=slashdefence,32 @@ -107,7 +103,6 @@ manwear=model_301_obj_wear,0 womanwear=model_464_obj_wear,0 category=armour_body weight=13lb -tradeable=yes param=magicattack,-15 param=stabdefence,25 param=slashdefence,35 @@ -131,7 +126,6 @@ manwear=model_301_obj_wear,0 womanwear=model_464_obj_wear,0 category=armour_body weight=17lb -tradeable=yes param=magicattack,-15 param=stabdefence,36 param=slashdefence,50 @@ -155,7 +149,6 @@ desc=A series of connected metal rings. category=armour_body iop2=Wear weight=15lb -tradeable=yes param=magicattack,-15 param=stabdefence,63 param=slashdefence,72 diff --git a/data/src/scripts/skill_combat/configs/melee/daggers.obj b/data/src/scripts/skill_combat/configs/melee/daggers.obj index e31ee85415..83bdf605a7 100644 --- a/data/src/scripts/skill_combat/configs/melee/daggers.obj +++ b/data/src/scripts/skill_combat/configs/melee/daggers.obj @@ -21,7 +21,6 @@ manwear=model_533_obj_wear,0 womanwear=model_533_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes respawnrate=500 param=stabattack,5 param=slashattack,3 @@ -60,7 +59,6 @@ manwear=model_533_obj_wear,0 womanwear=model_533_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,4 param=slashattack,2 param=crushattack,-4 @@ -90,7 +88,6 @@ manwear=model_533_obj_wear,0 womanwear=model_533_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes respawnrate=1000 param=stabattack,8 param=slashattack,4 @@ -129,7 +126,6 @@ manwear=model_533_obj_wear,0 womanwear=model_533_obj_wear,6 category=weapon_stab weight=14oz -tradeable=yes param=stabattack,11 param=slashattack,5 param=crushattack,-4 @@ -167,7 +163,6 @@ manwear=model_533_obj_wear,0 womanwear=model_533_obj_wear,6 category=weapon_stab weight=18oz -tradeable=yes param=stabattack,15 param=slashattack,8 param=crushattack,-4 @@ -205,7 +200,6 @@ manwear=model_533_obj_wear,0 womanwear=model_533_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,25 param=slashattack,12 param=crushattack,-4 @@ -238,7 +232,6 @@ manwear=model_539_obj_wear,0 womanwear=model_539_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,40 param=slashattack,25 param=crushattack,-4 @@ -278,7 +271,6 @@ manwear=model_533_obj_wear,0 womanwear=model_533_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes respawnrate=1200 param=stabattack,10 param=slashattack,5 @@ -320,7 +312,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,5 param=slashattack,3 param=crushattack,-4 @@ -360,7 +351,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,4 param=slashattack,2 param=crushattack,-4 @@ -392,7 +382,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,8 param=slashattack,4 param=crushattack,-4 @@ -432,7 +421,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=14oz -tradeable=yes param=stabattack,11 param=slashattack,5 param=crushattack,-4 @@ -472,7 +460,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=18oz -tradeable=yes param=stabattack,15 param=slashattack,8 param=crushattack,-4 @@ -512,7 +499,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,25 param=slashattack,12 param=crushattack,-4 @@ -542,7 +528,6 @@ manwear=model_539_obj_wear,0 womanwear=model_539_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,40 param=slashattack,25 param=crushattack,-4 @@ -584,7 +569,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,10 param=slashattack,5 param=crushattack,-4 @@ -614,7 +598,6 @@ manwear=model_504_obj_wear,0 womanwear=model_504_obj_wear,6 category=weapon_stab weight=1lb -tradeable=yes param=stabattack,255 param=slashattack,255 param=crushattack,255 diff --git a/data/src/scripts/skill_combat/configs/melee/fullhelms.obj b/data/src/scripts/skill_combat/configs/melee/fullhelms.obj index ac93d683ec..3ca55a774d 100644 --- a/data/src/scripts/skill_combat/configs/melee/fullhelms.obj +++ b/data/src/scripts/skill_combat/configs/melee/fullhelms.obj @@ -22,7 +22,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes respawnrate=700 param=magicattack,-6 param=rangeattack,-2 @@ -56,7 +55,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,4 @@ -87,7 +85,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,9 @@ -120,7 +117,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=5lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,13 @@ -153,7 +149,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=7lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,19 @@ -186,7 +181,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,30 @@ -219,7 +213,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,12 diff --git a/data/src/scripts/skill_combat/configs/melee/kiteshields.obj b/data/src/scripts/skill_combat/configs/melee/kiteshields.obj index 0ccfbd8740..a5dbcb7efe 100644 --- a/data/src/scripts/skill_combat/configs/melee/kiteshields.obj +++ b/data/src/scripts/skill_combat/configs/melee/kiteshields.obj @@ -18,7 +18,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,5 @@ -47,7 +46,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,8 @@ -74,7 +72,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,13 @@ -103,7 +100,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,17 @@ -132,7 +128,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=10lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,18 @@ -161,7 +156,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=13lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,27 @@ -190,7 +184,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,44 diff --git a/data/src/scripts/skill_combat/configs/melee/longswords.obj b/data/src/scripts/skill_combat/configs/melee/longswords.obj index 5ef08360cb..2f08db83eb 100644 --- a/data/src/scripts/skill_combat/configs/melee/longswords.obj +++ b/data/src/scripts/skill_combat/configs/melee/longswords.obj @@ -17,7 +17,6 @@ manwear=model_518_obj_wear,0 womanwear=model_518_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,4 param=slashattack,5 param=crushattack,-2 @@ -50,7 +49,6 @@ manwear=model_518_obj_wear,0 womanwear=model_518_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,6 param=slashattack,8 param=crushattack,-2 @@ -81,7 +79,6 @@ manwear=model_518_obj_wear,0 womanwear=model_518_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,9 param=slashattack,14 param=crushattack,-2 @@ -114,7 +111,6 @@ manwear=model_518_obj_wear,0 womanwear=model_518_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,13 param=slashattack,18 param=crushattack,-2 @@ -147,7 +143,6 @@ manwear=model_518_obj_wear,0 womanwear=model_518_obj_wear,6 category=weapon_slash weight=56oz -tradeable=yes param=stabattack,15 param=slashattack,20 param=crushattack,-2 @@ -180,7 +175,6 @@ manwear=model_518_obj_wear,0 womanwear=model_518_obj_wear,6 category=weapon_slash weight=72oz -tradeable=yes param=stabattack,20 param=slashattack,29 param=crushattack,-2 @@ -213,7 +207,6 @@ manwear=model_518_obj_wear,0 womanwear=model_518_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,38 param=slashattack,47 param=crushattack,-2 @@ -243,7 +236,6 @@ category=weapon_slash manwear=model_564_obj_wear,0 womanwear=model_564_obj_wear,6 weight=4lb -tradeable=yes param=stabattack,58 param=slashattack,69 param=crushattack,-2 diff --git a/data/src/scripts/skill_combat/configs/melee/maces.obj b/data/src/scripts/skill_combat/configs/melee/maces.obj index 6ec540f986..53320decf7 100644 --- a/data/src/scripts/skill_combat/configs/melee/maces.obj +++ b/data/src/scripts/skill_combat/configs/melee/maces.obj @@ -15,7 +15,6 @@ recol1d=8456 2dxan=392 category=weapon_spiked weight=4lb -tradeable=yes respawnrate=500 param=stabattack,4 param=slashattack,-2 @@ -46,7 +45,6 @@ recol1d=8354 2dxan=392 category=weapon_spiked weight=4lb -tradeable=yes param=stabattack,1 param=slashattack,-2 param=crushattack,6 @@ -74,7 +72,6 @@ model=model_2464_obj 2dxan=392 category=weapon_spiked weight=4lb -tradeable=yes param=stabattack,7 param=slashattack,-2 param=crushattack,13 @@ -104,7 +101,6 @@ recol1d=0 2dxan=392 category=weapon_spiked weight=4lb -tradeable=yes param=stabattack,8 param=slashattack,-2 param=crushattack,16 @@ -134,7 +130,6 @@ recol1d=6346 2dxan=392 category=weapon_spiked weight=56oz -tradeable=yes param=stabattack,11 param=slashattack,-2 param=crushattack,18 @@ -164,7 +159,6 @@ recol1d=6438 2dxan=392 category=weapon_spiked weight=72oz -tradeable=yes param=stabattack,13 param=slashattack,-2 param=crushattack,25 @@ -194,7 +188,6 @@ recol1d=6476 2dxan=392 category=weapon_spiked weight=4lb -tradeable=yes param=stabattack,20 param=slashattack,-2 param=crushattack,39 @@ -224,7 +217,6 @@ model=model_2391_obj 2dxan=348 category=weapon_spiked weight=4lb -tradeable=yes param=stabattack,40 param=slashattack,-2 param=crushattack,60 diff --git a/data/src/scripts/skill_combat/configs/melee/medhelms.obj b/data/src/scripts/skill_combat/configs/melee/medhelms.obj index df432ef5b3..15013574b5 100644 --- a/data/src/scripts/skill_combat/configs/melee/medhelms.obj +++ b/data/src/scripts/skill_combat/configs/melee/medhelms.obj @@ -19,7 +19,6 @@ manhead=model_57_obj_wear womanhead=model_117_obj_wear category=armour_helmet weight=4lb -tradeable=yes respawnrate=500 param=magicattack,-3 param=rangeattack,-1 @@ -50,7 +49,6 @@ manhead=model_57_obj_wear womanhead=model_117_obj_wear category=armour_helmet weight=4lb -tradeable=yes param=magicattack,-3 param=rangeattack,-1 param=stabdefence,3 @@ -78,7 +76,6 @@ manhead=model_57_obj_wear womanhead=model_117_obj_wear category=armour_helmet weight=4lb -tradeable=yes param=magicattack,-3 param=rangeattack,-1 param=stabdefence,7 @@ -108,7 +105,6 @@ manhead=model_57_obj_wear womanhead=model_117_obj_wear category=armour_helmet weight=3lb -tradeable=yes param=rangeattack,-1 param=magicattack,-3 param=stabdefence,10 @@ -138,7 +134,6 @@ manhead=model_57_obj_wear womanhead=model_117_obj_wear category=armour_helmet weight=5lb -tradeable=yes param=rangeattack,-1 param=magicattack,-3 param=stabdefence,14 @@ -168,7 +163,6 @@ manhead=model_57_obj_wear womanhead=model_117_obj_wear category=armour_helmet weight=4lb -tradeable=yes param=rangeattack,-1 param=magicattack,-3 param=stabdefence,22 @@ -203,7 +197,6 @@ wearpos2=head category=armour_helmet weight=3lb members=yes -tradeable=yes param=rangeattack,-1 param=magicattack,-3 param=stabdefence,33 @@ -237,7 +230,6 @@ manhead=model_57_obj_wear womanhead=model_117_obj_wear category=armour_helmet weight=4lb -tradeable=yes param=rangeattack,-1 param=magicattack,-3 param=stabdefence,9 diff --git a/data/src/scripts/skill_combat/configs/melee/platebodies.obj b/data/src/scripts/skill_combat/configs/melee/platebodies.obj index f1fb015c56..931c4880b2 100644 --- a/data/src/scripts/skill_combat/configs/melee/platebodies.obj +++ b/data/src/scripts/skill_combat/configs/melee/platebodies.obj @@ -21,7 +21,6 @@ womanwear=model_468_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes respawnrate=1500 param=magicattack,-30 param=rangeattack,-10 @@ -54,7 +53,6 @@ womanwear=model_468_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,15 @@ -82,7 +80,6 @@ womanwear=model_468_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes respawnrate=2000 param=magicattack,-30 param=rangeattack,-10 @@ -115,7 +112,6 @@ womanwear=model_468_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=19lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,46 @@ -147,7 +143,6 @@ womanwear=model_468_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=25lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,65 @@ -179,7 +174,6 @@ womanwear=model_468_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,41 @@ -210,7 +204,6 @@ womanwear=model_468_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,82 diff --git a/data/src/scripts/skill_combat/configs/melee/platelegs.obj b/data/src/scripts/skill_combat/configs/melee/platelegs.obj index e573946c1b..f71e1eb8d8 100644 --- a/data/src/scripts/skill_combat/configs/melee/platelegs.obj +++ b/data/src/scripts/skill_combat/configs/melee/platelegs.obj @@ -18,7 +18,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,11 @@ -43,7 +42,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes respawnrate=2000 param=magicattack,-21 param=rangeattack,-7 @@ -73,7 +71,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=17lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,24 @@ -102,7 +99,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=23lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,33 @@ -131,7 +127,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,8 @@ -160,7 +155,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,21 @@ -189,7 +183,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,51 diff --git a/data/src/scripts/skill_combat/configs/melee/plateskirts.obj b/data/src/scripts/skill_combat/configs/melee/plateskirts.obj index 400dae9f79..a2d58613bc 100644 --- a/data/src/scripts/skill_combat/configs/melee/plateskirts.obj +++ b/data/src/scripts/skill_combat/configs/melee/plateskirts.obj @@ -17,7 +17,6 @@ manwear=model_266_obj_wear,0 womanwear=model_430_obj_wear,0 category=armour_legs weight=18lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,11 @@ -43,7 +42,6 @@ manwear=model_266_obj_wear,0 womanwear=model_430_obj_wear,0 category=armour_legs weight=18lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,17 @@ -71,7 +69,6 @@ manwear=model_266_obj_wear,0 womanwear=model_430_obj_wear,0 category=armour_legs weight=16lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,24 @@ -99,7 +96,6 @@ manwear=model_266_obj_wear,0 womanwear=model_430_obj_wear,0 category=armour_legs weight=18lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,8 @@ -127,7 +123,6 @@ manwear=model_266_obj_wear,0 womanwear=model_430_obj_wear,0 category=armour_legs weight=18lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,21 @@ -155,7 +150,6 @@ manwear=model_266_obj_wear,0 womanwear=model_430_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,33 @@ -183,7 +177,6 @@ manwear=model_266_obj_wear,0 womanwear=model_430_obj_wear,0 category=armour_legs weight=18lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,51 diff --git a/data/src/scripts/skill_combat/configs/melee/scimitars.obj b/data/src/scripts/skill_combat/configs/melee/scimitars.obj index 0a58afbc1b..452891ad1c 100644 --- a/data/src/scripts/skill_combat/configs/melee/scimitars.obj +++ b/data/src/scripts/skill_combat/configs/melee/scimitars.obj @@ -16,7 +16,6 @@ manwear=model_490_obj_wear,0 womanwear=model_490_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,1 param=slashattack,7 param=crushattack,-2 @@ -46,7 +45,6 @@ manwear=model_490_obj_wear,0 womanwear=model_490_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes respawnrate=500 param=stabattack,2 param=slashattack,10 @@ -75,7 +73,6 @@ manwear=model_490_obj_wear,0 womanwear=model_490_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,3 param=slashattack,15 param=crushattack,-2 @@ -105,7 +102,6 @@ manwear=model_490_obj_wear,0 womanwear=model_490_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes respawnrate=1500 param=stabattack,4 param=slashattack,19 @@ -136,7 +132,6 @@ manwear=model_490_obj_wear,0 womanwear=model_490_obj_wear,6 category=weapon_slash weight=56oz -tradeable=yes param=stabattack,5 param=slashattack,21 param=crushattack,-2 @@ -166,7 +161,6 @@ manwear=model_490_obj_wear,0 womanwear=model_490_obj_wear,6 category=weapon_slash weight=72oz -tradeable=yes param=stabattack,6 param=slashattack,29 param=crushattack,-2 @@ -196,7 +190,6 @@ manwear=model_490_obj_wear,0 womanwear=model_490_obj_wear,6 category=weapon_slash weight=4lb -tradeable=yes param=stabattack,7 param=slashattack,45 param=crushattack,-2 diff --git a/data/src/scripts/skill_combat/configs/melee/shields.obj b/data/src/scripts/skill_combat/configs/melee/shields.obj index 4eab39c30c..30244f95dc 100644 --- a/data/src/scripts/skill_combat/configs/melee/shields.obj +++ b/data/src/scripts/skill_combat/configs/melee/shields.obj @@ -16,7 +16,6 @@ manwear=model_517_obj_wear,0 womanwear=model_517_obj_wear,6 category=armour_shield weight=5lb -tradeable=yes param=stabdefence,4 param=slashdefence,5 param=crushdefence,3 @@ -41,7 +40,6 @@ manwear=model_541_obj_wear,0 womanwear=model_541_obj_wear,6 category=armour_shield weight=8lb -tradeable=yes respawnrate=10 param=rangeattack,-2 param=magicattack,-6 @@ -68,7 +66,6 @@ manwear=model_541_obj_wear,0 womanwear=model_541_obj_wear,6 category=armour_shield weight=8lb -tradeable=yes param=rangeattack,-2 param=magicattack,-6 param=stabdefence,8 @@ -94,7 +91,6 @@ manwear=model_541_obj_wear,0 womanwear=model_541_obj_wear,6 category=armour_shield weight=8lb -tradeable=yes param=rangeattack,-2 param=magicattack,-6 param=stabdefence,12 @@ -120,7 +116,6 @@ manwear=model_541_obj_wear,0 womanwear=model_541_obj_wear,6 category=armour_shield weight=8lb -tradeable=yes param=rangeattack,-2 param=magicattack,-6 param=stabdefence,15 @@ -146,7 +141,6 @@ manwear=model_541_obj_wear,0 womanwear=model_541_obj_wear,6 category=armour_shield weight=7lb -tradeable=yes param=rangeattack,-2 param=magicattack,-6 param=stabdefence,17 @@ -172,7 +166,6 @@ manwear=model_541_obj_wear,0 womanwear=model_541_obj_wear,6 category=armour_shield weight=9lb -tradeable=yes param=rangeattack,-2 param=magicattack,-6 param=stabdefence,24 @@ -198,7 +191,6 @@ manwear=model_541_obj_wear,0 womanwear=model_541_obj_wear,6 category=armour_shield weight=8lb -tradeable=yes param=rangeattack,-2 param=magicattack,-6 param=stabdefence,38 @@ -223,7 +215,6 @@ manwear=model_565_obj_wear,0 womanwear=model_565_obj_wear,6 category=armour_shield weight=7lb -tradeable=yes param=rangeattack,-2 param=magicattack,-6 param=stabdefence,50 @@ -247,7 +238,6 @@ manwear=model_526_obj_wear,0 womanwear=model_526_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=stabdefence,7 param=slashdefence,9 param=crushdefence,8 diff --git a/data/src/scripts/skill_combat/configs/melee/spears.obj b/data/src/scripts/skill_combat/configs/melee/spears.obj index 41db4c38f1..daf5207093 100644 --- a/data/src/scripts/skill_combat/configs/melee/spears.obj +++ b/data/src/scripts/skill_combat/configs/melee/spears.obj @@ -21,7 +21,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,5 param=slashattack,5 param=crushattack,5 @@ -61,7 +60,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,8 param=slashattack,8 param=crushattack,8 @@ -103,7 +101,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,12 param=slashattack,12 param=crushattack,12 @@ -145,7 +142,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=4lb -tradeable=yes param=stabattack,17 param=slashattack,17 param=crushattack,17 @@ -187,7 +183,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=6lb -tradeable=yes param=stabattack,24 param=slashattack,24 param=crushattack,24 @@ -229,7 +224,6 @@ weight=5lb 2dyan=112 2dzan=144 2dxan=1960 -tradeable=yes param=stabattack,36 param=slashattack,36 param=crushattack,36 @@ -269,7 +263,6 @@ womanwear=model_505_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,55 param=slashattack,55 param=crushattack,55 @@ -314,7 +307,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=slashattack,5 param=crushattack,5 param=stabdefence,1 @@ -352,7 +344,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,8 param=slashattack,8 param=crushattack,8 @@ -393,7 +384,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,12 param=slashattack,12 param=crushattack,12 @@ -434,7 +424,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=4lb -tradeable=yes param=stabattack,17 param=slashattack,17 param=crushattack,17 @@ -475,7 +464,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=6lb -tradeable=yes param=stabattack,24 param=slashattack,24 param=crushattack,24 @@ -516,7 +504,6 @@ womanwear=model_540_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,36 param=slashattack,36 param=crushattack,36 @@ -555,7 +542,6 @@ womanwear=model_505_obj_wear,6 2dxan=1960 category=weapon_spear weight=5lb -tradeable=yes param=stabattack,55 param=slashattack,55 param=crushattack,55 diff --git a/data/src/scripts/skill_combat/configs/melee/swords.obj b/data/src/scripts/skill_combat/configs/melee/swords.obj index 9050c243c4..0c35c090ae 100644 --- a/data/src/scripts/skill_combat/configs/melee/swords.obj +++ b/data/src/scripts/skill_combat/configs/melee/swords.obj @@ -15,7 +15,6 @@ manwear=model_519_obj_wear,0 womanwear=model_519_obj_wear,6 category=weapon_stab weight=4lb -tradeable=yes param=stabattack,4 param=slashattack,3 param=crushattack,-2 @@ -45,7 +44,6 @@ manwear=model_519_obj_wear,0 womanwear=model_519_obj_wear,6 category=weapon_stab weight=4lb -tradeable=yes respawnrate=500 param=stabattack,6 param=slashattack,4 @@ -74,7 +72,6 @@ manwear=model_519_obj_wear,0 womanwear=model_519_obj_wear,6 category=weapon_stab weight=4lb -tradeable=yes respawnrate=1000 param=stabattack,11 param=slashattack,8 @@ -105,7 +102,6 @@ manwear=model_519_obj_wear,0 womanwear=model_519_obj_wear,6 category=weapon_stab weight=4lb -tradeable=yes param=stabattack,14 param=slashattack,10 param=crushattack,-2 @@ -135,7 +131,6 @@ manwear=model_519_obj_wear,0 womanwear=model_519_obj_wear,6 category=weapon_stab weight=56oz -tradeable=yes param=stabattack,16 param=slashattack,11 param=crushattack,-2 @@ -165,7 +160,6 @@ manwear=model_519_obj_wear,0 womanwear=model_519_obj_wear,6 category=weapon_stab weight=72oz -tradeable=yes param=stabattack,23 param=slashattack,18 param=crushattack,-2 @@ -195,7 +189,6 @@ manwear=model_519_obj_wear,0 womanwear=model_519_obj_wear,6 category=weapon_stab weight=4lb -tradeable=yes param=stabattack,38 param=slashattack,26 param=crushattack,-2 diff --git a/data/src/scripts/skill_combat/configs/melee/trails.obj b/data/src/scripts/skill_combat/configs/melee/trails.obj index 937046870b..04ee1b44ab 100644 --- a/data/src/scripts/skill_combat/configs/melee/trails.obj +++ b/data/src/scripts/skill_combat/configs/melee/trails.obj @@ -17,7 +17,6 @@ iop2=Wear 2dzoom=770 2dyan=160 2dxan=152 -tradeable=yes param=magicattack,-10 param=rangeattack,8 param=stabdefence,2 @@ -43,7 +42,6 @@ iop2=Wear 2dzoom=770 2dyan=160 2dxan=152 -tradeable=yes param=magicattack,4 param=magicdefence,4 @@ -66,7 +64,6 @@ manwear=model_3378_obj_wear,0 womanwear=model_3382_obj_wear,0 manhead=model_3384_obj_wear womanhead=model_3385_obj_wear -tradeable=yes param=magicattack,-10 param=rangeattack,8 param=stabdefence,4 @@ -92,7 +89,6 @@ manwear=model_243_obj_wear,0 womanwear=model_416_obj_wear,0 manhead=model_76_obj_wear womanhead=model_134_obj_wear -tradeable=yes [trail_berret_blue] name=Berret @@ -114,7 +110,6 @@ manwear=model_198_obj_wear,0 womanwear=model_373_obj_wear,0 manhead=model_40_obj_wear womanhead=model_98_obj_wear -tradeable=yes [trail_berret_black] name=Berret @@ -136,7 +131,6 @@ manwear=model_198_obj_wear,0 womanwear=model_373_obj_wear,0 manhead=model_40_obj_wear womanhead=model_98_obj_wear -tradeable=yes [trail_berret_white] name=Berret @@ -158,7 +152,6 @@ manwear=model_198_obj_wear,0 womanwear=model_373_obj_wear,0 manhead=model_40_obj_wear womanhead=model_98_obj_wear -tradeable=yes [trail_cavalier_tan] name=Cavalier @@ -178,7 +171,6 @@ manwear=model_186_obj_wear,0 womanwear=model_362_obj_wear,0 manhead=model_28_obj_wear womanhead=model_86_obj_wear -tradeable=yes [trail_cavalier_brown] name=Cavalier @@ -200,7 +192,6 @@ manwear=model_186_obj_wear,0 womanwear=model_362_obj_wear,0 manhead=model_28_obj_wear womanhead=model_86_obj_wear -tradeable=yes [trail_cavalier_black] name=Cavalier @@ -222,7 +213,6 @@ manwear=model_186_obj_wear,0 womanwear=model_362_obj_wear,0 manhead=model_28_obj_wear womanhead=model_86_obj_wear -tradeable=yes [trail_headband_red] name=Headband @@ -245,7 +235,6 @@ manwear=model_201_obj_wear,0 womanwear=model_376_obj_wear,0 manhead=model_43_obj_wear womanhead=model_101_obj_wear -tradeable=yes [trail_headband_black] name=Headband @@ -268,7 +257,6 @@ manwear=model_201_obj_wear,0 womanwear=model_376_obj_wear,0 manhead=model_43_obj_wear womanhead=model_101_obj_wear -tradeable=yes [trail_headband_brown] name=Headband @@ -291,7 +279,6 @@ manwear=model_201_obj_wear,0 womanwear=model_376_obj_wear,0 manhead=model_43_obj_wear womanhead=model_101_obj_wear -tradeable=yes [trail_pirates_hat] name=Pirate's hat @@ -310,7 +297,6 @@ manwear=model_190_obj_wear,0 womanwear=model_367_obj_wear,0 manhead=model_31_obj_wear womanhead=model_89_obj_wear -tradeable=yes [rune_platebody_zamorak] name=Zamorak platebody @@ -337,7 +323,6 @@ womanwear2=model_344_obj_wear womanwear3=model_3381_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,82 @@ -366,7 +351,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,51 @@ -399,7 +383,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,30 @@ -430,7 +413,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,44 @@ -466,7 +448,6 @@ womanwear2=model_344_obj_wear womanwear3=model_3330_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,82 @@ -495,7 +476,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,51 @@ -528,7 +508,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,30 @@ -559,7 +538,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,44 @@ -593,7 +571,6 @@ womanwear2=model_344_obj_wear womanwear3=model_3380_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,82 @@ -622,7 +599,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,51 @@ -655,7 +631,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,30 @@ -686,7 +661,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,44 @@ -718,7 +692,6 @@ womanwear=model_3383_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,41 @@ -747,7 +720,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,21 @@ -780,7 +752,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,12 @@ -811,7 +782,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,17 @@ -843,7 +813,6 @@ womanwear=model_3383_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,41 @@ -872,7 +841,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,21 @@ -905,7 +873,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,12 @@ -936,7 +903,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,17 @@ -968,7 +934,6 @@ womanwear=model_3383_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=25lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,65 @@ -997,7 +962,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=23lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,33 @@ -1028,7 +992,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=13lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,27 @@ -1061,7 +1024,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=7lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,19 @@ -1093,7 +1055,6 @@ womanwear=model_3383_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=25lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,65 @@ -1122,7 +1083,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=23lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,33 @@ -1153,7 +1113,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=13lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,27 @@ -1186,7 +1145,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=7lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,19 @@ -1218,7 +1176,6 @@ womanwear=model_3383_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,82 @@ -1247,7 +1204,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,51 @@ -1280,7 +1236,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,30 @@ -1311,7 +1266,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,44 @@ -1343,7 +1297,6 @@ womanwear=model_3383_obj_wear,0 womanwear2=model_344_obj_wear category=armour_body weight=22lb -tradeable=yes param=magicattack,-30 param=rangeattack,-10 param=stabdefence,82 @@ -1372,7 +1325,6 @@ manwear=model_268_obj_wear,0 womanwear=model_432_obj_wear,0 category=armour_legs weight=20lb -tradeable=yes param=magicattack,-21 param=rangeattack,-7 param=stabdefence,51 @@ -1405,7 +1357,6 @@ manhead=model_56_obj_wear womanhead=model_116_obj_wear category=armour_helmet weight=6lb -tradeable=yes param=magicattack,-6 param=rangeattack,-2 param=stabdefence,30 @@ -1436,7 +1387,6 @@ manwear=model_486_obj_wear,0 womanwear=model_486_obj_wear,6 category=armour_shield weight=12lb -tradeable=yes param=magicattack,-8 param=rangeattack,-2 param=stabdefence,44 diff --git a/data/src/scripts/skill_combat/configs/melee/warhammers.obj b/data/src/scripts/skill_combat/configs/melee/warhammers.obj index a69f45e543..f9328702fb 100644 --- a/data/src/scripts/skill_combat/configs/melee/warhammers.obj +++ b/data/src/scripts/skill_combat/configs/melee/warhammers.obj @@ -16,7 +16,6 @@ recol1d=8456 2dxan=344 category=weapon_blunt weight=4lb -tradeable=yes param=attackrate,6 param=stabattack,-4 param=slashattack,-4 @@ -27,7 +26,7 @@ param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 param=defend_anim,human_blunt_defend2 param=crush_sound,baxe_crush -// osrs attack seq_403. +// osrs defend seq_403. [bronze_warhammer] cost=47 @@ -47,7 +46,6 @@ recol1d=8354 2dxan=344 category=weapon_blunt weight=4lb -tradeable=yes param=attackrate,6 param=stabattack,-4 param=slashattack,-4 @@ -58,7 +56,7 @@ param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 param=defend_anim,human_blunt_defend2 param=crush_sound,baxe_crush -// osrs attack seq_403. +// osrs defend seq_403. [steel_warhammer] cost=640 @@ -77,7 +75,6 @@ model=model_2731_obj 2dxan=344 category=weapon_blunt weight=4lb -tradeable=yes param=attackrate,6 param=stabattack,-4 param=slashattack,-4 @@ -88,7 +85,7 @@ param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 param=defend_anim,human_blunt_defend2 param=crush_sound,baxe_crush -// osrs attack seq_403. +// osrs defend seq_403. [black_warhammer] cost=640 @@ -109,7 +106,6 @@ recol1d=0 2dxan=344 category=weapon_blunt weight=4lb -tradeable=yes param=attackrate,6 param=stabattack,-4 param=slashattack,-4 @@ -120,7 +116,7 @@ param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 param=defend_anim,human_blunt_defend2 param=crush_sound,baxe_crush -// osrs attack seq_403. +// osrs defend seq_403. [mithril_warhammer] cost=1660 @@ -141,7 +137,6 @@ recol1d=6346 2dxan=344 category=weapon_blunt weight=56oz -tradeable=yes param=attackrate,6 param=stabattack,-4 param=slashattack,-4 @@ -152,7 +147,7 @@ param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 param=defend_anim,human_blunt_defend2 param=crush_sound,baxe_crush -// osrs attack seq_403. +// osrs defend seq_403. [adamant_warhammer] cost=4120 @@ -173,7 +168,6 @@ recol1d=6438 2dxan=344 category=weapon_blunt weight=72oz -tradeable=yes param=attackrate,6 param=stabattack,-4 param=slashattack,-4 @@ -184,7 +178,7 @@ param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 param=defend_anim,human_blunt_defend2 param=crush_sound,baxe_crush -// osrs attack seq_403. +// osrs defend seq_403. [rune_warhammer] cost=41500 @@ -204,7 +198,6 @@ recol1d=6476 2dxan=344 category=weapon_blunt weight=4lb -tradeable=yes param=attackrate,6 param=stabattack,-4 param=slashattack,-4 @@ -215,4 +208,4 @@ param=crushattack_anim,human_blunt_crush // param=defend_anim,human_blunt_defend1 param=defend_anim,human_blunt_defend2 param=crush_sound,baxe_crush -// osrs attack seq_403. \ No newline at end of file +// osrs defend seq_403. \ No newline at end of file diff --git a/data/src/scripts/skill_combat/configs/ranged/arrows.obj b/data/src/scripts/skill_combat/configs/ranged/arrows.obj index 1b6847d27f..846e668c70 100644 --- a/data/src/scripts/skill_combat/configs/ranged/arrows.obj +++ b/data/src/scripts/skill_combat/configs/ranged/arrows.obj @@ -23,7 +23,6 @@ count4=bronze_arrow_5,5 category=arrows param=rangebonus,7 param=levelrequire,1 -tradeable=yes param=proj_launch,bronze_arrow_launch param=proj_travel,bronze_arrow_travel param=weapon_poisoned,bronze_arrow_p @@ -56,7 +55,6 @@ count4=bronze_arrow_p_5,5 category=arrows param=rangebonus,7 param=levelrequire,1 -tradeable=yes param=proj_launch,bronze_arrow_launch param=proj_travel,bronze_arrow_travel param=poison_severity,20 @@ -86,7 +84,6 @@ count4=iron_arrow_5,5 category=arrows param=rangebonus,10 param=levelrequire,1 -tradeable=yes param=proj_launch,iron_arrow_launch param=proj_travel,iron_arrow_travel param=weapon_poisoned,iron_arrow_p @@ -119,7 +116,6 @@ count4=iron_arrow_p_5,5 category=arrows param=rangebonus,10 param=levelrequire,1 -tradeable=yes param=proj_launch,iron_arrow_launch param=proj_travel,iron_arrow_travel param=poison_severity,20 @@ -145,7 +141,6 @@ count4=steel_arrow_5,5 category=arrows param=rangebonus,16 param=levelrequire,5 -tradeable=yes param=proj_launch,steel_arrow_launch param=proj_travel,steel_arrow_travel param=weapon_poisoned,steel_arrow_p @@ -176,7 +171,6 @@ count4=steel_arrow_p_5,5 category=arrows param=rangebonus,16 param=levelrequire,5 -tradeable=yes param=proj_launch,steel_arrow_launch param=proj_travel,steel_arrow_travel param=poison_severity,20 @@ -207,7 +201,6 @@ count4=mithril_arrow_5,5 category=arrows param=rangebonus,22 param=levelrequire,20 -tradeable=yes param=proj_launch,mithril_arrow_launch param=proj_travel,mithril_arrow_travel param=weapon_poisoned,mithril_arrow_p @@ -240,7 +233,6 @@ count4=mithril_arrow_p_5,5 category=arrows param=rangebonus,22 param=levelrequire,20 -tradeable=yes param=proj_launch,mithril_arrow_launch param=proj_travel,mithril_arrow_travel param=poison_severity,20 @@ -271,7 +263,6 @@ count4=adamant_arrow_5,5 category=arrows param=rangebonus,31 param=levelrequire,30 -tradeable=yes param=proj_launch,adamant_arrow_launch param=proj_travel,adamant_arrow_travel param=weapon_poisoned,adamant_arrow_p @@ -304,7 +295,6 @@ count4=adamant_arrow_p_5,5 category=arrows param=rangebonus,31 param=levelrequire,30 -tradeable=yes param=proj_launch,adamant_arrow_launch param=proj_travel,adamant_arrow_travel param=poison_severity,20 @@ -335,7 +325,6 @@ count4=rune_arrow_5,5 category=arrows param=rangebonus,49 param=levelrequire,40 -tradeable=yes param=proj_launch,rune_arrow_launch param=proj_travel,rune_arrow_travel param=weapon_poisoned,rune_arrow_p @@ -368,7 +357,6 @@ count4=rune_arrow_p_5,5 category=arrows param=rangebonus,49 param=levelrequire,40 -tradeable=yes param=proj_launch,rune_arrow_launch param=proj_travel,rune_arrow_travel param=poison_severity,20 @@ -1046,7 +1034,6 @@ param=levelrequire,1 param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=lit_arrow,^true -tradeable=yes [iron_fire_arrows_unlit] name=Iron fire arrows @@ -1072,7 +1059,6 @@ param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=unlit_arrow,^true param=next_obj_stage,iron_fire_arrows -tradeable=yes [iron_fire_arrows] name=Iron fire arrows @@ -1099,7 +1085,6 @@ param=levelrequire,1 param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=lit_arrow,^true -tradeable=yes [steel_fire_arrows_unlit] name=Steel fire arrows @@ -1125,7 +1110,6 @@ param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=next_obj_stage,steel_fire_arrows param=unlit_arrow,^true -tradeable=yes [steel_fire_arrows] name=Steel fire arrows @@ -1152,7 +1136,6 @@ param=levelrequire,5 param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=lit_arrow,^true -tradeable=yes [mithril_fire_arrows_unlit] name=Mithril fire arrows @@ -1178,7 +1161,6 @@ param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=next_obj_stage,mithril_fire_arrows param=unlit_arrow,^true -tradeable=yes [mithril_fire_arrows] name=Mithril fire arrows @@ -1205,7 +1187,6 @@ param=levelrequire,20 param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=lit_arrow,^true -tradeable=yes [adamant_fire_arrows_unlit] name=Adamnt fire arrows @@ -1231,7 +1212,6 @@ param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=next_obj_stage,adamant_fire_arrows param=unlit_arrow,^true -tradeable=yes [adamant_fire_arrows] name=Adamnt fire arrows @@ -1258,7 +1238,6 @@ param=levelrequire,30 param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=lit_arrow,^true -tradeable=yes [rune_fire_arrows_unlit] name=Rune fire arrows @@ -1284,7 +1263,6 @@ param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=next_obj_stage,rune_fire_arrows param=unlit_arrow,^true -tradeable=yes [rune_fire_arrows] name=Rune fire arrows @@ -1311,7 +1289,6 @@ param=levelrequire,40 param=proj_launch,fire_arrow_launch param=proj_travel,fire_arrow_travel param=lit_arrow,^true -tradeable=yes [unlitarrow_2] stackable=yes diff --git a/data/src/scripts/skill_combat/configs/ranged/bolts.obj b/data/src/scripts/skill_combat/configs/ranged/bolts.obj index 991b18cb26..3e4ddfe685 100644 --- a/data/src/scripts/skill_combat/configs/ranged/bolts.obj +++ b/data/src/scripts/skill_combat/configs/ranged/bolts.obj @@ -17,7 +17,6 @@ param=rangebonus,10 param=levelrequire,1 param=proj_launch,crossbowbolt_launch param=proj_travel,crossbowbolt_travel -tradeable=yes param=weapon_poisoned,bolt_p param=weapon_poisoned_message,You poison some bolts. @@ -44,7 +43,6 @@ param=levelrequire,1 param=proj_launch,crossbowbolt_launch param=proj_travel,crossbowbolt_travel param=poison_severity,20 -tradeable=yes //RANGED STRENGTH FOR UNUSUAL BOLTS: //The ranged strength stats for non-standard bolts before the 2006 crossbow rework are not known precisely. @@ -79,7 +77,6 @@ param=rangebonus,28 param=levelrequire,1 param=proj_launch,crossbowbolt_launch param=proj_travel,crossbowbolt_travel -tradeable=yes [pearl_bolt] stackable=yes @@ -105,7 +102,6 @@ param=rangebonus,19 param=levelrequire,1 param=proj_launch,crossbowbolt_launch param=proj_travel,crossbowbolt_travel -tradeable=yes [barbed_bolt] stackable=yes @@ -127,4 +123,3 @@ param=rangebonus,46 param=levelrequire,1 param=proj_launch,crossbowbolt_launch param=proj_travel,crossbowbolt_travel -tradeable=yes diff --git a/data/src/scripts/skill_combat/configs/ranged/bows.obj b/data/src/scripts/skill_combat/configs/ranged/bows.obj index 887ebb5951..358729ebda 100644 --- a/data/src/scripts/skill_combat/configs/ranged/bows.obj +++ b/data/src/scripts/skill_combat/configs/ranged/bows.obj @@ -17,7 +17,6 @@ manwear=model_563_obj_wear,0 womanwear=model_563_obj_wear,6 category=weapon_bow weight=4lb -tradeable=yes respawnrate=200 param=rangeattack,8 param=levelrequire,1 @@ -47,7 +46,6 @@ manwear=model_512_obj_wear,0 womanwear=model_512_obj_wear,6 category=weapon_bow weight=3lb -tradeable=yes respawnrate=200 param=rangeattack,8 param=levelrequire,1 @@ -76,7 +74,6 @@ manwear=model_512_obj_wear,0 womanwear=model_512_obj_wear,6 category=weapon_bow weight=4lb -tradeable=yes param=rangeattack,14 param=levelrequire,5 param=attackrange,7 @@ -104,7 +101,6 @@ manwear=model_563_obj_wear,0 womanwear=model_563_obj_wear,6 category=weapon_bow weight=5lb -tradeable=yes param=rangeattack,14 param=levelrequire,5 param=attackrate,6 @@ -134,7 +130,6 @@ manwear=model_563_obj_wear,0 womanwear=model_563_obj_wear,6 category=weapon_bow weight=4lb -tradeable=yes param=rangeattack,20 param=levelrequire,20 param=attackrate,6 @@ -164,7 +159,6 @@ manwear=model_512_obj_wear,0 womanwear=model_512_obj_wear,6 category=weapon_bow weight=3lb -tradeable=yes param=rangeattack,20 param=levelrequire,20 param=attackrange,7 @@ -193,7 +187,6 @@ manwear=model_563_obj_wear,0 womanwear=model_563_obj_wear,6 category=weapon_bow weight=4lb -tradeable=yes param=rangeattack,29 param=levelrequire,30 param=attackrate,6 @@ -224,7 +217,6 @@ manwear=model_512_obj_wear,0 womanwear=model_512_obj_wear,6 category=weapon_bow weight=3lb -tradeable=yes param=rangeattack,29 param=levelrequire,30 param=attackrange,7 @@ -253,7 +245,6 @@ manwear=model_563_obj_wear,0 womanwear=model_563_obj_wear,6 category=weapon_bow weight=4lb -tradeable=yes param=rangeattack,47 param=levelrequire,40 param=attackrate,6 @@ -283,7 +274,6 @@ manwear=model_512_obj_wear,0 womanwear=model_512_obj_wear,6 category=weapon_bow weight=3lb -tradeable=yes param=rangeattack,47 param=levelrequire,40 param=attackrange,7 @@ -312,7 +302,6 @@ manwear=model_563_obj_wear,0 womanwear=model_563_obj_wear,6 category=weapon_bow weight=4lb -tradeable=yes param=rangeattack,69 param=levelrequire,50 param=attackrate,6 @@ -342,7 +331,6 @@ manwear=model_512_obj_wear,0 womanwear=model_512_obj_wear,6 category=weapon_bow weight=3lb -tradeable=yes param=rangeattack,69 param=levelrequire,50 param=attackrange,7 @@ -376,3 +364,4 @@ param=rangeattack_anim,human_bow param=defend_anim,human_unarmedblock param=rangeattack_sound,arrowlaunch2 param=damagetype,^ranged_style +tradeable=no diff --git a/data/src/scripts/skill_combat/configs/ranged/crossbows.obj b/data/src/scripts/skill_combat/configs/ranged/crossbows.obj index a9167fe0fa..383cc99a07 100644 --- a/data/src/scripts/skill_combat/configs/ranged/crossbows.obj +++ b/data/src/scripts/skill_combat/configs/ranged/crossbows.obj @@ -14,7 +14,6 @@ manwear=model_508_obj_wear,0 womanwear=model_508_obj_wear,6 category=weapon_crossbow weight=8kg -tradeable=yes respawnrate=500 param=rangeattack,6 param=levelrequire,1 diff --git a/data/src/scripts/skill_combat/configs/ranged/darts.obj b/data/src/scripts/skill_combat/configs/ranged/darts.obj index f336e089bc..2bae982bee 100644 --- a/data/src/scripts/skill_combat/configs/ranged/darts.obj +++ b/data/src/scripts/skill_combat/configs/ranged/darts.obj @@ -29,7 +29,6 @@ param=proj_launch,bronze_dart_launch param=proj_travel,bronze_dart_travel param=weapon_poisoned,bronze_dart_p param=weapon_poisoned_message,You poison some darts. -tradeable=yes [iron_dart] stackable=yes @@ -62,7 +61,6 @@ param=proj_launch,iron_dart_launch param=proj_travel,iron_dart_travel param=weapon_poisoned,iron_dart_p param=weapon_poisoned_message,You poison some darts. -tradeable=yes [steel_dart] stackable=yes @@ -96,7 +94,6 @@ param=proj_launch,steel_dart_launch param=proj_travel,steel_dart_travel param=weapon_poisoned,steel_dart_p param=weapon_poisoned_message,You poison some darts. -tradeable=yes [mithril_dart] stackable=yes @@ -129,7 +126,6 @@ param=proj_launch,mithril_dart_launch param=proj_travel,mithril_dart_travel param=weapon_poisoned,mithril_dart_p param=weapon_poisoned_message,You poison some darts. -tradeable=yes [adamant_dart] stackable=yes @@ -162,7 +158,6 @@ param=proj_launch,adamant_dart_launch param=proj_travel,adamant_dart_travel param=weapon_poisoned,adamant_dart_p param=weapon_poisoned_message,You poison some darts. -tradeable=yes [rune_dart] stackable=yes @@ -195,7 +190,6 @@ param=proj_launch,rune_dart_launch param=proj_travel,rune_dart_travel param=weapon_poisoned,rune_dart_p param=weapon_poisoned_message,You poison some darts. -tradeable=yes [bronze_dart_p] stackable=yes @@ -231,7 +225,6 @@ param=rangeattack_sound,dart param=proj_launch,bronze_dart_launch param=proj_travel,bronze_dart_travel param=poison_severity,20 -tradeable=yes [iron_dart_p] stackable=yes @@ -265,7 +258,6 @@ param=rangeattack_sound,dart param=proj_launch,iron_dart_launch param=proj_travel,iron_dart_travel param=poison_severity,20 -tradeable=yes [steel_dart_p] stackable=yes @@ -300,7 +292,6 @@ param=rangeattack_sound,dart param=proj_launch,steel_dart_launch param=proj_travel,steel_dart_travel param=poison_severity,20 -tradeable=yes [mithril_dart_p] stackable=yes @@ -334,7 +325,6 @@ param=rangeattack_sound,dart param=proj_launch,mithril_dart_launch param=proj_travel,mithril_dart_travel param=poison_severity,20 -tradeable=yes [adamant_dart_p] stackable=yes @@ -368,7 +358,6 @@ param=rangeattack_sound,dart param=proj_launch,adamant_dart_launch param=proj_travel,adamant_dart_travel param=poison_severity,20 -tradeable=yes [rune_dart_p] stackable=yes @@ -402,7 +391,6 @@ param=rangeattack_sound,dart param=proj_launch,rune_dart_launch param=proj_travel,rune_dart_travel param=poison_severity,20 -tradeable=yes [poisoned_dart_p] stackable=yes @@ -430,3 +418,4 @@ param=defend_anim,human_unarmedblock param=rangeattack_sound,dart param=proj_launch,bronze_dart_launch param=proj_travel,bronze_dart_travel +tradeable=no diff --git a/data/src/scripts/skill_combat/configs/ranged/javelins.obj b/data/src/scripts/skill_combat/configs/ranged/javelins.obj index 25242b60a8..92410dcc0b 100644 --- a/data/src/scripts/skill_combat/configs/ranged/javelins.obj +++ b/data/src/scripts/skill_combat/configs/ranged/javelins.obj @@ -31,7 +31,6 @@ param=proj_launch,bronze_javelin_launch param=proj_travel,bronze_javelin_travel param=weapon_poisoned,bronze_javelin_p param=weapon_poisoned_message,You poison the javelins. -tradeable=yes [iron_javelin] name=Iron javelin @@ -66,7 +65,6 @@ param=proj_launch,iron_javelin_launch param=proj_travel,iron_javelin_travel param=weapon_poisoned,iron_javelin_p param=weapon_poisoned_message,You poison the javelins. -tradeable=yes [steel_javelin] name=Steel javelin @@ -99,7 +97,6 @@ param=proj_launch,steel_javelin_launch param=proj_travel,steel_javelin_travel param=weapon_poisoned,steel_javelin_p param=weapon_poisoned_message,You poison the javelins. -tradeable=yes [mithril_javelin] name=Mithril javelin @@ -134,7 +131,6 @@ param=proj_launch,mithril_javelin_launch param=proj_travel,mithril_javelin_travel param=weapon_poisoned,mithril_javelin_p param=weapon_poisoned_message,You poison the javelins. -tradeable=yes [adamant_javelin] name=Adamant javelin @@ -169,7 +165,6 @@ param=proj_launch,adamant_javelin_launch param=proj_travel,adamant_javelin_travel param=weapon_poisoned,adamant_javelin_p param=weapon_poisoned_message,You poison the javelins. -tradeable=yes [rune_javelin] name=Rune javelin @@ -204,7 +199,6 @@ param=proj_launch,rune_javelin_launch param=proj_travel,rune_javelin_travel param=weapon_poisoned,rune_javelin_p param=weapon_poisoned_message,You poison the javelins. -tradeable=yes [bronze_javelin_p] name=Bronze javelin(p) @@ -236,7 +230,6 @@ param=rangeattack_sound,javelin param=proj_launch,bronze_javelin_launch param=proj_travel,bronze_javelin_travel param=poison_severity,20 -tradeable=yes [iron_javelin_p] name=Iron javelin(p) @@ -268,7 +261,6 @@ param=rangeattack_sound,javelin param=proj_launch,iron_javelin_launch param=proj_travel,iron_javelin_travel param=poison_severity,20 -tradeable=yes [steel_javelin_p] name=Steel javelin(p) @@ -298,7 +290,6 @@ param=rangeattack_sound,javelin param=proj_launch,steel_javelin_launch param=proj_travel,steel_javelin_travel param=poison_severity,20 -tradeable=yes [mithril_javelin_p] name=Mithril javelin(p) @@ -330,7 +321,6 @@ param=rangeattack_sound,javelin param=proj_launch,mithril_javelin_launch param=proj_travel,mithril_javelin_travel param=poison_severity,20 -tradeable=yes [adamant_javelin_p] name=Adamant javelin(p) @@ -362,7 +352,6 @@ param=rangeattack_sound,javelin param=proj_launch,mithril_javelin_launch param=proj_travel,mithril_javelin_travel param=poison_severity,20 -tradeable=yes [rune_javelin_p] name=Rune javelin(p) @@ -394,4 +383,3 @@ param=rangeattack_sound,javelin param=proj_launch,rune_javelin_launch param=proj_travel,rune_javelin_travel param=poison_severity,20 -tradeable=yes diff --git a/data/src/scripts/skill_combat/configs/ranged/knives.obj b/data/src/scripts/skill_combat/configs/ranged/knives.obj index 7a65e44af5..4ad4ff4cda 100644 --- a/data/src/scripts/skill_combat/configs/ranged/knives.obj +++ b/data/src/scripts/skill_combat/configs/ranged/knives.obj @@ -33,7 +33,6 @@ param=proj_launch,iron_tknife_launch param=proj_travel,iron_tknife_travel param=weapon_poisoned,iron_knife_p param=weapon_poisoned_message,You poison some knives. -tradeable=yes [bronze_knife] members=yes @@ -70,7 +69,6 @@ param=proj_launch,bronze_tknife_launch param=proj_travel,bronze_tknife_travel param=weapon_poisoned,bronze_knife_p param=weapon_poisoned_message,You poison some knives. -tradeable=yes [steel_knife] members=yes @@ -105,7 +103,6 @@ param=proj_launch,steel_tknife_launch param=proj_travel,steel_tknife_travel param=weapon_poisoned,steel_knife_p param=weapon_poisoned_message,You poison some knives. -tradeable=yes [mithril_knife] members=yes @@ -142,7 +139,6 @@ param=proj_launch,mithril_tknife_launch param=proj_travel,mithril_tknife_travel param=weapon_poisoned,mithril_knife_p param=weapon_poisoned_message,You poison some knives. -tradeable=yes [adamant_knife] members=yes @@ -179,7 +175,6 @@ param=proj_launch,adamant_tknife_launch param=proj_travel,adamant_tknife_travel param=weapon_poisoned,adamant_knife_p param=weapon_poisoned_message,You poison some knives. -tradeable=yes [rune_knife] members=yes @@ -216,7 +211,6 @@ param=proj_launch,rune_tknife_launch param=proj_travel,rune_tknife_travel param=weapon_poisoned,rune_knife_p param=weapon_poisoned_message,You poison some knives. -tradeable=yes [black_knife] members=yes @@ -253,7 +247,6 @@ param=proj_launch,black_tknife_launch param=proj_travel,black_tknife_travel param=weapon_poisoned,black_knife_p param=weapon_poisoned_message,You poison some knives. -tradeable=yes [bronze_knife_p] members=yes @@ -289,7 +282,6 @@ param=rangeattack_sound,throwingknife param=proj_launch,bronze_tknife_launch param=proj_travel,bronze_tknife_travel param=poison_severity,20 -tradeable=yes [iron_knife_p] members=yes @@ -325,7 +317,6 @@ param=rangeattack_sound,throwingknife param=proj_launch,iron_tknife_launch param=proj_travel,iron_tknife_travel param=poison_severity,20 -tradeable=yes [steel_knife_p] members=yes @@ -359,7 +350,6 @@ param=rangeattack_sound,throwingknife param=proj_launch,steel_tknife_launch param=proj_travel,steel_tknife_travel param=poison_severity,20 -tradeable=yes [mithril_knife_p] members=yes @@ -395,7 +385,6 @@ param=rangeattack_sound,throwingknife param=proj_launch,mithril_tknife_launch param=proj_travel,mithril_tknife_travel param=poison_severity,20 -tradeable=yes [black_knife_p] members=yes @@ -431,7 +420,6 @@ param=rangeattack_sound,throwingknife param=proj_launch,black_tknife_launch param=proj_travel,black_tknife_travel param=poison_severity,20 -tradeable=yes [adamant_knife_p] members=yes @@ -467,7 +455,6 @@ param=rangeattack_sound,throwingknife param=proj_launch,adamant_tknife_launch param=proj_travel,adamant_tknife_travel param=poison_severity,20 -tradeable=yes [rune_knife_p] members=yes @@ -503,4 +490,3 @@ param=rangeattack_sound,throwingknife param=proj_launch,rune_tknife_launch param=proj_travel,rune_tknife_travel param=poison_severity,20 -tradeable=yes diff --git a/data/src/scripts/skill_combat/configs/ranged/thrownaxes.obj b/data/src/scripts/skill_combat/configs/ranged/thrownaxes.obj index 2bd4f5cdc2..38a10893fe 100644 --- a/data/src/scripts/skill_combat/configs/ranged/thrownaxes.obj +++ b/data/src/scripts/skill_combat/configs/ranged/thrownaxes.obj @@ -30,7 +30,6 @@ param=defend_anim,human_unarmedblock param=rangeattack_sound,throwingaxe param=proj_launch,bronze_taxe_launch param=proj_travel,bronze_taxe_travel -tradeable=yes [iron_thrownaxe] members=yes @@ -64,7 +63,6 @@ param=defend_anim,human_unarmedblock param=rangeattack_sound,throwingaxe param=proj_launch,iron_taxe_launch param=proj_travel,iron_taxe_travel -tradeable=yes [steel_thrownaxe] members=yes @@ -96,7 +94,6 @@ param=defend_anim,human_unarmedblock param=rangeattack_sound,throwingaxe param=proj_launch,steel_taxe_launch param=proj_travel,steel_taxe_travel -tradeable=yes [mithril_thrownaxe] members=yes @@ -130,7 +127,6 @@ param=defend_anim,human_unarmedblock param=rangeattack_sound,throwingaxe param=proj_launch,mithril_taxe_launch param=proj_travel,mithril_taxe_travel -tradeable=yes [adamant_thrownaxe] members=yes @@ -164,7 +160,6 @@ param=defend_anim,human_unarmedblock param=rangeattack_sound,throwingaxe param=proj_launch,adamant_taxe_launch param=proj_travel,adamant_taxe_travel -tradeable=yes [rune_thrownaxe] members=yes @@ -198,4 +193,3 @@ param=defend_anim,human_unarmedblock param=rangeattack_sound,throwingaxe param=proj_launch,rune_taxe_launch param=proj_travel,rune_taxe_travel -tradeable=yes diff --git a/data/src/scripts/skill_combat/scripts/npc/npc_combat.rs2 b/data/src/scripts/skill_combat/scripts/npc/npc_combat.rs2 index b39259a513..cfc0a0d6ec 100644 --- a/data/src/scripts/skill_combat/scripts/npc/npc_combat.rs2 +++ b/data/src/scripts/skill_combat/scripts/npc/npc_combat.rs2 @@ -109,7 +109,7 @@ if (npc_type = wormbrain & (~quest_dragon_getting_map_parts = false | inv_total( // } return (false); } -if (npc_category = battle_mage & %magearena_progress < ^mage_arena_complete) { +if (npc_category = battle_mage & %magearena < ^mage_arena_complete) { mes("You are not ready to fight the battle mages."); return(false); } @@ -164,7 +164,7 @@ if ((npc_type = zamorak_wizard | npc_type = grandtree_black_demon) & %npc_attack mes("It's not after you..."); return(false); } -if (npc_category = battle_mage & %magearena_progress < ^mage_arena_complete) { +if (npc_category = battle_mage & %magearena < ^mage_arena_complete) { mes("You are not ready to fight the battle mages."); return(false); } @@ -182,18 +182,18 @@ if(npc_type = fire_warrior_of_lesarkus) { // can't attack with magic ~chatnpc("Your puny weapons do nothing against me human! Come back when you can give me a real fight!"); return (false); } -if (npc_category = kolodion & enum(int, npc, mage_arena_bosses, %magearena_progress) ! npc_type) { - if (%magearena_progress > ^mage_arena_complete) { +if (npc_category = kolodion & enum(int, npc, mage_arena_bosses, %magearena) ! npc_type) { + if (%magearena > ^mage_arena_complete) { mes("You have already proven yourself against Kolodion."); return(false); } - if (enum(npc, int, mage_arena_stages, npc_type) < %magearena_progress) { - mes("You have already killed Kolodion in his form."); + if (enum(npc, int, mage_arena_stages, npc_type) < %magearena) { + mes("You have already killed Kolodion in his form."); } if (npc_type = kolodion_arachnid_form | npc_type = kolodion_demon_form) { - mes("You must now defeat him as <~add_article(enum(int, string, mage_arena_boss_names, %magearena_progress))>."); + mes("You must now defeat him as <~add_article(enum(int, string, mage_arena_boss_names, %magearena))>."); } else { - mes("You must currently fight Kolodion in his form."); + mes("You must currently fight Kolodion in his form."); } return(false); } @@ -263,7 +263,7 @@ if (inv_getobj(worn, ^wearpos_ring) = ring_of_recoil & npc_finduid(%aggressive_n [proc,npc_retaliate](int $queue_delay) npc_queue(1, 0, $queue_delay); // if in singles and attacking another player, then delay npc action by 8 ticks -if (map_multi(npc_coord) = false & %npc_attacking_uid ! uid & %npc_attacking_uid ! null) { +if (map_multiway(npc_coord) = false & %npc_attacking_uid ! uid & %npc_attacking_uid ! null) { %npc_action_delay = add(map_clock, 8); } %npc_aggressive_player = uid; @@ -276,7 +276,7 @@ if (map_multi(npc_coord) = false & %npc_attacking_uid ! uid & %npc_attacking_uid %aggressive_npc = npc_uid; [proc,npc_can_attack_player]()(boolean) -if (map_multi(npc_coord) = true) { +if (map_multiway(npc_coord) = true) { return(true); } if (add(%lastcombat_pvp, 8) > map_clock) { diff --git a/data/src/scripts/skill_combat/scripts/player/player_combat.rs2 b/data/src/scripts/skill_combat/scripts/player/player_combat.rs2 index 61330f9ff8..28f29b5434 100644 --- a/data/src/scripts/skill_combat/scripts/player/player_combat.rs2 +++ b/data/src/scripts/skill_combat/scripts/player/player_combat.rs2 @@ -97,7 +97,7 @@ switch_int ($damagetype) { } [proc,player_in_combat_check]()(boolean) -if (map_multi(npc_coord) = true) { +if (map_multiway(npc_coord) = true) { return(true); } // player has been attacked in the last 8 ticks, and not by the current npc diff --git a/data/src/scripts/skill_combat/scripts/player/player_magic.rs2 b/data/src/scripts/skill_combat/scripts/player/player_magic.rs2 index 22977f9542..3e6c22b443 100644 --- a/data/src/scripts/skill_combat/scripts/player/player_magic.rs2 +++ b/data/src/scripts/skill_combat/scripts/player/player_magic.rs2 @@ -222,6 +222,10 @@ if(npc_type = salarin_the_twisted) { case ^fire_strike : $damage = 12; } } +else if (npc_type = crest_chronozon) { + def_int $spell = db_getfield($spell_data, magic_spell_table:spell, 0); + ~crest_chronozon_spell($spell); +} // if maxhit is defined then damage npc ~npc_retaliate(calc($duration / 30 + 1)); // delayed an extra tick in osrs if ($maxhit ! null) { @@ -235,7 +239,7 @@ if ($maxhit ! null) { if (npc_param(defend_sound) ! null) { sound_synth(npc_param(defend_sound), 0, $duration); // delay 1 client tick for the hit queue } - ~give_combat_experience(%damagestyle, $damage, npc_param(combat_xp_multiplier)); + ~give_combat_experience(%damagestyle, $damage, %npc_combat_xp_multiplier); } // spell visual spotanim_npc(db_getfield($spell_data, magic_spell_table:spotanim_target, 0), $duration); diff --git a/data/src/scripts/skill_combat/scripts/player/player_melee.rs2 b/data/src/scripts/skill_combat/scripts/player/player_melee.rs2 index 485a57fc61..1d86a9393b 100644 --- a/data/src/scripts/skill_combat/scripts/player/player_melee.rs2 +++ b/data/src/scripts/skill_combat/scripts/player/player_melee.rs2 @@ -38,7 +38,7 @@ if (~player_npc_hit_roll(%damagetype) = true) { } $damage = randominc(min(%com_maxhit, npc_param(max_dealt))); $damage = min($damage, npc_stat(hitpoints)); - ~give_combat_experience(%damagestyle, $damage, npc_param(combat_xp_multiplier)); + ~give_combat_experience(%damagestyle, $damage, %npc_combat_xp_multiplier); } def_obj $weapon = inv_getobj(worn, ^wearpos_rhand); diff --git a/data/src/scripts/skill_combat/scripts/player/player_ranged.rs2 b/data/src/scripts/skill_combat/scripts/player/player_ranged.rs2 index 8c638239b3..e052da47a7 100644 --- a/data/src/scripts/skill_combat/scripts/player/player_ranged.rs2 +++ b/data/src/scripts/skill_combat/scripts/player/player_ranged.rs2 @@ -61,7 +61,7 @@ if (~player_npc_hit_roll(%damagetype) = true) { } $damage = randominc(min(%com_maxhit, npc_param(max_dealt))); $damage = min($damage, npc_stat(hitpoints)); - ~give_combat_experience(%damagestyle, $damage, npc_param(combat_xp_multiplier)); + ~give_combat_experience(%damagestyle, $damage, %npc_combat_xp_multiplier); } def_int $poison_severity = oc_param($ammo, poison_severity); diff --git a/data/src/scripts/skill_combat/scripts/pvp/pvp_combat.rs2 b/data/src/scripts/skill_combat/scripts/pvp/pvp_combat.rs2 index daeedc9239..27c0bbe311 100644 --- a/data/src/scripts/skill_combat/scripts/pvp/pvp_combat.rs2 +++ b/data/src/scripts/skill_combat/scripts/pvp/pvp_combat.rs2 @@ -87,7 +87,7 @@ return(true); [proc,pvp_in_combat_check]()(boolean) // if multi, return true -if (map_multi(.coord) = true) { +if (map_multiway(.coord) = true) { return(true); } // if you have been attacked in the last 8 ticks, and the last person to attack you isnt your opponent diff --git a/data/src/scripts/skill_combat/scripts/pvp/pvp_magic.rs2 b/data/src/scripts/skill_combat/scripts/pvp/pvp_magic.rs2 index 1a17df3b1b..6b33513b24 100644 --- a/data/src/scripts/skill_combat/scripts/pvp/pvp_magic.rs2 +++ b/data/src/scripts/skill_combat/scripts/pvp/pvp_magic.rs2 @@ -254,6 +254,10 @@ return($duration); [proc,magic_spell_maxhit](dbrow $spell_data)(int) def_int $maxhit = db_getfield($spell_data, magic_spell_table:maxhit, 0); +def_int $spell = db_getfield($spell_data, magic_spell_table:spell, 0); +if (inv_total(worn, gauntlets_of_chaos) > 0 & $spell >= ^wind_bolt & $spell <= ^fire_bolt) { + $maxhit = add($maxhit, 3); +} return($maxhit); [queue,pvp_freeze_player](int $duration) diff --git a/data/src/scripts/skill_cooking/configs/cooking_generic/cooking.obj b/data/src/scripts/skill_cooking/configs/cooking_generic/cooking.obj index c5c5372f63..ff836e7b2b 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_generic/cooking.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_generic/cooking.obj @@ -14,7 +14,6 @@ recol2d=24995 2dyan=1904 2dxan=140 weight=550g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,beer_glass @@ -34,7 +33,6 @@ recol2d=17974 2dyan=1904 2dxan=140 weight=550g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,beer_glass @@ -55,7 +53,6 @@ recol2d=24995 2dyan=1904 2dxan=140 weight=550g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,beer_glass @@ -76,7 +73,6 @@ recol2d=19748 2dyan=1904 2dxan=140 weight=550g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,beer_glass @@ -96,7 +92,6 @@ recol2d=8456 2dyan=1904 2dxan=140 weight=550g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,beer_glass @@ -117,7 +112,6 @@ recol2d=11819 2dyan=1904 2dxan=140 weight=550g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,beer_glass @@ -133,7 +127,6 @@ model=model_2491_obj 2dyan=1904 2dxan=140 weight=550g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,beer_glass @@ -148,7 +141,6 @@ model=model_2548_obj 2dyan=1904 2dxan=140 weight=50g -tradeable=yes param=crafting_glass_struct,beer_glass [swamp_tar] @@ -165,7 +157,6 @@ members=yes stackable=yes weight=1lb category=category_135 -tradeable=yes [raw_swamp_paste] name=Raw swamp paste @@ -182,7 +173,6 @@ recol1d=7399 members=yes stackable=yes weight=18oz -tradeable=yes [swamp_paste] name=Swamp paste @@ -197,7 +187,6 @@ model=model_2386_obj members=yes stackable=yes weight=18oz -tradeable=yes [chefshat] name=Chef's hat @@ -217,7 +206,6 @@ manhead=model_41_obj_wear womanhead=model_99_obj_wear iop2=Wear weight=2lb -tradeable=yes [pumpkin] name=Pumpkin @@ -232,7 +220,6 @@ model=model_2591_obj 2dxan=132 weight=500g category=category_131 -tradeable=yes [easter_egg] name=Easter egg @@ -245,7 +232,6 @@ model=model_2534_obj 2dxan=2044 weight=3oz category=category_59 -tradeable=yes // Typo of `bannana` in model name is Jagex consistent. [banana] @@ -261,7 +247,6 @@ model=inv_bannana 2dxan=280 weight=1oz category=category_86 -tradeable=yes [cabbage] name=Cabbage @@ -275,7 +260,6 @@ iop1=Eat cost=1 weight=1lb category=category_131 -tradeable=yes param=batta_message,You add the Cabbage to the gnome batta. [cabbage_draynor] @@ -290,7 +274,6 @@ iop1=Eat cost=1 weight=350g category=category_59 -tradeable=yes [spinach_roll] iop1=Eat @@ -303,7 +286,6 @@ model=model_2829_obj cost=1 weight=100g category=category_59 -tradeable=yes [kebab] name=Kebab @@ -319,7 +301,6 @@ model=model_2822_obj 2dxan=1876 weight=250g category=category_59 -tradeable=yes [chocolaty_milk] iop1=Drink @@ -337,6 +318,7 @@ category=category_59 name=Chocolaty milk desc=Milk with chocolate in it. param=next_obj_stage,bucket_empty +tradeable=no [cup_of_tea] name=Cup of tea @@ -351,7 +333,6 @@ model=model_2468_obj 2dxan=156 weight=150g members=yes -tradeable=yes param=next_obj_stage,cup_empty [cup_empty] @@ -372,7 +353,6 @@ recol3d=27482 2dxan=156 weight=50g members=yes -tradeable=yes [rotten_apples] name=Rotten apples @@ -390,6 +370,7 @@ members=yes cost=1 weight=120g category=category_86 +tradeable=no [onion] name=Onion @@ -403,7 +384,6 @@ recol1d=24108 2dxan=116 weight=150g category=category_131 -tradeable=yes param=ugthanki_kebab_struct,onion_kebab [chocolate_dust] @@ -420,7 +400,6 @@ weight=150g category=category_59 name=Chocolate dust desc=It's ground up chocolate. -tradeable=yes param=cocktail_message,You sprinkle the chocolate dust over the drink. [pot_empty] @@ -434,7 +413,6 @@ model=model_2345_obj 2dxan=112 cost=1 weight=1lb -tradeable=yes [obj_1946] name=Flour @@ -448,6 +426,7 @@ recol1d=28539 2dyan=1892 2dxan=264 weight=500g +tradeable=no [grain] name=Grain @@ -460,4 +439,3 @@ model=model_2398_obj 2dyan=88 2dxan=292 weight=600g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_generic/food_burnt.obj b/data/src/scripts/skill_cooking/configs/cooking_generic/food_burnt.obj index e76d7547be..a69c74d981 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_generic/food_burnt.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_generic/food_burnt.obj @@ -11,7 +11,6 @@ recol1d=5285 2dyan=1748 2dxan=88 weight=4oz -tradeable=yes //guess [burnt_meat] @@ -29,4 +28,3 @@ recol2d=7399 2dxan=308 cost=1 weight=8oz -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_generic/food_cooked.obj b/data/src/scripts/skill_cooking/configs/cooking_generic/food_cooked.obj index 91e4564c2e..ca2e91433e 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_generic/food_cooked.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_generic/food_cooked.obj @@ -17,7 +17,6 @@ members=yes iop1=Eat weight=600g category=category_5 -tradeable=yes param=ugthanki_kebab_struct,ugthanki_meat_kebab //guess @@ -35,7 +34,6 @@ recol1d=13472 2dxan=88 weight=5oz category=category_5 -tradeable=yes respawnrate=200 param=pizza_topping_struct,meat_topping param=uncooked_pie_struct,uncooked_meat_pie @@ -57,7 +55,6 @@ recol2d=20774 2dxan=308 weight=10oz category=category_5 -tradeable=yes respawnrate=200 param=pizza_topping_struct,meat_topping param=uncooked_pie_struct,uncooked_meat_pie @@ -81,3 +78,4 @@ recol2d=18785 iop1=Eat weight=7oz category=category_58 +tradeable=no diff --git a/data/src/scripts/skill_cooking/configs/cooking_generic/food_uncooked.obj b/data/src/scripts/skill_cooking/configs/cooking_generic/food_uncooked.obj index 6895db7fee..e593ed1d1d 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_generic/food_uncooked.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_generic/food_uncooked.obj @@ -11,7 +11,6 @@ model=model_2760_obj 2dxan=308 weight=800g members=yes -tradeable=yes category=cooking_generic [raw_beef] @@ -25,7 +24,6 @@ model=model_2760_obj 2dxan=308 cost=1 weight=12oz -tradeable=yes category=cooking_generic //guess @@ -40,7 +38,6 @@ model=model_2760_obj 2dxan=308 cost=1 weight=5oz -tradeable=yes category=cooking_generic //guess @@ -55,7 +52,6 @@ model=model_2760_obj 2dxan=308 cost=1 weight=15oz -tradeable=yes category=cooking_generic [raw_chicken] @@ -70,7 +66,6 @@ recol1d=22098 2dxan=88 cost=1 weight=6oz -tradeable=yes category=cooking_generic //guess @@ -91,4 +86,5 @@ recol2d=31041 2dxan=312 weight=8oz category=cooking_generic -param=fishing_struct,fishing_struct_lava_eel \ No newline at end of file +param=fishing_struct,fishing_struct_lava_eel +tradeable=no diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes.obj index 0bf8f88537..af19820619 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes.obj @@ -10,7 +10,6 @@ model=model_2531_obj 2dxan=164 weight=300g category=category_130 -tradeable=yes param=next_obj_stage,obj_1893 [obj_1893] @@ -29,7 +28,6 @@ recol2d=21921 2dxan=180 weight=200g category=category_130 -tradeable=yes param=next_obj_stage,obj_1895 [obj_1895] @@ -49,7 +47,6 @@ recol2d=21921 2dxan=160 weight=100g category=category_130 -tradeable=yes [chocolate_cake] iop1=Eat @@ -69,7 +66,6 @@ recol3d=10432 2dxan=164 weight=300g category=category_130 -tradeable=yes param=next_obj_stage,obj_1899 [obj_1899] @@ -90,7 +86,6 @@ recol3d=10432 cost=50 weight=200g category=category_130 -tradeable=yes param=next_obj_stage,chocolate_slice [chocolate_slice] @@ -112,7 +107,6 @@ recol3d=10432 cost=30 weight=100g category=category_130 -tradeable=yes //guess [burnt_cake] @@ -129,7 +123,6 @@ recol2d=7399 2dxan=164 cost=1 weight=150g -tradeable=yes [pot_of_flour] name=Pot of flour @@ -142,7 +135,6 @@ model=model_2406_obj 2dxan=112 cost=10 weight=3lb -tradeable=yes [bucket_milk] name=Bucket of milk @@ -169,7 +161,6 @@ model=model_2437_obj 2dyan=68 2dxan=144 weight=20g -tradeable=yes respawnrate=25 [chocolate_bar] @@ -185,7 +176,6 @@ weight=150g category=category_59 name=Chocolate bar desc=Mmmmmmm chocolate. -tradeable=yes param=grindable_ingredient_refined,chocolate_dust param=grindable_ingredient_message,You grind the chocolate to dust. param=cocktail_message,You crumble the chocolate into the drink. @@ -200,7 +190,6 @@ model=model_2756_obj 2dyan=116 2dxan=220 weight=6oz -tradeable=yes [cake_tin] name=Cake tin @@ -211,4 +200,3 @@ model=model_2596_obj 2dxan=172 cost=10 weight=100g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes_uncooked.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes_uncooked.obj index 9be3bc9d50..91c8795551 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes_uncooked.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/cakes/cakes_uncooked.obj @@ -8,5 +8,4 @@ model=model_2465_obj 2dxan=172 cost=20 weight=500g -tradeable=yes param=next_obj_stage,cake_tin \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/dough/dough.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/dough/dough.obj index e7988995b3..2e5479a323 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/dough/dough.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/dough/dough.obj @@ -10,7 +10,6 @@ recol1d=29595 2dxan=248 weight=120g members=yes -tradeable=yes [bread_dough] name=Bread dough @@ -23,7 +22,6 @@ model=model_2756_obj 2dxan=264 cost=4 weight=600g -tradeable=yes [pitta_bread] name=Pitta bread @@ -37,7 +35,6 @@ recol1d=30547 2dxan=248 weight=100g members=yes -tradeable=yes [bread] cost=12 @@ -52,7 +49,6 @@ model=model_2409_obj weight=500g category=category_59 respawnrate=200 -tradeable=yes [burnt_pitta_bread] name=Burnt pitta bread @@ -66,7 +62,6 @@ recol1d=5285 2dxan=248 weight=80g members=yes -tradeable=yes [burnt_bread] name=Burnt bread @@ -82,4 +77,3 @@ recol2d=5285 2dxan=392 cost=1 weight=350g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/battas/configs/battas.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/battas/configs/battas.obj index 69a3d8c572..6cc634f754 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/battas/configs/battas.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/battas/configs/battas.obj @@ -16,7 +16,6 @@ iop1=Eat weight=250g category=category_128 members=yes -tradeable=yes [premade_toad_batta] name=Toad batta @@ -34,7 +33,6 @@ members=yes cost=120 weight=250g category=category_128 -tradeable=yes [premade_cheese_tom_batta] name=Cheese+tom batta @@ -52,7 +50,6 @@ members=yes cost=120 weight=250g category=category_128 -tradeable=yes [premade_fruit_batta] name=Fruit batta @@ -70,7 +67,6 @@ members=yes cost=120 weight=250g category=category_128 -tradeable=yes [premade_vegetable_batta] name=Vegetable batta @@ -90,7 +86,6 @@ members=yes cost=120 weight=250g category=category_128 -tradeable=yes [odd_batta] name=Odd batta @@ -113,7 +108,6 @@ category=category_124 weight=250g iop1=Eat category=category_15 -tradeable=yes [burnt_batta] name=Burnt batta @@ -129,7 +123,6 @@ recol1d=5285 2dyan=136 2dxan=236 weight=200g -tradeable=yes [half_baked_batta] iop1=Inspect @@ -146,6 +139,7 @@ recol1d=18820 2dyan=136 2dxan=236 weight=250g +tradeable=no [raw_batta] name=Raw batta @@ -159,6 +153,7 @@ model=model_2447_obj 2dyan=136 2dxan=236 weight=250g +tradeable=no [unfinished_worm_batta1] name=Unfinished batta @@ -178,7 +173,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [worm_batta] @@ -198,7 +192,6 @@ recol2d=30385 weight=250g iop1=Eat members=yes -tradeable=yes [toad_batta] category=category_125 @@ -216,7 +209,6 @@ recol1d=224 iop1=Eat weight=250g members=yes -tradeable=yes [unfinished_cheese_tom_batta1] name=Unfinished batta @@ -234,7 +226,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [cheese_tom_batta] @@ -253,7 +244,6 @@ recol1d=31649 iop1=Eat weight=250g members=yes -tradeable=yes [unfinished_fruit_batta1] name=Unfinished batta @@ -273,7 +263,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [unfinished_fruit_batta2] @@ -294,7 +283,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [unfinished_fruit_batta3] @@ -315,7 +303,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [unfinished_fruit_batta4] @@ -336,7 +323,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [unfinished_fruit_batta5] @@ -357,7 +343,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [unfinished_fruit_batta6] @@ -378,7 +363,6 @@ recol2d=31393 weight=250g iop1=Eat category=category_15 -tradeable=yes param=gnome_cooking_type,3 [unfinished_fruit_batta7] @@ -399,7 +383,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [unfinished_fruit_batta8] @@ -418,7 +401,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [fruit_batta] @@ -437,7 +419,6 @@ recol1d=31201 iop1=Eat weight=250g members=yes -tradeable=yes [unfinished_vegetable_batta1] name=Unfinished batta @@ -457,7 +438,6 @@ iop1=Eat weight=250g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,3 [vegetable_batta] @@ -477,4 +457,3 @@ recol2d=27567 iop1=Eat weight=250g members=yes -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/cocktails/configs/cocktails.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/cocktails/configs/cocktails.obj index ac742f468b..1766827e73 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/cocktails/configs/cocktails.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/cocktails/configs/cocktails.obj @@ -10,7 +10,6 @@ model=model_2830_obj 2dyan=1888 2dxan=104 weight=1kg -tradeable=yes category=alcoholic_drinks [whisky] @@ -25,7 +24,6 @@ model=model_2660_obj 2dyan=1888 2dxan=104 weight=1kg -tradeable=yes category=alcoholic_drinks [gin] @@ -42,7 +40,6 @@ recol1d=352 2dyan=1888 2dxan=104 weight=1kg -tradeable=yes category=alcoholic_drinks [brandy] @@ -56,7 +53,6 @@ model=model_2836_obj 2dyan=1808 2dxan=76 weight=1kg -tradeable=yes category=alcoholic_drinks [cocktail_guide] @@ -72,7 +68,6 @@ recol1d=7427 2dyan=152 2dxan=256 weight=18oz -tradeable=yes [cocktail_shaker] name=Cocktail shaker @@ -86,6 +81,7 @@ model=model_2771_obj 2dxan=92 iop1=Inspect weight=150g +tradeable=no [cocktail_glass] name=Cocktail glass @@ -98,7 +94,6 @@ model=model_2655_obj cost=1 weight=100g members=yes -tradeable=yes [premade_blurberry_special] name=Blurberry special @@ -115,7 +110,6 @@ recol1d=31297 2dxan=104 category=category_83 weight=450g -tradeable=yes param=next_obj_stage,cocktail_glass [premade_chocolate_saturday] @@ -133,7 +127,6 @@ recol1d=16705 2dxan=104 category=category_83 weight=450g -tradeable=yes param=next_obj_stage,cocktail_glass [premade_drunk_dragon] @@ -149,7 +142,6 @@ model=model_2661_obj 2dxan=104 category=category_83 weight=450g -tradeable=yes param=next_obj_stage,cocktail_glass [premade_fruit_blast] @@ -171,7 +163,6 @@ recol3d=31553 2dxan=104 category=category_83 weight=450g -tradeable=yes param=next_obj_stage,cocktail_glass [premade_pineapple_punch] @@ -193,7 +184,6 @@ recol3d=31201 2dxan=104 category=category_83 weight=450g -tradeable=yes param=next_obj_stage,cocktail_glass [premade_short_green_guy] @@ -211,7 +201,6 @@ recol1d=17353 2dxan=104 category=category_83 weight=450g -tradeable=yes param=next_obj_stage,cocktail_glass [premade_wizard_blizzard] @@ -229,7 +218,6 @@ recol1d=26517 2dxan=104 category=category_83 weight=450g -tradeable=yes param=next_obj_stage,cocktail_glass [unfinished_pineapple_punch1] @@ -247,7 +235,6 @@ recol1d=31589 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -266,7 +253,6 @@ recol1d=31589 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -285,7 +271,6 @@ recol1d=31589 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -308,7 +293,6 @@ recol3d=31201 2dxan=104 category=category_83 weight=500g -tradeable=yes param=next_obj_stage,cocktail_glass [unfinished_wizard_blizzard1] @@ -326,7 +310,6 @@ recol1d=26517 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -345,7 +328,6 @@ recol1d=26517 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -364,7 +346,6 @@ recol1d=26517 2dxan=104 category=category_83 weight=500g -tradeable=yes param=next_obj_stage,cocktail_glass [unfinished_blurberry_special1] @@ -382,7 +363,6 @@ recol1d=31297 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -401,7 +381,6 @@ recol1d=31297 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -420,7 +399,6 @@ recol1d=31297 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -439,7 +417,6 @@ recol1d=31297 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -458,7 +435,6 @@ recol1d=31297 2dxan=104 category=category_83 weight=500g -tradeable=yes param=next_obj_stage,cocktail_glass [unfinished_chocolate_saturday1] @@ -476,7 +452,6 @@ recol1d=25199 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -495,7 +470,6 @@ recol1d=16705 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -514,7 +488,6 @@ recol1d=16705 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -533,7 +506,6 @@ recol1d=16705 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -552,7 +524,6 @@ recol1d=16705 2dxan=104 category=category_83 weight=500g -tradeable=yes param=next_obj_stage,cocktail_glass [unfinished_short_green_guy1] @@ -570,7 +541,6 @@ recol1d=17353 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -589,7 +559,6 @@ recol1d=17353 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -608,7 +577,6 @@ recol1d=17353 2dxan=104 category=category_83 weight=500g -tradeable=yes param=next_obj_stage,cocktail_glass [unfinished_fruit_blast1] @@ -626,7 +594,6 @@ recol1d=31393 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -649,7 +616,6 @@ recol3d=31553 2dxan=104 category=category_83 weight=500g -tradeable=yes param=next_obj_stage,cocktail_glass [unfinished_drunk_dragon1] @@ -665,7 +631,6 @@ model=model_2532_obj 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -684,7 +649,6 @@ recol1d=473 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -701,7 +665,6 @@ model=model_2661_obj 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass param=gnome_cooking_type,0 @@ -718,7 +681,6 @@ model=model_2661_obj 2dxan=104 category=category_83 weight=500g -tradeable=yes param=next_obj_stage,cocktail_glass [odd_cocktail1] @@ -737,7 +699,6 @@ recol1d=16912 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass [odd_cocktail2] @@ -756,7 +717,6 @@ recol1d=16912 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass [odd_cocktail3] @@ -775,7 +735,6 @@ recol1d=16912 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass [odd_cocktail4] @@ -798,7 +757,6 @@ recol3d=15855 2dxan=104 weight=400g category=category_15 -tradeable=yes param=next_obj_stage,cocktail_glass [lemon] @@ -813,7 +771,6 @@ model=model_2501_obj 2dxan=700 category=category_120 weight=100g -tradeable=yes [lemon_chunks] name=Lemon chunks @@ -832,7 +789,6 @@ recol1d=31660 2dxan=244 category=category_120 weight=80g -tradeable=yes param=cocktail_message,You add the diced lemon to the drink. [lemon_slices] @@ -851,7 +807,6 @@ recol2d=31637 2dxan=284 category=category_120 weight=80g -tradeable=yes param=cocktail_message,You add a lemon slice to the drink. [orange] @@ -866,7 +821,6 @@ model=model_2640_obj 2dxan=308 category=category_120 weight=110g -tradeable=yes [orange_chunks] name=Orange chunks @@ -883,7 +837,6 @@ model=model_2573_obj 2dxan=244 category=category_120 weight=90g -tradeable=yes param=cocktail_message,You add the diced orange to the drink. [orange_slices] @@ -900,7 +853,6 @@ recol1d=31435 2dxan=284 category=category_120 weight=90g -tradeable=yes param=cocktail_message,You add an orange slice to the dirnk. [pineapple] @@ -916,7 +868,6 @@ model=model_2736_obj 2dxan=228 category=category_120 weight=150g -tradeable=yes [pineapple_chunks] name=Pineapple chunks @@ -935,7 +886,6 @@ recol1d=31429 2dxan=244 category=category_120 weight=120g -tradeable=yes param=pizza_topping_struct,pineapple_topping [pineapple_ring] @@ -951,7 +901,6 @@ model=model_2653_obj 2dxan=248 category=category_120 weight=30g -tradeable=yes param=pizza_topping_struct,pineapple_topping [lime] @@ -966,7 +915,6 @@ model=model_2816_obj 2dxan=596 category=category_120 weight=100g -tradeable=yes [lime_chunks] name=Lime chunks @@ -985,7 +933,6 @@ recol1d=23539 2dxan=244 category=category_120 weight=80g -tradeable=yes [lime_slices] name=Lime slices @@ -1003,5 +950,4 @@ recol2d=544 2dxan=284 category=category_120 weight=80g -tradeable=yes param=cocktail_message,You add a lime slice to the drink. \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/crunchies/configs/crunchies.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/crunchies/configs/crunchies.obj index 0288b725b9..5a57cbe563 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/crunchies/configs/crunchies.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/crunchies/configs/crunchies.obj @@ -12,7 +12,6 @@ members=yes cost=85 weight=250g category=category_128 -tradeable=yes [premade_choc_chip_crunchies] name=Chocchip crunchies @@ -26,7 +25,6 @@ members=yes cost=85 weight=250g category=category_128 -tradeable=yes [premade_spicy_crunchies] name=Spicy crunchies @@ -42,7 +40,6 @@ members=yes cost=85 weight=250g category=category_128 -tradeable=yes [premade_toad_crunchies] name=Toad crunchies @@ -58,7 +55,6 @@ members=yes cost=85 weight=250g category=category_128 -tradeable=yes [odd_crunchies] iop1=Eat @@ -75,7 +71,6 @@ recol1d=12576 2dxan=220 weight=300g category=category_15 -tradeable=yes [burnt_crunchies] name=Burnt crunchies @@ -89,7 +84,6 @@ recol1d=5285 2dzoom=650 2dxan=220 weight=250g -tradeable=yes [half_baked_crunchies] iop1=Inspect @@ -106,6 +100,7 @@ recol1d=18820 2dyan=1664 2dxan=252 weight=350g +tradeable=no [raw_crunchies] name=Raw crunchies @@ -119,6 +114,7 @@ model=model_2723_obj 2dyan=1664 2dxan=252 weight=400g +tradeable=no [unfinished_worm_crunchies1] name=Unfinished crunchy @@ -133,7 +129,6 @@ weight=300g category=category_15 iop1=Eat members=yes -tradeable=yes param=gnome_cooking_type,2 [worm_crunchies] @@ -150,7 +145,6 @@ recol1d=29459 iop1=Eat weight=250g members=yes -tradeable=yes [unfinished_choc_chip_crunchies1] name=Unfinished crunchy @@ -164,7 +158,6 @@ iop1=Eat weight=300g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,2 [choc_chip_crunchies] @@ -180,7 +173,6 @@ weight=250g iop1=Eat weight=250g members=yes -tradeable=yes [unfinished_spicy_crunchies1] name=Unfinished crunchy @@ -196,7 +188,6 @@ iop1=Eat weight=300g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,2 [spicy_crunchies] @@ -213,7 +204,6 @@ recol1d=31105 iop1=Eat weight=250g members=yes -tradeable=yes [unfinished_toad_crunchies1] name=Unfinished crunchy @@ -229,7 +219,6 @@ iop1=Eat weight=300g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,2 [toad_crunchies] @@ -246,4 +235,3 @@ recol1d=512 members=yes iop1=Eat weight=250g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnome_cooking.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnome_cooking.obj index 47ccb658df..b427c4789f 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnome_cooking.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnome_cooking.obj @@ -9,7 +9,6 @@ model=model_2431_obj 2dxan=136 weight=200g members=yes -tradeable=yes [dwellberry] name=Dwellberries @@ -25,7 +24,6 @@ model=model_2808_obj 2dxan=180 category=category_120 weight=14g -tradeable=yes param=singular_name,dwellberry param=batta_message,You add the dwell berries to the gnome batta. @@ -42,7 +40,6 @@ model=model_2743_obj 2dxan=664 category=category_120 weight=14g -tradeable=yes param=singular_name,equa leaf param=plural_name,equa leaves param=cocktail_message,You sprinkle the leaves over the drink. @@ -63,7 +60,6 @@ model=model_2636_obj 2dxan=128 category=category_120 weight=200g -tradeable=yes param=cocktail_message,You pour the thick cream into the drink. [swamp_toad] @@ -79,7 +75,6 @@ model=model_2622_obj 2dyan=128 2dxan=352 weight=500g -tradeable=yes //guess [toad_legs] @@ -96,7 +91,6 @@ model=model_2668_obj 2dxan=340 weight=150g category=category_128 -tradeable=yes param=plural_name,toad's legs [equa_toad_legs] @@ -113,7 +107,6 @@ model=model_2668_obj 2dxan=340 weight=150g category=category_15 -tradeable=yes [spicy_toad_legs] iop1=Eat @@ -129,7 +122,6 @@ model=model_2668_obj 2dxan=340 weight=150g category=category_15 -tradeable=yes [seasoned_toad_legs] iop1=Eat @@ -145,7 +137,6 @@ model=model_2668_obj 2dxan=340 weight=150g category=category_15 -tradeable=yes param=singular_name,toad's legs param=plural_name,toad's legs param=batta_message,You add the seasoned toad's legs to the gnome batta. @@ -164,7 +155,6 @@ model=model_2519_obj 2dxan=404 weight=100g category=category_15 -tradeable=yes param=batta_message,You add the spicy king worm to the gnome batta. [king_worm] @@ -181,8 +171,6 @@ model=model_2519_obj 2dxan=404 weight=120g category=category_128 -tradeable=yes - [batta_tin] name=Batta tin @@ -196,6 +184,7 @@ model=model_2659_obj 2dxan=236 weight=100g param=gnome_cooking_struct,batta_tin +tradeable=no [crunchy_tray] name=Crunchy tray @@ -209,6 +198,7 @@ model=model_2612_obj 2dxan=252 weight=100g param=gnome_cooking_struct,crunchy_tray +tradeable=no [gnomebowl_mould] name=Gnomebowl mould @@ -221,6 +211,7 @@ model=model_2814_obj 2dxan=192 weight=150g param=gnome_cooking_struct,gnomebowl_mould +tradeable=no [gianne_cook_book] name=Gianne's cook book @@ -233,7 +224,6 @@ model=model_2794_obj 2dyan=152 2dxan=256 weight=18oz -tradeable=yes [gnome_spice] name=Gnome spice @@ -246,7 +236,6 @@ model=model_2431_obj cost=2 weight=150g members=yes -tradeable=yes param=singular_name,spice dash param=plural_name,spice dashes param=crunchies_message,You sprinkle the spice into the dough. @@ -266,4 +255,3 @@ recol1d=23146 cost=2 weight=500g members=yes -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnomebowls/configs/gnomebowls.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnomebowls/configs/gnomebowls.obj index 2560d4f5b4..9396c0dd2a 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnomebowls/configs/gnomebowls.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/gnome_cooking/gnomebowls/configs/gnomebowls.obj @@ -14,7 +14,6 @@ weight=350g iop1=Eat weight=350g members=yes -tradeable=yes [premade_tangled_toads_legs] cost=2 @@ -29,7 +28,6 @@ model=model_2579_obj iop1=Eat weight=350g members=yes -tradeable=yes [premade_worm_hole] category=category_127 @@ -44,7 +42,6 @@ model=model_2609_obj iop1=Eat weight=350g members=yes -tradeable=yes [premade_veg_ball] name=Veg ball @@ -59,7 +56,6 @@ model=model_2823_obj iop1=Eat weight=350g members=yes -tradeable=yes [chocolate_bomb] name=Chocolate bomb @@ -76,7 +72,6 @@ members=yes cost=160 weight=350g category=category_128 -tradeable=yes [tangled_toads_legs] name=Tangled toad's legs @@ -91,7 +86,6 @@ members=yes cost=160 weight=350g category=category_128 -tradeable=yes [worm_hole] name=Worm hole @@ -106,7 +100,6 @@ members=yes cost=150 weight=350g category=category_128 -tradeable=yes [veg_ball] name=Veg ball @@ -121,7 +114,6 @@ members=yes cost=150 weight=350g category=category_128 -tradeable=yes [odd_gnomebowl] name=Odd gnomebowl @@ -141,7 +133,6 @@ recol2d=15745 weight=250g iop1=Eat category=category_15 -tradeable=yes [burnt_gnomebowl] name=Burnt gnomebowl @@ -158,7 +149,6 @@ recol2d=10570 2dyan=1888 2dxan=192 weight=220g -tradeable=yes [half_baked_gnomebowl] iop1=Inspect @@ -172,6 +162,7 @@ model=model_2797_obj 2dyan=1888 2dxan=192 weight=275g +tradeable=no [raw_gnomebowl] name=Raw gnomebowl @@ -188,6 +179,7 @@ recol2d=26315 2dyan=1888 2dxan=192 weight=300g +tradeable=no [unfinished_chocolate_bomb1] name=Unfinished bowl @@ -208,7 +200,6 @@ weight=300g members=yes iop1=Eat category=category_15 -tradeable=yes param=gnome_cooking_type,1 [unfinished_chocolate_bomb2] @@ -228,7 +219,6 @@ iop1=Eat weight=300g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,1 [unfinished_chocolate_bomb3] @@ -248,7 +238,6 @@ iop1=Eat weight=300g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,1 [unfinished_worm_hole1] @@ -264,7 +253,6 @@ iop1=Eat weight=300g category=category_15 members=yes -tradeable=yes param=gnome_cooking_type,1 [unfinished_veg_ball1] @@ -282,5 +270,4 @@ members=yes weight=300g iop1=Eat category=category_15 -tradeable=yes param=gnome_cooking_type,1 diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/oomlie_bird_meat/oomlie_bird_meat.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/oomlie_bird_meat/oomlie_bird_meat.obj index e3187436be..f56021a9c6 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/oomlie_bird_meat/oomlie_bird_meat.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/oomlie_bird_meat/oomlie_bird_meat.obj @@ -11,7 +11,6 @@ recol1d=22098 members=yes cost=10 weight=225g -tradeable=yes category=cooking_generic [palm_leaf] @@ -26,7 +25,6 @@ model=model_2651_obj 2dxan=292 weight=100g members=yes -tradeable=yes //guess [burnt_wrapped_oomlie] @@ -49,7 +47,6 @@ recol4d=8456 cost=1 weight=275g members=yes -tradeable=yes [burnt_oomlie] name=Burnt oomlie @@ -64,7 +61,6 @@ recol1d=5285 2dyan=1748 2dxan=88 weight=4oz -tradeable=yes //guess [cooked_wrapped_oomlie] @@ -89,7 +85,6 @@ members=yes cost=35 weight=300g category=category_59 -tradeable=yes //guess [wrapped_oomlie] @@ -104,5 +99,4 @@ model=model_2687_obj cost=16 weight=325g members=yes -tradeable=yes category=cooking_generic \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies.obj index a2fb14aa37..a1148c5105 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies.obj @@ -16,7 +16,6 @@ recol3d=20971 2dxan=192 weight=450g category=category_129 -tradeable=yes param=next_obj_stage,half_an_apple_pie [redberry_pie] @@ -37,7 +36,6 @@ recol3d=20971 2dxan=192 weight=450g category=category_129 -tradeable=yes param=next_obj_stage,obj_2333 [meat_pie] @@ -58,7 +56,6 @@ recol3d=20971 2dxan=192 weight=450g category=category_129 -tradeable=yes param=next_obj_stage,obj_2331 [obj_2331] @@ -85,7 +82,6 @@ recol6d=9315 2dxan=192 weight=225g category=category_129 -tradeable=yes param=next_obj_stage,piedish [obj_2333] @@ -112,7 +108,6 @@ recol6d=18564 2dxan=192 weight=225g category=category_129 -tradeable=yes param=next_obj_stage,piedish [half_an_apple_pie] @@ -139,7 +134,6 @@ recol6d=22384 2dxan=192 weight=225g category=category_129 -tradeable=yes param=next_obj_stage,piedish [burnt_pie] @@ -159,7 +153,6 @@ recol3d=20971 2dxan=192 cost=1 weight=350g -tradeable=yes [redberry] cost=3 @@ -172,7 +165,6 @@ model=model_2358_obj 2dyan=668 2dxan=404 weight=7g -tradeable=yes param=uncooked_pie_struct,uncooked_redberry_pie [pie_shell] @@ -191,7 +183,6 @@ recol3d=20971 2dxan=192 cost=4 weight=250g -tradeable=yes [cooking_apple] name=Cooking apple @@ -202,7 +193,6 @@ model=model_2404_obj 2dxan=212 cost=1 weight=3oz -tradeable=yes param=uncooked_pie_struct,uncooked_apple_pie [piedish] @@ -221,4 +211,3 @@ recol3d=20971 2dxan=192 cost=3 weight=100g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies_uncooked.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies_uncooked.obj index 955856e86d..9f90ca9b49 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies_uncooked.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pies/pies_uncooked.obj @@ -15,7 +15,6 @@ recol3d=20971 2dxan=192 cost=16 weight=500g -tradeable=yes //guess [uncooked_meat_pie] @@ -34,7 +33,6 @@ recol3d=20971 2dxan=192 cost=8 weight=500g -tradeable=yes //guess [uncooked_redberry_pie] @@ -53,4 +51,3 @@ recol3d=20971 2dxan=192 cost=6 weight=500g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza.obj index 6305b79e2d..4eb7110e27 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza.obj @@ -15,7 +15,6 @@ recol2d=19489 2dxan=272 weight=400g category=category_132 -tradeable=yes [meat_pizza] iop1=Eat @@ -35,7 +34,6 @@ recol3d=19489 2dxan=260 weight=900g category=category_132 -tradeable=yes param=next_obj_stage,obj_2295 [obj_2295] @@ -57,7 +55,6 @@ recol3d=19489 2dxan=272 weight=450g category=category_132 -tradeable=yes [anchovy_pizza] iop1=Eat @@ -77,7 +74,6 @@ recol3d=19489 2dxan=260 weight=900g category=category_132 -tradeable=yes param=next_obj_stage,obj_2299 [obj_2299] @@ -99,7 +95,6 @@ recol3d=19489 2dxan=272 weight=450g category=category_132 -tradeable=yes [pineapple_pizza] iop1=Eat @@ -120,7 +115,6 @@ recol3d=19489 weight=900g category=category_132 members=yes -tradeable=yes param=next_obj_stage,obj_2303 [obj_2303] @@ -143,7 +137,6 @@ recol3d=19489 weight=450g category=category_132 members=yes -tradeable=yes [plain_pizza] iop1=Eat @@ -161,7 +154,6 @@ recol2d=19489 cost=40 weight=800g category=category_132 -tradeable=yes param=next_obj_stage,obj_2291 [burnt_pizza] @@ -180,7 +172,6 @@ recol3d=3171 2dyan=176 2dxan=260 weight=700g -tradeable=yes [tomato] name=Tomato @@ -195,7 +186,6 @@ model=model_2632_obj weight=80g category=category_86 category=category_131 -tradeable=yes param=ugthanki_kebab_struct,tomato_kebab [cheese] @@ -209,7 +199,6 @@ model=model_2365_obj 2dxan=116 weight=200g category=category_59 -tradeable=yes param=singular_name,cheese portion param=batta_message,You crumble cheese over the gnome batta. @@ -225,7 +214,6 @@ recol1d=29492 2dyan=176 2dxan=260 weight=100g -tradeable=yes [incomplete_pizza] name=Incomplete pizza @@ -241,4 +229,3 @@ recol2d=19489 2dyan=176 2dxan=260 weight=600g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza_uncooked.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza_uncooked.obj index b37b76828a..d7a34e5d43 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza_uncooked.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/pizza/pizza_uncooked.obj @@ -13,4 +13,3 @@ recol2d=19489 2dyan=176 2dxan=260 weight=800g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew.obj index cc8300e8c0..16ca9917e0 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew.obj @@ -10,7 +10,6 @@ recol1d=14800 2dyan=1856 2dxan=204 weight=1kg -tradeable=yes //guess [incomplete_stew_meat] @@ -24,7 +23,6 @@ recol1d=14800 2dyan=1856 2dxan=204 weight=1200g -tradeable=yes //guess [burnt_stew] @@ -39,7 +37,6 @@ recol1d=4228 2dxan=204 iop1=Empty Bowl weight=1300g -tradeable=yes //guess [burnt_curry] @@ -55,7 +52,6 @@ recol1d=4228 members=yes iop1=Empty Bowl weight=1300g -tradeable=yes [potato] name=Potato @@ -69,7 +65,6 @@ model=model_2766_obj 2dxan=156 weight=500g category=category_131 -tradeable=yes //guess [stew] @@ -85,7 +80,6 @@ recol1d=11488 2dxan=204 weight=1500g category=category_59 -tradeable=yes param=next_obj_stage,bowl_empty //guess @@ -103,5 +97,4 @@ recol1d=22881 weight=1500g category=category_59 members=yes -tradeable=yes param=next_obj_stage,bowl_empty \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew_uncooked.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew_uncooked.obj index 3aba5d47c3..7b4a46762f 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew_uncooked.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/stew/stew_uncooked.obj @@ -10,7 +10,6 @@ recol1d=19974 2dyan=1856 2dxan=204 weight=1500g -tradeable=yes category=cooking_generic //guess @@ -26,5 +25,4 @@ recol1d=31201 2dxan=204 weight=1500g members=yes -tradeable=yes category=cooking_generic \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/ugthanki_kebab/ugthanki_kebab.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/ugthanki_kebab/ugthanki_kebab.obj index e0e1ec368a..57aa18a074 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/ugthanki_kebab/ugthanki_kebab.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/ugthanki_kebab/ugthanki_kebab.obj @@ -10,7 +10,6 @@ cost=3 weight=200g category=category_86 members=yes -tradeable=yes param=ugthanki_kebab_struct,chopped_tomato_kebab [chopped_onion] @@ -25,7 +24,6 @@ weight=200g category=category_131 cost=3 members=yes -tradeable=yes param=ugthanki_kebab_struct,chopped_onion_kebab [chopped_ugthanki] @@ -39,7 +37,6 @@ model=model_2556_obj cost=5 weight=200g members=yes -tradeable=yes param=ugthanki_kebab_struct,chopped_ugthanki_kebab [chopped_onion_tomato] @@ -54,7 +51,6 @@ cost=5 weight=300g category=category_131 members=yes -tradeable=yes param=ugthanki_kebab_struct,chopped_onion_tomato_kebab [chopped_ugthanki_onion] @@ -68,7 +64,6 @@ model=model_2556_obj cost=7 weight=300g members=yes -tradeable=yes param=ugthanki_kebab_struct,chopped_ugthanki_onion_kebab [chopped_ugthanki_tomato] @@ -82,7 +77,6 @@ model=model_2556_obj cost=7 weight=300g members=yes -tradeable=yes param=ugthanki_kebab_struct,chopped_ugthanki_tomato_kebab [kebab_mix] @@ -96,7 +90,6 @@ model=model_2556_obj cost=9 weight=400g members=yes -tradeable=yes [dodgy_ugthanki_kebab] name=Ugthanki kebab @@ -113,7 +106,6 @@ members=yes iop1=Eat weight=500g category=category_59 -tradeable=yes [ugthanki_kebab] name=Ugthanki kebab @@ -130,4 +122,3 @@ members=yes iop1=Eat weight=500g category=category_59 -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/wine/wine.obj b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/wine/wine.obj index 993e493856..33c149d313 100644 --- a/data/src/scripts/skill_cooking/configs/cooking_inv/configs/wine/wine.obj +++ b/data/src/scripts/skill_cooking/configs/cooking_inv/configs/wine/wine.obj @@ -12,7 +12,6 @@ recol1d=25765 2dxan=260 cost=1 weight=1500g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,jug_empty @@ -29,7 +28,6 @@ recol1d=17451 2dxan=404 cost=1 weight=250g -tradeable=yes respawnrate=80 [jug_wine] @@ -46,7 +44,6 @@ recol1d=25765 2dyan=84 2dxan=260 weight=1500g -tradeable=yes category=alcoholic_drinks param=next_obj_stage,jug_empty @@ -65,7 +62,6 @@ recol1d=25765 2dxan=260 iop1=Drink weight=1kg -tradeable=yes category=alcoholic_drinks param=next_obj_stage,jug_empty @@ -82,4 +78,3 @@ recol1d=25765 2dyan=84 2dxan=260 weight=1500g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/cocktail_mixing.rs2 b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/cocktail_mixing.rs2 index 1445928817..2752409870 100644 --- a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/cocktail_mixing.rs2 +++ b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/cocktail_mixing.rs2 @@ -84,6 +84,7 @@ switch_obj(last_useitem) { case half_baked_gnomebowl : @add_bowl_ingredient(last_item); case half_baked_batta : @add_cocktail_ingredient(last_item); case half_baked_crunchies : @add_crunchies_ingredient(last_item); + case raw_chompy : @quest_chompybird_add_ingredients_to_chompy_message; case default : ~displaymessage(^dm_default); } diff --git a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/gnome_battas.rs2 b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/gnome_battas.rs2 index 7e9d3600da..8e8722491e 100644 --- a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/gnome_battas.rs2 +++ b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/gnome_cooking/gnome_battas.rs2 @@ -49,6 +49,7 @@ if_close; //p_stopaction; switch_obj(last_useitem) { case half_baked_batta : @add_batta_ingredient(last_item); + case raw_chompy : @quest_chompybird_add_ingredients_to_chompy_message; case default : ~displaymessage(^dm_default); } diff --git a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/pizza/pizza.rs2 b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/pizza/pizza.rs2 index 18d9276e34..a024493b13 100644 --- a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/pizza/pizza.rs2 +++ b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/pizza/pizza.rs2 @@ -15,6 +15,7 @@ switch_obj (last_useitem) { case incomplete_pizza : mes("I think it's already got enough tomato on."); case half_baked_gnomebowl : @add_bowl_ingredient(last_item); case half_baked_batta : @add_batta_ingredient(last_item); + case raw_chompy : @quest_chompybird_add_ingredients_to_chompy_message; case default : ~displaymessage(^dm_default); }; diff --git a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/stew/stew.rs2 b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/stew/stew.rs2 index 9ba391b903..f67c4e7abb 100644 --- a/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/stew/stew.rs2 +++ b/data/src/scripts/skill_cooking/scripts/cooking_inv/scripts/stew/stew.rs2 @@ -3,6 +3,7 @@ switch_obj (last_useitem) { case bowl_water : @make_incomplete_stew(last_slot); case incomplete_stew_meat : @make_uncooked_stew(last_slot, last_useslot); case bowl_empty : @no_water_stew_message; + case raw_chompy : @quest_chompybird_add_ingredients_to_chompy_message; case default : ~displaymessage(^dm_default); }; diff --git a/data/src/scripts/skill_crafting/configs/crafting.obj b/data/src/scripts/skill_crafting/configs/crafting.obj index b8325c67cb..e1375d742b 100644 --- a/data/src/scripts/skill_crafting/configs/crafting.obj +++ b/data/src/scripts/skill_crafting/configs/crafting.obj @@ -21,7 +21,6 @@ manwear2=model_284_obj_wear womanwear=model_444_obj_wear,0 womanwear2=model_448_obj_wear weight=7g -tradeable=yes [blessedstar] name=Holy symbol @@ -46,7 +45,6 @@ manwear2=model_284_obj_wear womanwear=model_444_obj_wear,0 womanwear2=model_448_obj_wear weight=7g -tradeable=yes param=stabdefence,2 param=slashdefence,2 param=crushdefence,2 @@ -79,7 +77,6 @@ womanwear=model_444_obj_wear,0 womanwear2=model_450_obj_wear iop2=Wear weight=7g -tradeable=yes [unholy_symbol] name=Unholy symbol @@ -112,6 +109,7 @@ param=crushattack,2 param=magicattack,2 param=rangeattack,2 param=prayerbonus,8 +tradeable=no [needle] @@ -125,7 +123,6 @@ model=model_2770_obj 2dyan=868 2dxan=368 weight=1g -tradeable=yes [thread] name=Thread @@ -138,7 +135,6 @@ model=model_2831_obj 2dyan=1644 2dxan=248 weight=3g -tradeable=yes [shears] name=Shears @@ -151,7 +147,6 @@ womanwear=model_525_obj_wear,6 2dyan=136 2dxan=300 weight=4oz -tradeable=yes [cow_hide] name=Cow hide @@ -163,7 +158,6 @@ model=model_2338_obj 2dyan=116 2dxan=440 weight=6lb -tradeable=yes [chisel] name=Chisel @@ -175,7 +169,6 @@ model=model_2489_obj 2dyan=1928 2dxan=404 weight=1lb -tradeable=yes [brown_apron] name=Brown apron @@ -196,7 +189,6 @@ wearpos=torso manwear=model_305_obj_wear,0 womanwear=model_467_obj_wear,0 weight=1lb -tradeable=yes [ball_of_wool] name=Ball of wool @@ -209,7 +201,6 @@ model=model_2795_obj 2dyan=448 2dxan=152 weight=12g -tradeable=yes [bow_string] members=yes @@ -223,7 +214,6 @@ model=model_2552_obj 2dyan=1872 2dxan=148 weight=14g -tradeable=yes [woad_leaf] name=Woad leaf @@ -241,7 +231,6 @@ recol2d=531 2dxan=344 weight=10g stackable=yes -tradeable=yes [bronze_wire] name=Bronze wire @@ -254,7 +243,6 @@ model=model_2715_obj 2dxan=332 weight=5g members=yes -tradeable=yes [dragonhide_black] name=Dragonhide @@ -271,7 +259,6 @@ recol2d=12684 2dxan=440 weight=7lb members=yes -tradeable=yes [dragonhide_red] name=Dragonhide @@ -288,7 +275,6 @@ recol2d=12288 2dxan=440 weight=7lb members=yes -tradeable=yes [dragonhide_blue] name=Dragonhide @@ -305,7 +291,6 @@ recol2d=93 2dxan=440 weight=7lb members=yes -tradeable=yes [dragonhide_green] name=Dragonhide @@ -318,4 +303,3 @@ model=model_2356_obj 2dxan=440 weight=7lb members=yes -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/dye_cape/capes.obj b/data/src/scripts/skill_crafting/configs/dye_cape/capes.obj index a365a5d3f8..df15eb3761 100644 --- a/data/src/scripts/skill_crafting/configs/dye_cape/capes.obj +++ b/data/src/scripts/skill_crafting/configs/dye_cape/capes.obj @@ -17,7 +17,6 @@ wearpos=back manwear=model_323_obj_wear,0 womanwear=model_481_obj_wear,0 weight=1lb -tradeable=yes param=slashdefence,1 param=crushdefence,1 param=rangedefence,2 @@ -44,7 +43,6 @@ wearpos=back manwear=model_323_obj_wear,0 womanwear=model_481_obj_wear,0 weight=1lb -tradeable=yes param=slashdefence,1 param=crushdefence,1 param=rangedefence,2 @@ -71,7 +69,6 @@ wearpos=back manwear=model_323_obj_wear,0 womanwear=model_481_obj_wear,0 weight=1lb -tradeable=yes param=slashdefence,1 param=crushdefence,1 param=rangedefence,2 @@ -98,7 +95,6 @@ wearpos=back manwear=model_323_obj_wear,0 womanwear=model_481_obj_wear,0 weight=1lb -tradeable=yes param=slashdefence,1 param=crushdefence,1 param=rangedefence,2 @@ -125,7 +121,6 @@ wearpos=back manwear=model_323_obj_wear,0 womanwear=model_481_obj_wear,0 weight=1lb -tradeable=yes param=slashdefence,1 param=crushdefence,1 param=rangedefence,2 @@ -152,7 +147,6 @@ wearpos=back manwear=model_323_obj_wear,0 womanwear=model_481_obj_wear,0 weight=1lb -tradeable=yes param=slashdefence,1 param=crushdefence,1 param=rangedefence,2 @@ -179,7 +173,6 @@ wearpos=back manwear=model_323_obj_wear,0 womanwear=model_481_obj_wear,0 weight=1lb -tradeable=yes param=slashdefence,1 param=crushdefence,1 param=rangedefence,2 diff --git a/data/src/scripts/skill_crafting/configs/dye_cape/dyes.obj b/data/src/scripts/skill_crafting/configs/dye_cape/dyes.obj index deb78eab7d..c40ddaf945 100644 --- a/data/src/scripts/skill_crafting/configs/dye_cape/dyes.obj +++ b/data/src/scripts/skill_crafting/configs/dye_cape/dyes.obj @@ -11,7 +11,6 @@ recol1d=30753 2dxan=124 weight=20g category=category_82 -tradeable=yes param=crafting_capes_struct,red_dye [yellow_dye] @@ -27,7 +26,6 @@ recol1d=31649 2dxan=124 weight=20g category=category_82 -tradeable=yes param=crafting_capes_struct,yellow_dye [blue_dye] @@ -43,7 +41,6 @@ recol1d=31 2dxan=124 weight=20g category=category_82 -tradeable=yes param=crafting_capes_struct,blue_dye [orange_dye] @@ -59,7 +56,6 @@ recol1d=28097 2dxan=124 weight=20g category=category_82 -tradeable=yes param=crafting_capes_struct,orange_dye [green_dye] @@ -75,7 +71,6 @@ recol1d=768 2dxan=124 weight=20g category=category_82 -tradeable=yes param=crafting_capes_struct,green_dye [purple_dye] @@ -91,5 +86,4 @@ recol1d=19487 2dxan=124 weight=20g category=category_82 -tradeable=yes param=crafting_capes_struct,purple_dye diff --git a/data/src/scripts/skill_crafting/configs/gem/uncut_gems.obj b/data/src/scripts/skill_crafting/configs/gem/uncut_gems.obj index 291a69dead..8825337497 100644 --- a/data/src/scripts/skill_crafting/configs/gem/uncut_gems.obj +++ b/data/src/scripts/skill_crafting/configs/gem/uncut_gems.obj @@ -12,7 +12,6 @@ recol1d=32767 2dzan=1860 2dxan=368 weight=3g -tradeable=yes [uncut_ruby] cost=100 @@ -28,7 +27,6 @@ recol1d=16417 2dzan=1860 2dxan=368 weight=3g -tradeable=yes [uncut_emerald] cost=50 @@ -44,7 +42,6 @@ recol1d=672 2dzan=1860 2dxan=368 weight=3g -tradeable=yes [uncut_sapphire] cost=25 @@ -60,7 +57,6 @@ recol1d=23 2dzan=1860 2dxan=368 weight=3g -tradeable=yes respawnrate=500 [uncut_opal] @@ -78,7 +74,6 @@ recol1d=29587 2dxan=368 weight=3g members=yes -tradeable=yes [uncut_jade] cost=30 @@ -95,7 +90,6 @@ recol1d=22512 2dxan=368 weight=3g members=yes -tradeable=yes [uncut_red_topaz] cost=40 @@ -112,7 +106,6 @@ recol1d=30765 2dxan=368 weight=3g members=yes -tradeable=yes [uncut_dragonstone] cost=1000 @@ -129,4 +122,3 @@ recol1d=12307 2dxan=368 weight=3g members=yes -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/glass/glass.obj b/data/src/scripts/skill_crafting/configs/glass/glass.obj index 362a90c3ad..bd0397c6e4 100644 --- a/data/src/scripts/skill_crafting/configs/glass/glass.obj +++ b/data/src/scripts/skill_crafting/configs/glass/glass.obj @@ -11,7 +11,6 @@ weight=2lb members=yes name=Molten glass desc=Hot glass ready to be blown into useful objects. -tradeable=yes [soda_ash] name=Soda ash @@ -26,7 +25,6 @@ recol1d=28539 2dyan=1892 2dxan=264 weight=2oz -tradeable=yes [bucket_sand] members=yes @@ -41,7 +39,6 @@ recol1d=24205 2dyan=1688 2dxan=204 weight=2500g -tradeable=yes [glassblowing_pipe] name=Glassblowing pipe @@ -56,4 +53,3 @@ womanwear=model_515_obj_wear,0 2dyan=132 2dxan=228 weight=2oz -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/jewellery/amulets.obj b/data/src/scripts/skill_crafting/configs/jewellery/amulets.obj index f771ced7ef..1210051206 100644 --- a/data/src/scripts/skill_crafting/configs/jewellery/amulets.obj +++ b/data/src/scripts/skill_crafting/configs/jewellery/amulets.obj @@ -11,7 +11,6 @@ recol1d=22241 2dyan=100 2dxan=304 weight=4g -tradeable=yes param=crafting_jewelry_struct,unstrung_gold_amulet [unstrung_sapphire_amulet] @@ -27,7 +26,6 @@ recol1d=23 2dyan=100 2dxan=304 weight=4g -tradeable=yes param=crafting_jewelry_struct,unstrung_sapphire_amulet [unstrung_emerald_amulet] @@ -43,7 +41,6 @@ recol1d=672 2dyan=100 2dxan=304 weight=4g -tradeable=yes param=crafting_jewelry_struct,unstrung_emerald_amulet [unstrung_ruby_amulet] @@ -59,7 +56,6 @@ recol1d=30753 2dyan=100 2dxan=304 weight=4g -tradeable=yes param=crafting_jewelry_struct,unstrung_ruby_amulet [unstrung_diamond_amulet] @@ -73,7 +69,6 @@ model=model_2550_obj 2dyan=100 2dxan=304 weight=4g -tradeable=yes param=crafting_jewelry_struct,unstrung_diamond_amulet [unstrung_dragonstone_amulet] @@ -90,7 +85,6 @@ recol1d=12307 2dxan=304 weight=4g members=yes -tradeable=yes param=crafting_jewelry_struct,unstrung_dragonstone_amulet [black_amulet] @@ -104,7 +98,6 @@ recol2d=4228 2dzoom=370 2dyan=100 2dxan=304 -tradeable=yes dummyitem=inv_only [obj_1687] @@ -158,7 +151,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=7g -tradeable=yes [sapphire_amulet] cost=900 @@ -182,7 +174,6 @@ manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=7g category=category_621 -tradeable=yes [emerald_amulet] cost=1275 @@ -205,7 +196,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=7g -tradeable=yes [ruby_amulet] cost=2025 @@ -228,7 +218,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=7g -tradeable=yes [diamond_amulet] cost=3525 @@ -249,7 +238,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=7g -tradeable=yes [dragonstone_amulet] cost=17625 @@ -273,4 +261,3 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=7g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/jewellery/cut_gems.obj b/data/src/scripts/skill_crafting/configs/jewellery/cut_gems.obj index 2ffeab2d17..b0afd609ff 100644 --- a/data/src/scripts/skill_crafting/configs/jewellery/cut_gems.obj +++ b/data/src/scripts/skill_crafting/configs/jewellery/cut_gems.obj @@ -18,7 +18,6 @@ recol3d=24311 manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes [ruby] cost=1000 @@ -36,7 +35,6 @@ recol1d=16417 manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes [emerald] cost=500 @@ -60,7 +58,6 @@ recol4d=12266 manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes [sapphire] cost=250 @@ -84,7 +81,6 @@ recol4d=10655 manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes respawnrate=1000 [opal] @@ -110,7 +106,6 @@ members=yes manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes [jade] cost=150 @@ -135,7 +130,6 @@ members=yes manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes [red_topaz] cost=200 @@ -160,7 +154,6 @@ members=yes manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes [dragonstone] cost=10000 @@ -185,7 +178,6 @@ members=yes manwear=model_516_obj_wear,0 womanwear=model_516_obj_wear,6 weight=2g -tradeable=yes [crushed_gemstone] name=Crushed gemstone @@ -200,4 +192,3 @@ recol1d=32767 2dzoom=1210 2dyan=1892 2dxan=264 -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/jewellery/jewellery.struct b/data/src/scripts/skill_crafting/configs/jewellery/jewellery.struct index e6593864db..1db9609ad2 100644 --- a/data/src/scripts/skill_crafting/configs/jewellery/jewellery.struct +++ b/data/src/scripts/skill_crafting/configs/jewellery/jewellery.struct @@ -123,6 +123,18 @@ param=levelrequired,17 param=productexp,500 param=name,Unholy Symbol of Zamorak +[perfect_ring] +param=product,perfect_ring +param=gem,ruby +param=levelrequired,34 +param=productexp,700 + +[perfect_necklace] +param=product,perfect_necklace +param=gem,ruby +param=levelrequired,40 +param=productexp,750 + diff --git a/data/src/scripts/skill_crafting/configs/jewellery/moulds.obj b/data/src/scripts/skill_crafting/configs/jewellery/moulds.obj index e32a19902e..bbb81dc759 100644 --- a/data/src/scripts/skill_crafting/configs/jewellery/moulds.obj +++ b/data/src/scripts/skill_crafting/configs/jewellery/moulds.obj @@ -8,7 +8,6 @@ weight=1lb 2dzoom=630 2dyan=92 2dxan=308 -tradeable=yes respawnrate=200 [unholy_mould] @@ -22,6 +21,7 @@ model=model_2673_obj 2dxan=320 weight=1lb members=yes +tradeable=no [amulet_mould] name=Amulet mould @@ -34,7 +34,6 @@ model=model_2368_obj 2dyan=96 2dxan=340 weight=1lb -tradeable=yes respawnrate=200 [necklace_mould] @@ -47,7 +46,6 @@ weight=1lb 2dzoom=640 2dyan=84 2dxan=316 -tradeable=yes respawnrate=200 [holy_mould] @@ -60,5 +58,4 @@ model=model_2448_obj 2dyan=96 2dxan=320 weight=1lb -tradeable=yes respawnrate=200 \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/jewellery/necklaces.obj b/data/src/scripts/skill_crafting/configs/jewellery/necklaces.obj index 966397b878..001194880b 100644 --- a/data/src/scripts/skill_crafting/configs/jewellery/necklaces.obj +++ b/data/src/scripts/skill_crafting/configs/jewellery/necklaces.obj @@ -15,7 +15,6 @@ wearpos=front manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=7g -tradeable=yes param=crafting_jewelry_struct,gold_necklace [sapphire_necklace] @@ -35,7 +34,6 @@ wearpos=front manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=10g -tradeable=yes respawnrate=500 [emerald_necklace] @@ -55,7 +53,6 @@ wearpos=front manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=10g -tradeable=yes [ruby_necklace] cost=2175 @@ -74,7 +71,6 @@ wearpos=front manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=10g -tradeable=yes [diamond_necklace] cost=3675 @@ -93,7 +89,6 @@ wearpos=front manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=10g -tradeable=yes [dragonstone_necklace] cost=18375 @@ -113,7 +108,6 @@ wearpos=front manwear=model_281_obj_wear,0 womanwear=model_445_obj_wear,0 weight=10g -tradeable=yes [black_necklace] model=model_2506_obj @@ -126,7 +120,6 @@ recol2d=4228 2dzoom=620 2dyan=68 2dxan=424 -tradeable=yes dummyitem=inv_only [obj_1668] diff --git a/data/src/scripts/skill_crafting/configs/jewellery/rings.obj b/data/src/scripts/skill_crafting/configs/jewellery/rings.obj index 55e920bd60..107cf83012 100644 --- a/data/src/scripts/skill_crafting/configs/jewellery/rings.obj +++ b/data/src/scripts/skill_crafting/configs/jewellery/rings.obj @@ -15,7 +15,6 @@ iop2=Wear wearpos=ring weight=4g category=category_656 -tradeable=yes respawnrate=500 param=crafting_jewelry_struct,gold_ring @@ -36,7 +35,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [emerald_ring] name=Emerald ring @@ -55,7 +53,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [ruby_ring] name=Ruby ring @@ -74,7 +71,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes respawnrate=500 [diamond_ring] @@ -92,7 +88,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [dragonstone_ring] name=Dragonstone ring @@ -112,7 +107,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [black_ring] model=model_2677_obj @@ -126,7 +120,6 @@ recol2d=4228 2dyan=180 2dzan=2024 2dxan=268 -tradeable=yes dummyitem=inv_only [obj_1649] diff --git a/data/src/scripts/skill_crafting/configs/jewellery/silver.obj b/data/src/scripts/skill_crafting/configs/jewellery/silver.obj index 1ec51a03c4..e6a263704c 100644 --- a/data/src/scripts/skill_crafting/configs/jewellery/silver.obj +++ b/data/src/scripts/skill_crafting/configs/jewellery/silver.obj @@ -8,7 +8,6 @@ model=model_2480_obj 2dyan=92 2dxan=352 weight=4g -tradeable=yes param=crafting_jewelry_struct,unstrung_symbol [unstrung_emblem] @@ -25,5 +24,4 @@ recol1d=24311 2dxan=336 weight=4g members=yes -tradeable=yes param=crafting_jewelry_struct,unstrung_emblem \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/leather/hides.obj b/data/src/scripts/skill_crafting/configs/leather/hides.obj index d1af7604e3..9a2829f06e 100644 --- a/data/src/scripts/skill_crafting/configs/leather/hides.obj +++ b/data/src/scripts/skill_crafting/configs/leather/hides.obj @@ -10,7 +10,6 @@ recol1d=8416 2dyan=116 2dxan=440 weight=5lb -tradeable=yes [hardleather] name=Hard leather @@ -24,7 +23,6 @@ recol1d=5250 2dyan=116 2dxan=440 weight=7lb -tradeable=yes //green @@ -41,7 +39,6 @@ recol1d=256 2dxan=440 weight=7lb members=yes -tradeable=yes //blue [dragon_leather_blue] @@ -57,7 +54,6 @@ recol1d=11 2dxan=440 weight=7lb members=yes -tradeable=yes //red [dragon_leather_red] @@ -73,7 +69,6 @@ recol1d=8192 2dxan=440 weight=7lb members=yes -tradeable=yes //black [dragon_leather_black] @@ -89,4 +84,3 @@ recol1d=3171 2dxan=440 weight=7lb members=yes -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/leather/leather_gear.obj b/data/src/scripts/skill_crafting/configs/leather/leather_gear.obj index 63aa8b6131..6c81eb36ef 100644 --- a/data/src/scripts/skill_crafting/configs/leather/leather_gear.obj +++ b/data/src/scripts/skill_crafting/configs/leather/leather_gear.obj @@ -14,7 +14,6 @@ category=armour_hands 2dyan=828 2dxan=420 weight=8oz -tradeable=yes param=slashdefence,1 param=crushdefence,2 @@ -33,7 +32,6 @@ wearpos=feet manwear=model_185_obj_wear,0 womanwear=model_361_obj_wear,0 weight=12oz -tradeable=yes param=slashdefence,1 param=crushdefence,1 @@ -52,7 +50,6 @@ wearpos=hands manwear=model_177_obj_wear,0 womanwear=model_354_obj_wear,0 weight=8oz -tradeable=yes param=rangeattack,4 param=stabdefence,2 param=slashdefence,2 @@ -78,7 +75,6 @@ manwear=model_178_obj_wear,0 womanwear=model_355_obj_wear,0 category=category_16 weight=10oz -tradeable=yes param=magicattack,-10 param=rangeattack,8 param=stabdefence,3 @@ -102,7 +98,6 @@ manwear=model_262_obj_wear,0 womanwear=model_425_obj_wear,0 category=armour_legs weight=6lb -tradeable=yes param=rangeattack,4 param=stabdefence,2 param=slashdefence,2 @@ -124,7 +119,6 @@ manwear=model_277_obj_wear,0 womanwear=model_441_obj_wear,0 category=armour_legs weight=10lb -tradeable=yes param=crafting_studded_struct,studded_chaps param=magicattack,-5 param=rangeattack,6 @@ -150,7 +144,6 @@ manwear=model_258_obj_wear,0 womanwear=model_423_obj_wear,0 category=armour_legs weight=12lb -tradeable=yes param=magicattack,-10 param=rangeattack,8 param=stabdefence,22 @@ -173,7 +166,6 @@ manwear=model_311_obj_wear,0 womanwear=model_475_obj_wear,0 category=armour_body weight=6lb -tradeable=yes param=magicattack,-2 param=rangeattack,2 param=stabdefence,8 @@ -195,7 +187,6 @@ manwear=model_296_obj_wear,0 womanwear=model_296_obj_wear,0 category=armour_body weight=8lb -tradeable=yes param=magicattack,-4 param=rangeattack,8 param=stabdefence,12 @@ -217,7 +208,6 @@ manwear=model_303_obj_wear,0 womanwear=model_466_obj_wear,0 category=armour_body weight=12lb -tradeable=yes param=crafting_studded_struct,studded_body param=magicattack,-4 param=rangeattack,8 @@ -244,7 +234,6 @@ manwear=model_314_obj_wear,0 womanwear=model_477_obj_wear,0 category=armour_body weight=15lb -tradeable=yes param=magicattack,-15 param=rangeattack,15 param=stabdefence,40 @@ -276,7 +265,6 @@ manhead2=model_63_idk_head womanhead2=model_120_idk_head category=armour_helmet weight=2lb -tradeable=yes param=rangeattack,1 param=stabdefence,2 param=slashdefence,3 @@ -305,7 +293,6 @@ manhead2=model_63_idk_head womanhead2=model_120_idk_head category=armour_helmet weight=2lb -tradeable=yes param=magicattack,-1 param=rangeattack,2 param=stabdefence,4 @@ -338,7 +325,6 @@ womanwear=model_355_obj_wear,0 category=category_16 weight=10oz members=yes -tradeable=yes param=magicattack,-10 param=rangeattack,9 param=stabdefence,4 @@ -369,7 +355,6 @@ womanwear=model_355_obj_wear,0 category=category_16 weight=10oz members=yes -tradeable=yes param=magicattack,-10 param=rangeattack,10 param=stabdefence,5 @@ -400,7 +385,6 @@ womanwear=model_355_obj_wear,0 category=category_16 weight=10oz members=yes -tradeable=yes param=magicattack,-10 param=rangeattack,11 param=stabdefence,6 @@ -429,7 +413,6 @@ womanwear=model_423_obj_wear,0 category=armour_legs weight=12lb members=yes -tradeable=yes param=magicattack,-10 param=rangeattack,11 param=stabdefence,25 @@ -459,7 +442,6 @@ womanwear=model_423_obj_wear,0 category=armour_legs weight=12lb members=yes -tradeable=yes param=magicattack,-10 param=rangeattack,14 param=stabdefence,28 @@ -489,7 +471,6 @@ womanwear=model_423_obj_wear,0 category=armour_legs weight=12lb members=yes -tradeable=yes param=magicattack,-10 param=rangeattack,17 param=stabdefence,31 @@ -520,7 +501,6 @@ womanwear=model_477_obj_wear,0 category=armour_body weight=15lb members=yes -tradeable=yes param=magicattack,-15 param=rangeattack,20 param=stabdefence,45 @@ -551,7 +531,6 @@ womanwear=model_477_obj_wear,0 category=armour_body weight=15lb members=yes -tradeable=yes param=magicattack,-15 param=rangeattack,25 param=stabdefence,50 @@ -582,7 +561,6 @@ womanwear=model_477_obj_wear,0 category=armour_body weight=15lb members=yes -tradeable=yes param=magicattack,-15 param=rangeattack,30 param=stabdefence,55 diff --git a/data/src/scripts/skill_crafting/configs/pottery/pottery.obj b/data/src/scripts/skill_crafting/configs/pottery/pottery.obj index b777bf038c..368c542a51 100644 --- a/data/src/scripts/skill_crafting/configs/pottery/pottery.obj +++ b/data/src/scripts/skill_crafting/configs/pottery/pottery.obj @@ -9,7 +9,6 @@ model=model_2610_obj 2dxan=220 weight=2lb cost=2 -tradeable=yes param=crafting_pottery_struct,soft_clay [unfired_pot] @@ -25,7 +24,6 @@ recol1d=11488 2dxan=112 cost=1 weight=24oz -tradeable=yes param=crafting_pottery_struct,unfired_pot [unfired_piedish] @@ -44,7 +42,6 @@ recol3d=11488 2dyan=104 2dxan=192 weight=24oz -tradeable=yes param=crafting_pottery_struct,unfired_piedish [unfired_bowl] @@ -60,5 +57,4 @@ recol2d=11488 2dyan=1856 2dxan=204 weight=24oz -tradeable=yes param=crafting_pottery_struct,unfired_bowl \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/spinning/spinning.obj b/data/src/scripts/skill_crafting/configs/spinning/spinning.obj index 6966dc8553..272d5f5e5d 100644 --- a/data/src/scripts/skill_crafting/configs/spinning/spinning.obj +++ b/data/src/scripts/skill_crafting/configs/spinning/spinning.obj @@ -10,7 +10,6 @@ model=model_2690_obj 2dzan=1840 2dxan=428 weight=1lb -tradeable=yes param=crafting_spinning_struct,flax [wool] @@ -22,5 +21,4 @@ model=model_2779_obj 2dyan=160 2dxan=332 weight=3g -tradeable=yes param=crafting_spinning_struct,wool \ No newline at end of file diff --git a/data/src/scripts/skill_crafting/configs/studded/studded.obj b/data/src/scripts/skill_crafting/configs/studded/studded.obj index 00f54980b8..4a2d790cef 100644 --- a/data/src/scripts/skill_crafting/configs/studded/studded.obj +++ b/data/src/scripts/skill_crafting/configs/studded/studded.obj @@ -9,4 +9,3 @@ model=model_2598_obj cost=150 weight=3lb members=yes -tradeable=yes diff --git a/data/src/scripts/skill_crafting/scripts/jewellery/jewellery.rs2 b/data/src/scripts/skill_crafting/scripts/jewellery/jewellery.rs2 index 96e924eb1d..ab83e56756 100644 --- a/data/src/scripts/skill_crafting/scripts/jewellery/jewellery.rs2 +++ b/data/src/scripts/skill_crafting/scripts/jewellery/jewellery.rs2 @@ -225,21 +225,40 @@ p_delay(2); [proc,crafting_gold](namedobj $product, namedobj $gem, int $productexp, int $count) -inv_del(inv, gold_bar, 1); +def_obj $bar = gold_bar; +if (inv_total(inv, perfect_gold_bar) >= 1) { + // Tested on OSRS: if normal gold bar and perfect gold bar are both in inventory, the perfect gold bar gets used first, + // even if the normal gold bar was explicitly used on the furnace. If you select normal ruby ring with normal gold bar + // and you have a perfect bar in your inv, a perfect ring will be made instead (and only one, even if you have more + // gold bars and selected make x). + $bar = perfect_gold_bar; + if ($product = ruby_necklace) { + $product = perfect_necklace; + } + else if ($product = ruby_ring) { + $product = perfect_ring; + } +} +inv_del(inv, $bar, 1); + if ($gem ! null) { inv_del(inv, $gem, 1); } inv_add(inv, $product, 1); + stat_advance(crafting, $productexp); -mes("You make <~add_article(lowercase(oc_name($product)))>."); +if ($bar = gold_bar) { + // No message for perfect gold items https://youtu.be/e8btuenT4nE?t=729 + mes("You make <~add_article(lowercase(oc_name($product)))>."); +} $count = calc($count - 1); if ($count < 1) { return; } // check if player has enough gold bars or gems -if (inv_total(inv, gold_bar) < 1) { +if (inv_total(inv, $bar) < 1) { ~mesbox("You don't have enough gold bars to make any more."); return; } diff --git a/data/src/scripts/skill_firemaking/configs/firemaking.obj b/data/src/scripts/skill_firemaking/configs/firemaking.obj index e21d02fdef..53cf8651d6 100644 --- a/data/src/scripts/skill_firemaking/configs/firemaking.obj +++ b/data/src/scripts/skill_firemaking/configs/firemaking.obj @@ -12,7 +12,6 @@ womanwear=model_488_obj_wear,0 2dyan=1968 2dxan=196 weight=35g -tradeable=yes [ashes] name=Ashes @@ -26,7 +25,6 @@ recol1d=28539 2dyan=1892 2dxan=264 weight=2oz -tradeable=yes [lit_torch] cost=4 @@ -39,7 +37,6 @@ model=model_2671_obj 2dxan=124 weight=500g members=yes -tradeable=yes category=light_source_lit [unlit_torch] @@ -52,7 +49,6 @@ model=model_2554_obj 2dxan=1632 weight=500g members=yes -tradeable=yes category=light_source_unlit param=product,lit_torch @@ -80,8 +76,10 @@ param=proj_launch,unlit_arrow_launch param=proj_travel,unlit_arrow_travel param=next_obj_stage,lit_arrows param=unlit_arrow,^true +tradeable=no [obj_599] +tradeable=no [logs] name=Logs @@ -96,7 +94,6 @@ weight=2kg 2dxan=280 op4=Light category=category_22 -tradeable=yes param=levelrequire,1 param=productexp,400 @@ -116,7 +113,6 @@ recol1d=15651 op4=Light weight=2kg category=category_22 -tradeable=yes param=levelrequire,75 param=productexp,3038 @@ -135,7 +131,6 @@ recol1d=15717 op4=Light weight=2kg category=category_22 -tradeable=yes param=levelrequire,60 param=productexp,2025 @@ -154,7 +149,6 @@ recol1d=14560 op4=Light weight=2kg category=category_22 -tradeable=yes param=levelrequire,45 param=productexp,1350 @@ -173,7 +167,6 @@ recol1d=16643 op4=Light weight=2kg category=category_22 -tradeable=yes param=levelrequire,30 param=productexp,900 @@ -192,6 +185,5 @@ recol1d=14659 op4=Light weight=2kg category=category_22 -tradeable=yes param=levelrequire,15 param=productexp,600 \ No newline at end of file diff --git a/data/src/scripts/skill_fishing/configs/fishing.obj b/data/src/scripts/skill_fishing/configs/fishing.obj index 4ea6746961..036d4fcf20 100644 --- a/data/src/scripts/skill_fishing/configs/fishing.obj +++ b/data/src/scripts/skill_fishing/configs/fishing.obj @@ -9,7 +9,6 @@ cost=20 manwear=model_531_obj_wear,0 womanwear=model_531_obj_wear,6 weight=9oz -tradeable=yes param=fish_equipment_struct,fish_equipment_lobster_pot [net] @@ -25,7 +24,6 @@ cost=5 manwear=model_551_obj_wear,0 womanwear=model_551_obj_wear,6 weight=10lb -tradeable=yes param=fish_equipment_struct,fish_equipment_net [net_big] @@ -42,7 +40,6 @@ members=yes manwear=model_489_obj_wear,0 womanwear=model_489_obj_wear,6 weight=18lb -tradeable=yes param=fish_equipment_struct,fish_equipment_big_net [fishing_rod] @@ -58,7 +55,6 @@ cost=5 manwear=model_562_obj_wear,0 womanwear=model_562_obj_wear,6 weight=3lb -tradeable=yes param=fish_equipment_struct,fish_equipment_fishing_rod [fly_fishing_rod] @@ -74,7 +70,6 @@ cost=5 manwear=model_562_obj_wear,0 womanwear=model_562_obj_wear,6 weight=3lb -tradeable=yes param=fish_equipment_struct,fish_equipment_fly_fishing_rod [harpoon] @@ -90,7 +85,6 @@ cost=5 manwear=model_503_obj_wear,0 womanwear=model_503_obj_wear,6 weight=3lb -tradeable=yes param=fish_equipment_struct,fish_equipment_harpoon [fishing_bait] @@ -105,7 +99,6 @@ model=model_2436_obj stackable=yes cost=3 weight=2g -tradeable=yes [feather] name=Feather @@ -120,7 +113,6 @@ stackable=yes cost=2 weight=2g category=category_532 -tradeable=yes [shrimps] name=Shrimps @@ -133,7 +125,6 @@ cost=5 iop1=Eat weight=100g category=category_58 -tradeable=yes [raw_shrimps] name=Raw shrimps @@ -149,7 +140,6 @@ recol2d=30319 cost=5 weight=120g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_shrimps [anchovies] @@ -167,7 +157,6 @@ cost=15 iop1=Eat weight=100g category=category_58 -tradeable=yes param=pizza_topping_struct,anchovy_topping [raw_anchovies] @@ -184,7 +173,6 @@ recol2d=17971 cost=15 weight=120g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_anchovies [burnt_shrimp_anchovies] @@ -201,7 +189,6 @@ recol2d=7399 cost=1 weight=80g category=category_116 -tradeable=yes [sardine] name=Sardine @@ -221,7 +208,6 @@ cost=10 iop1=Eat weight=120g category=category_58 -tradeable=yes [raw_sardine] name=Raw sardine @@ -240,7 +226,6 @@ recol2d=18417 cost=10 weight=140g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_sardine [salmon] @@ -259,7 +244,6 @@ cost=50 iop1=Eat weight=500g category=category_58 -tradeable=yes [raw_salmon] name=Raw salmon @@ -276,7 +260,6 @@ recol2d=29331 cost=50 weight=550g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_salmon [trout] @@ -295,7 +278,6 @@ cost=20 iop1=Eat weight=400g category=category_58 -tradeable=yes [raw_trout] name=Raw trout @@ -312,7 +294,6 @@ recol2d=32767 cost=20 weight=450g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_trout [giant_carp] @@ -332,6 +313,7 @@ iop1=Eat weight=500g category=category_58 members=yes +tradeable=no [raw_giant_carp] name=Raw giant carp @@ -349,6 +331,7 @@ cost=50 weight=550g category=category_57 members=yes +tradeable=no [cod] name=Cod @@ -367,7 +350,6 @@ iop1=Eat weight=400g category=category_58 members=yes -tradeable=yes [raw_cod] name=Raw cod @@ -385,7 +367,6 @@ cost=25 weight=450g category=category_57 members=yes -tradeable=yes [burnt_salmon_trout_carp_cod_pike] name=Burnt fish @@ -402,7 +383,6 @@ recol2d=10570 cost=1 weight=350g category=category_116 -tradeable=yes [raw_herring] name=Raw herring @@ -420,7 +400,6 @@ recol2d=32767 cost=15 weight=550g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_herring [herring] @@ -440,7 +419,6 @@ cost=15 iop1=Eat weight=500g category=category_58 -tradeable=yes [raw_pike] name=Raw pike @@ -457,7 +435,6 @@ recol2d=22517 cost=25 weight=550g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_pike [pike] @@ -476,7 +453,6 @@ cost=25 weight=500g category=category_58 iop1=Eat -tradeable=yes [raw_mackerel] name=Raw mackerel @@ -495,7 +471,6 @@ cost=17 weight=350g category=category_57 members=yes -tradeable=yes [mackerel] name=Mackerel @@ -515,7 +490,6 @@ iop1=Eat weight=300g category=category_58 members=yes -tradeable=yes [burnt_mackerel] name=Burnt fish @@ -533,7 +507,6 @@ recol2d=10570 cost=1 weight=300g category=category_116 -tradeable=yes [raw_tuna] name=Raw tuna @@ -550,7 +523,6 @@ recol2d=32767 cost=100 weight=450g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_tuna [tuna] @@ -569,7 +541,6 @@ cost=100 iop1=Eat weight=400g category=category_58 -tradeable=yes [raw_bass] name=Raw bass @@ -587,7 +558,6 @@ cost=120 weight=400g category=category_57 members=yes -tradeable=yes [bass] name=Bass @@ -606,7 +576,6 @@ iop1=Eat weight=350g category=category_58 members=yes -tradeable=yes [burnt_tuna_bass] name=Burnt fish @@ -623,7 +592,6 @@ recol2d=10570 cost=1 weight=300g category=category_116 -tradeable=yes [burnt_sardine] name=Burnt fish @@ -642,7 +610,6 @@ model=model_2357_obj 2dxan=320 weight=300g category=category_116 -tradeable=yes [raw_swordfish] name=Raw swordfish @@ -659,7 +626,6 @@ recol2d=29437 cost=200 weight=500g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_swordfish [swordfish] @@ -678,7 +644,6 @@ cost=200 iop1=Eat weight=450g category=category_58 -tradeable=yes [burnt_swordfish] name=Burnt swordfish @@ -695,7 +660,6 @@ recol2d=10570 cost=1 weight=400g category=category_116 -tradeable=yes [raw_lobster] name=Raw lobster @@ -711,7 +675,6 @@ recol1d=15554 cost=150 weight=400g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_lobster [lobster] @@ -727,7 +690,6 @@ cost=150 iop1=Eat weight=350g category=category_58 -tradeable=yes [burnt_lobster] name=Burnt lobster @@ -743,7 +705,6 @@ recol1d=7399 cost=1 weight=300g category=category_116 -tradeable=yes [raw_shark] name=Raw shark @@ -760,7 +721,6 @@ cost=300 weight=700g category=category_57 members=yes -tradeable=yes param=fishing_struct,fishing_struct_shark [shark] @@ -781,7 +741,6 @@ iop1=Eat weight=650g category=category_58 members=yes -tradeable=yes [burnt_shark] name=Burnt shark @@ -800,7 +759,6 @@ cost=1 weight=600g category=category_116 members=yes -tradeable=yes [raw_manta_ray] name=Raw manta ray @@ -818,7 +776,6 @@ cost=500 weight=450g category=category_57 members=yes -tradeable=yes param=fishing_struct,fishing_struct_manta_ray [manta_ray] @@ -838,7 +795,6 @@ iop1=Eat weight=400g category=category_58 members=yes -tradeable=yes [burnt_manta_ray] name=Burnt manta ray @@ -856,7 +812,6 @@ cost=1 weight=350g category=category_116 members=yes -tradeable=yes [raw_sea_turtle] name=Raw sea turtle @@ -870,7 +825,6 @@ members=yes 2dxan=236 weight=400g category=category_57 -tradeable=yes param=fishing_struct,fishing_struct_sea_turtle [sea_turtle] @@ -890,7 +844,6 @@ iop1=Eat weight=350g category=category_58 members=yes -tradeable=yes [burnt_sea_turtle] name=Burnt sea turtle @@ -908,7 +861,6 @@ members=yes 2dxan=236 weight=320g category=category_116 -tradeable=yes [seaweed] name=Seaweed @@ -922,7 +874,6 @@ model=model_2370_obj cost=2 weight=200g members=yes -tradeable=yes category=cooking_generic [edible_seaweed] @@ -939,7 +890,6 @@ iop1=Eat weight=250g category=category_59 members=yes -tradeable=yes [casket] name=Casket @@ -954,7 +904,6 @@ cost=50 iop1=Open weight=5kg members=yes -tradeable=yes [oyster] name=Oyster @@ -969,7 +918,6 @@ cost=200 iop1=Open weight=100g members=yes -tradeable=yes [empty_oyster] name=Empty oyster @@ -983,7 +931,6 @@ model=model_2593_obj cost=5 weight=80g members=yes -tradeable=yes [oyster_perl] name=Oyster pearl @@ -997,7 +944,6 @@ model=model_2721_obj cost=112 weight=2g members=yes -tradeable=yes [oyster_perls] name=Oyster pearls @@ -1011,4 +957,3 @@ model=model_2377_obj cost=1400 weight=4g members=yes -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_fletching/configs/arrows/arrows.obj b/data/src/scripts/skill_fletching/configs/arrows/arrows.obj index 562a9e5ace..e7395a9a5f 100644 --- a/data/src/scripts/skill_fletching/configs/arrows/arrows.obj +++ b/data/src/scripts/skill_fletching/configs/arrows/arrows.obj @@ -16,7 +16,6 @@ members=yes stackable=yes cost=1 weight=4g -tradeable=yes [iron_arrowheads] category=category_968 @@ -36,7 +35,6 @@ members=yes stackable=yes cost=2 weight=4g -tradeable=yes [steel_arrowheads] category=category_968 @@ -52,7 +50,6 @@ members=yes stackable=yes cost=6 weight=4g -tradeable=yes [mithril_arrowheads] category=category_968 @@ -72,7 +69,6 @@ members=yes stackable=yes cost=16 weight=3g -tradeable=yes [adamant_arrowheads] category=category_968 @@ -92,7 +88,6 @@ members=yes stackable=yes cost=40 weight=5g -tradeable=yes [rune_arrowheads] category=category_968 @@ -112,7 +107,6 @@ members=yes stackable=yes cost=200 weight=4g -tradeable=yes [arrow_shaft] name=Arrow shaft @@ -127,7 +121,6 @@ model=model_2616_obj 2dyan=100 2dxan=216 weight=10g -tradeable=yes [headless_arrow] name=Headless arrow @@ -142,7 +135,6 @@ model=model_2764_obj 2dyan=100 2dxan=216 weight=12g -tradeable=yes [obj_2864] name=Ogre arrow shaft @@ -159,4 +151,3 @@ recol1d=11556 2dyan=100 2dxan=216 weight=10g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_fletching/configs/bolts/bolts.obj b/data/src/scripts/skill_fletching/configs/bolts/bolts.obj index 93c2c18e60..ad6a1385b3 100644 --- a/data/src/scripts/skill_fletching/configs/bolts/bolts.obj +++ b/data/src/scripts/skill_fletching/configs/bolts/bolts.obj @@ -14,7 +14,6 @@ stackable=yes cost=30 weight=4g category=category_530 -tradeable=yes [obj_46] name=Pearl bolttips @@ -30,7 +29,6 @@ stackable=yes cost=56 weight=4g category=category_530 -tradeable=yes [obj_47] name=Barb bolttips @@ -46,4 +44,3 @@ cost=95 2dxan=492 weight=4g category=category_530 -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_fletching/configs/darts/darts.obj b/data/src/scripts/skill_fletching/configs/darts/darts.obj index faede79597..a9056adcbd 100644 --- a/data/src/scripts/skill_fletching/configs/darts/darts.obj +++ b/data/src/scripts/skill_fletching/configs/darts/darts.obj @@ -13,7 +13,6 @@ stackable=yes 2dyan=308 2dxan=344 weight=8g -tradeable=yes [iron_dart_tip] category=category_969 @@ -30,7 +29,6 @@ stackable=yes 2dyan=308 2dxan=344 weight=8g -tradeable=yes [steel_dart_tip] category=category_969 @@ -47,7 +45,6 @@ stackable=yes 2dyan=308 2dxan=344 weight=8g -tradeable=yes [mithril_dart_tip] category=category_969 @@ -64,7 +61,6 @@ stackable=yes 2dyan=308 2dxan=344 weight=6g -tradeable=yes [adamant_dart_tip] category=category_969 @@ -81,7 +77,6 @@ stackable=yes 2dyan=308 2dxan=344 weight=10g -tradeable=yes [rune_dart_tip] category=category_969 @@ -98,4 +93,3 @@ stackable=yes 2dyan=308 2dxan=344 weight=8g -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_fletching/configs/ogre/ogre_arrows.obj b/data/src/scripts/skill_fletching/configs/ogre/ogre_arrows.obj index 5dda8d052a..477e02bd60 100644 --- a/data/src/scripts/skill_fletching/configs/ogre/ogre_arrows.obj +++ b/data/src/scripts/skill_fletching/configs/ogre/ogre_arrows.obj @@ -17,7 +17,6 @@ weight=4g 2dzoom=780 2dyan=176 2dxan=440 -tradeable=yes [achey_logs] name=Achey tree logs @@ -35,8 +34,6 @@ category=category_22 weight=3lb members=yes op4=Light -tradeable=yes -tradeable=yes [obj_2865] name=Flighted ogre arrow @@ -55,7 +52,6 @@ recol2d=32767 2dyan=100 2dxan=216 weight=12g -tradeable=yes [ogre_arrow] name=Ogre arrow @@ -91,7 +87,6 @@ param=rangebonus,22 param=levelrequire,30 param=proj_launch,ogre_arrow_launch param=proj_travel,ogre_arrow_travel -tradeable=yes [ogre_arrow_5] stackable=yes diff --git a/data/src/scripts/skill_fletching/configs/stringing/bows.obj b/data/src/scripts/skill_fletching/configs/stringing/bows.obj index ec26e40b8e..a5cd1a8df4 100644 --- a/data/src/scripts/skill_fletching/configs/stringing/bows.obj +++ b/data/src/scripts/skill_fletching/configs/stringing/bows.obj @@ -12,7 +12,6 @@ recol1d=21985 2dyan=1004 2dxan=460 weight=47oz -tradeable=yes category=unstrung_bow [obj_50] @@ -29,7 +28,6 @@ recol1d=21985 2dyan=124 2dxan=508 weight=35oz -tradeable=yes category=unstrung_bow [obj_54] @@ -46,7 +44,6 @@ recol1d=23009 2dyan=124 2dxan=508 weight=35oz -tradeable=yes category=unstrung_bow [obj_56] @@ -63,7 +60,6 @@ recol1d=23009 2dyan=1004 2dxan=460 weight=47oz -tradeable=yes category=unstrung_bow [obj_58] @@ -80,7 +76,6 @@ recol1d=20004 2dyan=1004 2dxan=460 weight=47oz -tradeable=yes category=unstrung_bow [obj_60] cost=100 @@ -96,7 +91,6 @@ recol1d=20004 2dyan=124 2dxan=508 weight=35oz -tradeable=yes category=unstrung_bow [obj_62] @@ -113,7 +107,6 @@ recol1d=21040 2dyan=1004 2dxan=460 weight=47oz -tradeable=yes category=unstrung_bow [obj_64] @@ -130,7 +123,6 @@ recol1d=21040 2dyan=124 2dxan=508 weight=35oz -tradeable=yes category=unstrung_bow [obj_66] @@ -147,7 +139,6 @@ recol1d=23073 2dyan=1004 2dxan=460 weight=47oz -tradeable=yes category=unstrung_bow [obj_68] @@ -164,7 +155,6 @@ recol1d=23073 2dyan=124 2dxan=508 weight=35oz -tradeable=yes category=unstrung_bow [obj_70] @@ -181,7 +171,6 @@ recol1d=1451 2dyan=1004 2dxan=460 weight=47oz -tradeable=yes category=unstrung_bow [obj_72] @@ -198,5 +187,4 @@ recol1d=1451 2dyan=124 2dxan=508 weight=35oz -tradeable=yes category=unstrung_bow \ No newline at end of file diff --git a/data/src/scripts/skill_fletching/scripts/bolts.rs2 b/data/src/scripts/skill_fletching/scripts/bolts.rs2 index 829b8cd004..4f355e5fa9 100644 --- a/data/src/scripts/skill_fletching/scripts/bolts.rs2 +++ b/data/src/scripts/skill_fletching/scripts/bolts.rs2 @@ -59,7 +59,7 @@ if ($data = null) { def_int $level = db_getfield($data, fletching_table:level, 0); if (stat(fletching) < $level) { // osrs - ~doubleobjbox(bolt, $bolt_tips, "You need a Fletching level of to make that kind of bolt."); + ~doubleobjbox(bolt, $bolt_tips, "You need a Fletching level of to make that kind of bolt.", 150); return; } // bolts are made through smithing, they can be upgraded with fletching diff --git a/data/src/scripts/skill_fletching/scripts/cut_logs.rs2 b/data/src/scripts/skill_fletching/scripts/cut_logs.rs2 index 49562d16c3..ff5c9f7a6e 100644 --- a/data/src/scripts/skill_fletching/scripts/cut_logs.rs2 +++ b/data/src/scripts/skill_fletching/scripts/cut_logs.rs2 @@ -60,7 +60,7 @@ if ($product = $obj2) { } if (stat(fletching) < $level) { // osrs has a level 1 fail message for arrow shafts but i doubt 2004 used it - ~doubleobjbox($log, $product, "You need a Fletching level of at least to make <~add_article(lowercase(oc_name($product)))>."); + ~doubleobjbox($log, $product, "You need a Fletching level of at least to make <~add_article(lowercase(oc_name($product)))>.", 150); return; } // make one bow at a time diff --git a/data/src/scripts/skill_fletching/scripts/ogre_arrows.rs2 b/data/src/scripts/skill_fletching/scripts/ogre_arrows.rs2 index 562991ad63..d43651602b 100644 --- a/data/src/scripts/skill_fletching/scripts/ogre_arrows.rs2 +++ b/data/src/scripts/skill_fletching/scripts/ogre_arrows.rs2 @@ -130,7 +130,7 @@ inv_add(inv, ogre_arrow, $arrow_count); // todo tbc exact mechanism if (%chompybird_progress ! ^chompybird_not_started) { - setbit(%chompybird_kills, ^chompybird_varbit_made_arrows); + %chompybird_kills = setbit(%chompybird_kills, ^chompybird_varbit_made_arrows); } stat_advance(fletching, multiply($arrow_count, 10)); diff --git a/data/src/scripts/skill_herblore/configs/brewing/potions.obj b/data/src/scripts/skill_herblore/configs/brewing/potions.obj index 9c1973e5ee..430560ee88 100644 --- a/data/src/scripts/skill_herblore/configs/brewing/potions.obj +++ b/data/src/scripts/skill_herblore/configs/brewing/potions.obj @@ -14,7 +14,6 @@ recol1d=29543 2dxan=84 weight=35g category=category_69 -tradeable=yes param=next_obj_stage,3dose1strength param=decant_potion_enum,potion_1strength param=dose_count,4 @@ -34,7 +33,6 @@ recol1d=29543 2dxan=84 weight=30g category=category_69 -tradeable=yes param=next_obj_stage,2dose1strength param=decant_potion_enum,potion_1strength param=dose_count,3 @@ -54,7 +52,6 @@ recol1d=29543 2dyan=1996 2dxan=84 weight=25g -tradeable=yes param=next_obj_stage,1dose1strength param=decant_potion_enum,potion_1strength param=dose_count,2 @@ -74,7 +71,6 @@ recol1d=29543 2dyan=1996 2dxan=84 weight=20g -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_1strength param=dose_count,1 @@ -95,7 +91,6 @@ recol1d=7037 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dose1attack param=decant_potion_enum,potion_1attack param=dose_count,3 @@ -116,7 +111,6 @@ recol1d=7037 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dose1attack param=decant_potion_enum,potion_1attack param=dose_count,2 @@ -137,7 +131,6 @@ recol1d=7037 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_1attack param=dose_count,1 @@ -158,7 +151,6 @@ recol1d=28903 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dose1restore param=decant_potion_enum,potion_1restore param=dose_count,3 @@ -179,7 +171,6 @@ recol1d=28903 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dose1restore param=decant_potion_enum,potion_1restore param=dose_count,2 @@ -200,7 +191,6 @@ recol1d=28903 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_1restore param=dose_count,1 @@ -221,7 +211,6 @@ recol1d=7078 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dose1defense param=decant_potion_enum,potion_1defense param=dose_count,3 @@ -242,7 +231,6 @@ recol1d=7078 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dose1defense param=decant_potion_enum,potion_1defense param=dose_count,2 @@ -263,7 +251,6 @@ recol1d=7078 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_1defense param=dose_count,1 @@ -284,7 +271,6 @@ recol1d=7091 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2doseprayerrestore param=decant_potion_enum,potion_prayerrestore param=dose_count,3 @@ -305,7 +291,6 @@ recol1d=7091 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1doseprayerrestore param=decant_potion_enum,potion_prayerrestore param=dose_count,2 @@ -326,7 +311,6 @@ recol1d=7091 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_prayerrestore param=dose_count,1 @@ -347,7 +331,6 @@ recol1d=6365 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dose2attack param=decant_potion_enum,potion_2attack param=dose_count,3 @@ -368,7 +351,6 @@ recol1d=6365 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dose2attack param=decant_potion_enum,potion_2attack param=dose_count,2 @@ -389,7 +371,6 @@ recol1d=6365 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_2attack param=dose_count,1 @@ -410,7 +391,6 @@ recol1d=6342 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dosefisherspotion param=decant_potion_enum,potion_fisherspotion param=dose_count,3 @@ -431,7 +411,6 @@ recol1d=6342 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dosefisherspotion param=decant_potion_enum,potion_fisherspotion param=dose_count,2 @@ -452,7 +431,6 @@ recol1d=6342 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_fisherspotion param=dose_count,1 @@ -473,7 +451,6 @@ recol1d=30653 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dose2strength param=decant_potion_enum,potion_2strength param=dose_count,3 @@ -494,7 +471,6 @@ recol1d=30653 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dose2strength param=decant_potion_enum,potion_2strength param=dose_count,2 @@ -515,7 +491,6 @@ recol1d=30653 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_2strength param=dose_count,1 @@ -536,7 +511,6 @@ recol1d=29351 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dose2defense param=decant_potion_enum,potion_2defense param=dose_count,3 @@ -557,7 +531,6 @@ recol1d=29351 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dose2defense param=decant_potion_enum,potion_2defense param=dose_count,2 @@ -578,7 +551,6 @@ recol1d=29351 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_2defense param=dose_count,1 @@ -599,7 +571,6 @@ recol1d=6845 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2doserangerspotion param=decant_potion_enum,potion_rangerspotion param=dose_count,3 @@ -620,7 +591,6 @@ recol1d=6845 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1doserangerspotion param=decant_potion_enum,potion_rangerspotion param=dose_count,2 @@ -641,7 +611,6 @@ recol1d=6845 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_rangerspotion param=dose_count,1 @@ -662,7 +631,7 @@ recol1d=13251 weight=30g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,2doseantipoison param=decant_potion_enum,potion_antipoison param=dose_count,3 @@ -683,7 +652,7 @@ recol1d=13251 weight=25g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,1doseantipoison param=decant_potion_enum,potion_antipoison param=dose_count,2 @@ -704,7 +673,7 @@ recol1d=13251 weight=20g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_antipoison param=dose_count,1 @@ -725,7 +694,7 @@ recol1d=30828 weight=30g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,2dose2antipoison param=decant_potion_enum,potion_2antipoison param=dose_count,3 @@ -746,7 +715,7 @@ recol1d=30828 weight=25g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,1dose2antipoison param=decant_potion_enum,potion_2antipoison param=dose_count,2 @@ -767,7 +736,7 @@ recol1d=30828 weight=20g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_2antipoison param=dose_count,1 @@ -787,7 +756,6 @@ recol1d=2463 weight=25g category=category_69 members=yes -tradeable=yes // jagex name [3dosepotionofzamorak] @@ -805,7 +773,6 @@ recol1d=29217 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dosepotionofzamorak param=decant_potion_enum,potion_potionofzamorak param=dose_count,3 @@ -826,7 +793,6 @@ recol1d=29217 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dosepotionofzamorak param=decant_potion_enum,potion_potionofzamorak param=dose_count,2 @@ -847,7 +813,6 @@ recol1d=29217 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_potionofzamorak param=dose_count,1 @@ -868,7 +833,6 @@ recol1d=7037 2dxan=84 weight=35g members=yes -tradeable=yes param=next_obj_stage,3dose1attack param=decant_potion_enum,potion_1attack param=dose_count,4 @@ -889,7 +853,6 @@ recol1d=28903 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dose1restore param=decant_potion_enum,potion_1restore param=dose_count,1 @@ -910,7 +873,6 @@ recol1d=7078 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dose1defense param=decant_potion_enum,potion_1defense param=dose_count,4 @@ -931,7 +893,6 @@ recol1d=7091 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3doseprayerrestore param=decant_potion_enum,potion_prayerrestore param=dose_count,4 @@ -952,7 +913,6 @@ recol1d=6365 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dose2attack param=decant_potion_enum,potion_2attack param=dose_count,4 @@ -973,7 +933,6 @@ recol1d=6342 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dosefisherspotion param=decant_potion_enum,potion_fisherspotion param=dose_count,4 @@ -994,7 +953,6 @@ recol1d=30653 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dose2strength param=decant_potion_enum,potion_2strength param=dose_count,4 @@ -1015,7 +973,6 @@ recol1d=29351 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dose2defense param=decant_potion_enum,potion_2defense param=dose_count,4 @@ -1036,7 +993,6 @@ recol1d=6845 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3doserangerspotion param=decant_potion_enum,potion_rangerspotion param=dose_count,4 @@ -1057,7 +1013,7 @@ recol1d=13251 weight=35g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,3doseantipoison param=decant_potion_enum,potion_antipoison param=dose_count,4 @@ -1078,7 +1034,7 @@ recol1d=30828 weight=35g category=category_69 members=yes -tradeable=yes +param=cures_poison,yes param=next_obj_stage,3dose2antipoison param=decant_potion_enum,potion_2antipoison param=dose_count,4 @@ -1099,7 +1055,6 @@ recol1d=29217 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dosepotionofzamorak param=decant_potion_enum,potion_potionofzamorak param=dose_count,4 @@ -1120,7 +1075,6 @@ recol1d=11282 weight=35g category=category_69 members=yes -tradeable=yes param=next_obj_stage,3dose1antidragon param=decant_potion_enum,potion_1antidragon param=dose_count,4 @@ -1141,7 +1095,6 @@ recol1d=11282 weight=30g category=category_69 members=yes -tradeable=yes param=next_obj_stage,2dose1antidragon param=decant_potion_enum,potion_1antidragon param=dose_count,3 @@ -1162,7 +1115,6 @@ recol1d=11282 weight=25g category=category_69 members=yes -tradeable=yes param=next_obj_stage,1dose1antidragon param=decant_potion_enum,potion_1antidragon param=dose_count,2 @@ -1183,7 +1135,6 @@ recol1d=11282 weight=20g category=category_69 members=yes -tradeable=yes param=next_obj_stage,vial_empty param=decant_potion_enum,potion_1antidragon param=dose_count,1 @@ -1202,3 +1153,4 @@ recol1d=28570 2dxan=84 weight=25g members=yes +tradeable=no diff --git a/data/src/scripts/skill_herblore/configs/brewing/potions_additives.obj b/data/src/scripts/skill_herblore/configs/brewing/potions_additives.obj index a896d19970..7457729618 100644 --- a/data/src/scripts/skill_herblore/configs/brewing/potions_additives.obj +++ b/data/src/scripts/skill_herblore/configs/brewing/potions_additives.obj @@ -11,7 +11,6 @@ model=model_2520_obj 2dyan=256 2dxan=364 weight=7g -tradeable=yes param=brew_potion_struct,3dose1attack param=brew_potion_struct_secondary,3dose2attack // jagex name @@ -26,7 +25,6 @@ model=model_2343_obj 2dyan=12 2dxan=252 weight=7g -tradeable=yes param=brew_potion_struct,3dose1restore // jagex name @@ -41,7 +39,6 @@ model=model_2629_obj 2dyan=380 2dxan=456 weight=7g -tradeable=yes param=brew_potion_struct,3dose1strength param=brew_potion_struct_secondary,3dose2strength // jagex name @@ -58,7 +55,6 @@ model=model_2440_obj 2dyan=48 2dxan=484 weight=7g -tradeable=yes respawnrate=30 param=brew_potion_struct,3doseprayerrestore param=brew_potion_struct_secondary,3dosefisherspotion @@ -77,7 +73,6 @@ recol1d=24135 members=yes cost=20 weight=7g -tradeable=yes param=brew_potion_struct,3doseantipoison param=brew_potion_struct_secondary,3dose2antipoison // guessed name @@ -96,7 +91,6 @@ cost=10 weight=7g name=White berries desc=Sour berries, used in potions. -tradeable=yes respawnrate=10 param=brew_potion_struct,3dose1defense param=brew_potion_struct_secondary,3dose2defense @@ -115,7 +109,6 @@ desc=Finely ground scale of Dragon. cost=52 weight=7g members=yes -tradeable=yes param=brew_potion_struct,weapon_poison param=brew_potion_struct_secondary,3dose1antidragon // jagex name @@ -132,7 +125,6 @@ recol1d=25765 2dyan=84 2dxan=260 weight=3oz -tradeable=yes respawnrate=50 param=brew_potion_struct,3doserangerspotion // guessed name @@ -154,7 +146,6 @@ recol2d=12640 weight=7g category=category_86 members=yes -tradeable=yes respawnrate=30 param=brew_potion_struct,3dosepotionofzamorak param=brew_potion_struct_secondary,vial_water_jangerberries @@ -174,6 +165,7 @@ recol1d=28570 weight=25g members=yes param=brew_potion_struct,blamish_oil +tradeable=no [ground_bat_bones] name=Ground bat bones @@ -186,7 +178,6 @@ model=model_2742_obj 2dxan=136 weight=100g members=yes -tradeable=yes param=brew_potion_struct,ogre_potion param=brew_potion_struct_secondary,bat_bones_explode param=brew_potion_struct_tertiary,bat_bones_explode2 diff --git a/data/src/scripts/skill_herblore/configs/brewing/potions_unfinished.obj b/data/src/scripts/skill_herblore/configs/brewing/potions_unfinished.obj index bcc6b4032d..8812315af9 100644 --- a/data/src/scripts/skill_herblore/configs/brewing/potions_unfinished.obj +++ b/data/src/scripts/skill_herblore/configs/brewing/potions_unfinished.obj @@ -14,7 +14,6 @@ recol1d=19191 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_marrentill_potion] @@ -31,7 +30,6 @@ recol1d=23158 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_tarromin_potion] @@ -48,7 +46,6 @@ recol1d=23251 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_harralander_potion] @@ -65,7 +62,6 @@ recol1d=23155 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_ranarr_potion] @@ -82,7 +78,6 @@ recol1d=19186 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_irit_potion] @@ -99,7 +94,6 @@ recol1d=21147 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_avantoe_potion] @@ -116,7 +110,6 @@ recol1d=20083 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_kwuarm_potion] @@ -133,7 +126,6 @@ recol1d=23254 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_cadantine_potion] @@ -150,7 +142,6 @@ recol1d=26324 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_dwarf_weed_potion] @@ -167,7 +158,6 @@ recol1d=20186 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_torstol_potion] @@ -184,7 +174,6 @@ recol1d=29427 weight=2oz category=category_69 members=yes -tradeable=yes // guessed name [unf_lantadyme_potion] @@ -201,4 +190,3 @@ recol1d=26324 weight=2oz category=category_69 members=yes -tradeable=yes diff --git a/data/src/scripts/skill_herblore/configs/brewing/vials.obj b/data/src/scripts/skill_herblore/configs/brewing/vials.obj index df3decdbfa..9a962d1572 100644 --- a/data/src/scripts/skill_herblore/configs/brewing/vials.obj +++ b/data/src/scripts/skill_herblore/configs/brewing/vials.obj @@ -12,7 +12,6 @@ recol1d=16956 2dxan=84 weight=20g cost=2 -tradeable=yes param=changesto,vial_empty // jagex name @@ -28,6 +27,5 @@ manwear=model_561_obj_wear,0 womanwear=model_561_obj_wear,6 weight=15g cost=2 -tradeable=yes param=crafting_glass_struct,vial_empty param=changesto,vial_water diff --git a/data/src/scripts/skill_herblore/configs/grinding/grindables.obj b/data/src/scripts/skill_herblore/configs/grinding/grindables.obj index fdeae58862..a0b12c7d8b 100644 --- a/data/src/scripts/skill_herblore/configs/grinding/grindables.obj +++ b/data/src/scripts/skill_herblore/configs/grinding/grindables.obj @@ -12,7 +12,6 @@ cost=20 weight=7g name=Unicorn horn desc=This horn has restorative properties. -tradeable=yes param=grindable_ingredient_refined,unicorn_horn_dust param=grindable_ingredient_message,You grind the unicorn horn to dust. // jagex name @@ -28,7 +27,6 @@ model=model_2761_obj 2dyan=148 2dxan=212 weight=10g -tradeable=yes respawnrate=30 param=grindable_ingredient_refined,dragon_scale_dust param=grindable_ingredient_message,You grind down the blue dragon scale. diff --git a/data/src/scripts/skill_herblore/configs/grinding/tools.obj b/data/src/scripts/skill_herblore/configs/grinding/tools.obj index ef6a82bebe..c54c8105ee 100644 --- a/data/src/scripts/skill_herblore/configs/grinding/tools.obj +++ b/data/src/scripts/skill_herblore/configs/grinding/tools.obj @@ -8,7 +8,6 @@ model=model_2682_obj 2dyan=316 2dxan=180 weight=2oz -tradeable=yes name=Pestle and mortar desc=I can grind things for potions in this. diff --git a/data/src/scripts/skill_herblore/configs/herbs.obj b/data/src/scripts/skill_herblore/configs/herbs.obj index 987cdd4cba..fa98c5d64c 100644 --- a/data/src/scripts/skill_herblore/configs/herbs.obj +++ b/data/src/scripts/skill_herblore/configs/herbs.obj @@ -16,7 +16,6 @@ recol2d=288 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_exp,25 param=identified_herb_message,This herb is a Guam Leaf. param=brew_potion_struct,unf_guam_potion @@ -39,7 +38,6 @@ recol2d=384 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,5 param=identified_herb_exp,38 param=identified_herb_message,This herb is a Marrentill. @@ -62,7 +60,6 @@ recol2d=387 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,11 param=identified_herb_exp,50 param=identified_herb_message,This herb is a Tarromin. @@ -85,7 +82,6 @@ recol2d=8512 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,20 param=identified_herb_exp,63 param=identified_herb_message,This herb is a Harralander. @@ -108,7 +104,6 @@ recol2d=6432 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,25 param=identified_herb_exp,75 param=identified_herb_message,This herb is a Ranarr Weed. @@ -131,7 +126,6 @@ recol2d=5507 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,40 param=identified_herb_exp,88 param=identified_herb_message,This herb is an Irit Leaf. @@ -154,7 +148,6 @@ recol2d=1251 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,48 param=identified_herb_exp,100 param=identified_herb_message,This herb is an Avantoe. @@ -177,7 +170,6 @@ recol2d=6400 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,54 param=identified_herb_exp,113 param=identified_herb_message,This herb is a Kwuarm. @@ -200,7 +192,6 @@ recol2d=5346 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,65 param=identified_herb_exp,125 param=identified_herb_message,This herb is a Cadantine. @@ -223,7 +214,6 @@ recol2d=224 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,70 param=identified_herb_exp,138 param=identified_herb_message,This herb is a Dwarf Weed. @@ -246,7 +236,6 @@ recol2d=256 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,75 param=identified_herb_exp,150 param=identified_herb_message,This herb is a Torstol. @@ -274,6 +263,7 @@ param=identified_herb_level,3 param=identified_herb_exp,25 param=identified_herb_message,You identify the herb. It is Snake Weed. // https://youtu.be/maeY2TnTNVY?t=530 +tradeable=no // guessed name [ardrigal] @@ -296,6 +286,7 @@ param=identified_herb_level,3 param=identified_herb_exp,25 param=identified_herb_message,You identify the herb. It is Ardrigal. // https://youtu.be/maeY2TnTNVY?t=898 +tradeable=no // guessed name [sito_foil] @@ -314,6 +305,7 @@ param=identified_herb_level,3 param=identified_herb_exp,25 param=identified_herb_message,You identify the herb. It is Sito Foil. // https://youtu.be/maeY2TnTNVY?t=1126 +tradeable=no // guessed name [volencia_moss] @@ -332,6 +324,7 @@ param=identified_herb_level,3 param=identified_herb_exp,25 param=identified_herb_message,You identify the herb. It is Volencia Moss. // https://youtu.be/maeY2TnTNVY?t=1205 +tradeable=no // guessed name [rogues_purse] @@ -350,6 +343,7 @@ param=identified_herb_level,3 param=identified_herb_exp,25 param=identified_herb_message,You identify the herb. It is Rogues Purse. // https://youtu.be/maeY2TnTNVY?t=1493 +tradeable=no // jagex name [lantadyme] @@ -364,7 +358,6 @@ model=model_2364_obj 2dxan=376 weight=7g category=category_774 -tradeable=yes param=identified_herb_level,67 param=identified_herb_exp,131 param=identified_herb_message,This herb is a Lantadyme. diff --git a/data/src/scripts/skill_herblore/configs/identifying/unids.obj b/data/src/scripts/skill_herblore/configs/identifying/unids.obj index f82c633fbc..c03e76ec7a 100644 --- a/data/src/scripts/skill_herblore/configs/identifying/unids.obj +++ b/data/src/scripts/skill_herblore/configs/identifying/unids.obj @@ -12,7 +12,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes respawnrate=200 // guessed name @@ -28,7 +27,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_tarromin] @@ -43,7 +41,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_harralander] @@ -58,7 +55,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_ranarr_weed] @@ -72,7 +68,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_irit_leaf] @@ -86,7 +81,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_avantoe] @@ -100,7 +94,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_kwuarm] @@ -114,7 +107,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_cadantine] @@ -128,7 +120,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_dwarf_weed] @@ -142,7 +133,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_torstol] @@ -156,7 +146,6 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes // guessed name [unidentified_snake_weed] @@ -176,6 +165,7 @@ members=yes 2dxan=484 iop1=Identify weight=7g +tradeable=no // guessed name [unidentified_ardrigal] @@ -195,6 +185,7 @@ members=yes 2dxan=376 weight=7g iop1=Identify +tradeable=no // guessed name [unidentified_sito_foil] @@ -209,6 +200,7 @@ members=yes 2dxan=376 iop1=Identify weight=7g +tradeable=no // guessed name [unidentified_volencia_moss] @@ -223,6 +215,7 @@ members=yes 2dxan=376 iop1=Identify weight=7g +tradeable=no // guessed name [unidentified_rogues_purse] @@ -237,6 +230,7 @@ members=yes 2dxan=376 iop1=Identify weight=7g +tradeable=no // guessed name [unidentified_lantadyme] @@ -251,4 +245,3 @@ model=model_2364_obj 2dyan=1588 2dxan=376 weight=7g -tradeable=yes diff --git a/data/src/scripts/skill_magic/configs/enchanted_jewelry.obj b/data/src/scripts/skill_magic/configs/enchanted_jewelry.obj index e90119f21e..6530fff5f8 100644 --- a/data/src/scripts/skill_magic/configs/enchanted_jewelry.obj +++ b/data/src/scripts/skill_magic/configs/enchanted_jewelry.obj @@ -16,7 +16,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [ring_of_duel_8] name=Ring of dueling(8) @@ -37,7 +36,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=next_obj_stage,ring_of_duel_7 param=charges,8 @@ -60,7 +58,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=next_obj_stage,ring_of_duel_6 param=charges,7 @@ -83,7 +80,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=next_obj_stage,ring_of_duel_5 param=charges,6 @@ -106,7 +102,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=next_obj_stage,ring_of_duel_4 param=charges,5 @@ -129,7 +124,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=next_obj_stage,ring_of_duel_3 param=charges,4 @@ -152,7 +146,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=next_obj_stage,ring_of_duel_2 param=charges,3 @@ -175,7 +168,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=next_obj_stage,ring_of_duel_1 param=charges,2 @@ -198,7 +190,6 @@ wearpos=ring weight=6g iop4=Rub category=category_136 -tradeable=yes param=charges,1 //guess @@ -220,7 +211,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [ring_of_life] name=Ring of life @@ -238,7 +228,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [ring_of_wealth] name=Ring of wealth @@ -259,7 +248,6 @@ iop2=Wear wearpos=ring weight=6g category=category_656 -tradeable=yes [amulet_of_glory] cost=17625 @@ -284,7 +272,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g -tradeable=yes param=stabattack,10 param=slashattack,10 param=crushattack,10 @@ -322,7 +309,6 @@ manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g category=category_557 -tradeable=yes param=stabattack,10 param=slashattack,10 param=crushattack,10 @@ -361,7 +347,6 @@ manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g category=category_557 -tradeable=yes param=stabattack,10 param=slashattack,10 param=crushattack,10 @@ -400,7 +385,6 @@ manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g category=category_557 -tradeable=yes param=stabattack,10 param=slashattack,10 param=crushattack,10 @@ -439,7 +423,6 @@ manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g category=category_557 -tradeable=yes param=stabattack,10 param=slashattack,10 param=crushattack,10 @@ -475,7 +458,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g -tradeable=yes param=strengthbonus,10 [amulet_of_magic] @@ -499,7 +481,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g -tradeable=yes param=magicattack,10 [amulet_of_defence] @@ -523,7 +504,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g -tradeable=yes param=stabdefence,7 param=slashdefence,7 param=crushdefence,7 @@ -549,7 +529,6 @@ wearpos=front manwear=model_290_obj_wear,0 womanwear=model_454_obj_wear,0 weight=10g -tradeable=yes param=stabattack,6 param=slashattack,6 param=crushattack,6 diff --git a/data/src/scripts/skill_magic/configs/magic.obj b/data/src/scripts/skill_magic/configs/magic.obj index 0ac59a5037..af82cabd6b 100644 --- a/data/src/scripts/skill_magic/configs/magic.obj +++ b/data/src/scripts/skill_magic/configs/magic.obj @@ -16,7 +16,6 @@ womanwear=model_348_idk,0 manwear2=model_292_idk womanwear2=model_456_idk weight=2lb -tradeable=yes param=magicattack,3 param=magicdefence,3 @@ -37,7 +36,6 @@ womanwear=model_377_obj_wear,0 manhead=model_44_obj_wear womanhead=model_102_obj_wear weight=1lb -tradeable=yes param=magicattack,2 param=magicdefence,2 @@ -59,7 +57,6 @@ womanwear=model_348_idk,0 manwear2=model_292_idk womanwear2=model_456_idk weight=2lb -tradeable=yes param=magicattack,3 param=magicdefence,3 @@ -82,6 +79,5 @@ womanwear=model_377_obj_wear,0 manhead=model_44_obj_wear womanhead=model_102_obj_wear weight=1lb -tradeable=yes param=magicattack,2 param=magicdefence,2 \ No newline at end of file diff --git a/data/src/scripts/skill_magic/configs/orbs.obj b/data/src/scripts/skill_magic/configs/orbs.obj index 5feb2c65fe..b373bb4969 100644 --- a/data/src/scripts/skill_magic/configs/orbs.obj +++ b/data/src/scripts/skill_magic/configs/orbs.obj @@ -13,7 +13,6 @@ members=yes name=Unpowered orb desc=I'd prefer it if it was powered. cost=100 -tradeable=yes param=crafting_glass_struct,stafforb [fire_orb] @@ -30,7 +29,6 @@ name=Fire orb desc=A magic glowing orb. cost=300 weight=1lb -tradeable=yes category=craft_orb param=crafting_staff_struct,fire_orb @@ -48,7 +46,6 @@ name=Water orb desc=A magic glowing orb. cost=300 weight=1lb -tradeable=yes category=craft_orb param=crafting_staff_struct,water_orb @@ -64,7 +61,6 @@ name=Air orb desc=A magic glowing orb. cost=300 weight=1lb -tradeable=yes category=craft_orb param=crafting_staff_struct,air_orb @@ -82,6 +78,5 @@ name=Earth orb desc=A magic glowing orb. cost=300 weight=1lb -tradeable=yes category=craft_orb param=crafting_staff_struct,earth_orb diff --git a/data/src/scripts/skill_magic/configs/runes.obj b/data/src/scripts/skill_magic/configs/runes.obj index 8804644746..72df313af6 100644 --- a/data/src/scripts/skill_magic/configs/runes.obj +++ b/data/src/scripts/skill_magic/configs/runes.obj @@ -8,7 +8,6 @@ model=model_2399_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes category=category_149 respawnrate=200 @@ -22,7 +21,6 @@ model=model_2652_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes category=category_149 [airrune] @@ -35,7 +33,6 @@ model=model_2405_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes category=category_149 [earthrune] @@ -48,7 +45,6 @@ model=model_2737_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes category=category_149 [mindrune] @@ -61,7 +57,6 @@ model=model_2481_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes category=category_149 [bodyrune] @@ -74,7 +69,6 @@ model=model_2340_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes category=category_149 [deathrune] @@ -87,7 +81,6 @@ model=model_2645_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes respawnrate=200 category=category_149 @@ -101,7 +94,6 @@ model=model_2734_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes respawnrate=200 category=category_149 @@ -115,7 +107,6 @@ model=model_2707_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes respawnrate=200 category=category_149 @@ -129,7 +120,6 @@ model=model_2382_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes category=category_149 [cosmicrune] @@ -142,7 +132,6 @@ model=model_2735_obj 2dzoom=740 2dxan=516 weight=2g -tradeable=yes respawnrate=200 category=category_149 @@ -157,7 +146,6 @@ model=model_2665_obj 2dxan=516 members=yes weight=2g -tradeable=yes respawnrate=200 category=category_149 @@ -172,5 +160,4 @@ model=model_2434_obj 2dxan=516 members=yes weight=2g -tradeable=yes category=category_149 diff --git a/data/src/scripts/skill_magic/scripts/magic.rs2 b/data/src/scripts/skill_magic/scripts/magic.rs2 index 0ccb803548..6e2a1ddb89 100644 --- a/data/src/scripts/skill_magic/scripts/magic.rs2 +++ b/data/src/scripts/skill_magic/scripts/magic.rs2 @@ -61,7 +61,7 @@ def_int $rune_count3; $rune1, $rune_count1, $rune2, $rune_count2, $rune3, $rune_count3 = db_getfield($spell_data, magic_spell_table:runesrequired, 0); // check if wielding staff and look for staff in db def_obj $staff = inv_getobj(worn, ^wearpos_rhand); -if (map_members = false & oc_members($staff) = true) { +if (map_members = false & $staff ! null & oc_members($staff) = true) { return($rune1, $rune_count1, $rune2, $rune_count2, $rune3, $rune_count3); } db_find(magic_staff_table:staff, $staff); diff --git a/data/src/scripts/skill_magic/scripts/spells/charge.rs2 b/data/src/scripts/skill_magic/scripts/spells/charge.rs2 index 5b30303f58..a898e61a5a 100644 --- a/data/src/scripts/skill_magic/scripts/spells/charge.rs2 +++ b/data/src/scripts/skill_magic/scripts/spells/charge.rs2 @@ -1,7 +1,7 @@ [if_button,magic:charge] if_close; if (p_finduid(uid) = true) { - if (%magearena_progress < ^mage_arena_staff_given) { + if (%magearena < ^mage_arena_staff_given) { mes("This spell can only be learnt in the Mage Arena."); return; } diff --git a/data/src/scripts/skill_magic/scripts/spells/superheat.rs2 b/data/src/scripts/skill_magic/scripts/spells/superheat.rs2 index c78b493f45..8b3d45fbb8 100644 --- a/data/src/scripts/skill_magic/scripts/spells/superheat.rs2 +++ b/data/src/scripts/skill_magic/scripts/spells/superheat.rs2 @@ -23,6 +23,8 @@ if ($ore1 = iron_ore & inv_total(inv, coal) > 1 & stat(smithing) >= 30) { // remove bar at end of name def_string $metal_name = substring(oc_name($bar), 0, calc(string_length(oc_name($bar)) - 4)); def_struct $bar_struct = oc_param($bar, smelting_struct); +// Ensure ore1 now refers to the primary ingredient (important for bronze) +$ore1 = struct_param($bar_struct, ingredient); // if not enough level if (stat(smithing) < struct_param($bar_struct, levelrequired)) { mes("You need a smithing level of at least to smelt <$metal_name>."); diff --git a/data/src/scripts/skill_mining/configs/ores.obj b/data/src/scripts/skill_mining/configs/ores.obj index f8d23a1f6b..a81567529d 100644 --- a/data/src/scripts/skill_mining/configs/ores.obj +++ b/data/src/scripts/skill_mining/configs/ores.obj @@ -8,7 +8,6 @@ model=model_2349_obj 2dxan=516 weight=2g category=category_91 -tradeable=yes [clay] name=Clay @@ -22,7 +21,6 @@ recol1d=22025 2dxan=264 weight=1kg category=category_91 -tradeable=yes [copper_ore] cost=3 @@ -38,7 +36,6 @@ recol1d=29095 2dxan=368 weight=5lb category=category_91 -tradeable=yes param=smeltsto,bronze_bar [tin_ore] @@ -55,7 +52,6 @@ recol1d=14798 2dxan=368 weight=5lb category=category_91 -tradeable=yes param=smeltsto,bronze_bar [iron_ore] @@ -74,7 +70,6 @@ recol2d=6242 2dxan=368 weight=5lb category=category_91 -tradeable=yes param=smeltsto,iron_bar [silver_ore] @@ -93,7 +88,6 @@ recol2d=8456 2dxan=368 weight=5lb category=category_91 -tradeable=yes param=smeltsto,silver_bar [gold_ore] @@ -112,7 +106,6 @@ recol2d=31393 2dxan=368 weight=5lb category=category_91 -tradeable=yes respawnrate=500 param=smeltsto,gold_bar @@ -133,6 +126,8 @@ recol2d=31393 weight=5lb category=category_91 members=yes +param=smeltsto,perfect_gold_bar +tradeable=no [mithril_ore] cost=162 @@ -148,7 +143,6 @@ recol1d=6346 2dxan=368 weight=4lb category=category_91 -tradeable=yes param=smeltsto,mithril_bar [adamantite_ore] @@ -165,7 +159,6 @@ recol1d=6438 2dxan=368 weight=6lb category=category_91 -tradeable=yes param=smeltsto,adamantite_bar [runite_ore] @@ -182,7 +175,6 @@ recol1d=6476 2dxan=368 weight=5lb category=category_91 -tradeable=yes param=smeltsto,runite_bar [coal] @@ -199,4 +191,3 @@ recol1d=4226 2dxan=368 weight=5lb category=category_91 -tradeable=yes diff --git a/data/src/scripts/skill_mining/configs/pickaxes.obj b/data/src/scripts/skill_mining/configs/pickaxes.obj index 7c000a6ab5..7b0e0669b8 100644 --- a/data/src/scripts/skill_mining/configs/pickaxes.obj +++ b/data/src/scripts/skill_mining/configs/pickaxes.obj @@ -16,7 +16,6 @@ weight=5lb wearpos=righthand iop2=Wield category=weapon_pickaxe -tradeable=yes param=stabattack,4 param=slashattack,-2 param=crushattack,2 @@ -52,7 +51,6 @@ weight=5lb wearpos=righthand iop2=Wield category=weapon_pickaxe -tradeable=yes param=stabattack,5 param=slashattack,-2 param=crushattack,3 @@ -86,7 +84,6 @@ weight=5lb wearpos=righthand iop2=Wield category=weapon_pickaxe -tradeable=yes param=stabattack,8 param=slashattack,-2 param=crushattack,6 @@ -122,7 +119,6 @@ weight=6lb wearpos=righthand iop2=Wield category=weapon_pickaxe -tradeable=yes param=stabattack,17 param=slashattack,-2 param=crushattack,15 @@ -158,7 +154,6 @@ weight=4lb wearpos=righthand iop2=Wield category=weapon_pickaxe -tradeable=yes param=stabattack,12 param=slashattack,-2 param=crushattack,10 @@ -194,7 +189,6 @@ weight=5lb wearpos=righthand iop2=Wield category=weapon_pickaxe -tradeable=yes param=stabattack,26 param=slashattack,-2 param=crushattack,24 diff --git a/data/src/scripts/skill_mining/scripts/mine.rs2 b/data/src/scripts/skill_mining/scripts/mine.rs2 index 55e922e400..90ec20f6b4 100644 --- a/data/src/scripts/skill_mining/scripts/mine.rs2 +++ b/data/src/scripts/skill_mining/scripts/mine.rs2 @@ -110,7 +110,6 @@ if (%action_delay < map_clock) { ~mining_sound; p_oploc(3); - [label,get_ore_normal] db_find(mining_table:rock, loc_type); def_dbrow $data = db_findnext; @@ -141,7 +140,13 @@ if (random($chance) = ^true) { // stop mining, give ore and xp. Sudden says its sound_230 sound_synth(sound_230, 0, 0); anim(null, 0); - inv_add(inv, db_getfield($data, mining_table:rock_output, 0), 1); + // The 'perfect' gold rocks in Family Crest are the same ID as regular gold rocks, so check to + // give out the right ore if we're in that location. Only gold rocks are in this room. + def_namedobj $output = db_getfield($data, mining_table:rock_output, 0); + if(inzone(^crest_perfect_mine_lower_bound, ^crest_perfect_mine_upper_bound, coord) = true) { + $output = perfect_gold_ore; + } + inv_add(inv, $output, 1); stat_advance(mining, db_getfield($data, mining_table:rock_exp, 0)); mes("You manage to mine some ."); return; @@ -240,7 +245,6 @@ if (stat_random(stat(mining), $low, $high) = true) { ~mining_sound; p_oploc(3); - [proc,mining_gem_table]()(namedobj) def_int $rand = random(128); if ($rand < 2) return (uncut_diamond); diff --git a/data/src/scripts/skill_prayer/configs/bones.obj b/data/src/scripts/skill_prayer/configs/bones.obj index 4a62ef4567..4fc51b8820 100644 --- a/data/src/scripts/skill_prayer/configs/bones.obj +++ b/data/src/scripts/skill_prayer/configs/bones.obj @@ -9,7 +9,6 @@ model=model_2674_obj iop1=Bury weight=500g category=bones -tradeable=yes param=bone_exp,45 [burnt_bones] @@ -25,7 +24,6 @@ recol1d=7399 iop1=Bury weight=500g category=bones -tradeable=yes param=bone_exp,45 [bat_bones] @@ -40,7 +38,6 @@ iop1=Bury category=bones weight=300g members=yes -tradeable=yes param=bone_exp,45 param=grindable_ingredient_refined,ground_bat_bones param=grindable_ingredient_message,You grind the bones to a powder. @@ -55,7 +52,6 @@ model=model_222_obj iop1=Bury weight=800g category=bones -tradeable=yes respawnrate=50 param=bone_exp,150 @@ -70,7 +66,6 @@ model=model_222_obj iop1=Bury weight=800g category=bones -tradeable=yes param=bone_exp,300 [dragon_bones] @@ -84,7 +79,6 @@ iop1=Bury weight=1500g category=bones members=yes -tradeable=yes param=bone_exp,720 [wolf_bones] @@ -102,5 +96,4 @@ members=yes 2dxan=400 iop1=Bury category=bones -tradeable=yes param=bone_exp,45 diff --git a/data/src/scripts/skill_prayer/configs/robes.obj b/data/src/scripts/skill_prayer/configs/robes.obj index 8afdf8ce6c..bbafbb5e6c 100644 --- a/data/src/scripts/skill_prayer/configs/robes.obj +++ b/data/src/scripts/skill_prayer/configs/robes.obj @@ -14,7 +14,6 @@ wearpos=legs manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=2lb -tradeable=yes param=prayerbonus,4 [obj_540] @@ -36,7 +35,6 @@ womanwear=model_348_idk,0 manwear2=model_292_idk womanwear2=model_456_idk weight=2lb -tradeable=yes param=prayerbonus,4 [obj_542] @@ -54,7 +52,6 @@ wearpos=legs manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=2lb -tradeable=yes param=prayerbonus,6 [obj_544] @@ -75,7 +72,6 @@ womanwear=model_348_idk,0 manwear2=model_292_idk womanwear2=model_456_idk weight=2lb -tradeable=yes param=prayerbonus,5 [obj_546] @@ -96,7 +92,6 @@ womanwear=model_348_idk,0 manwear2=model_292_idk womanwear2=model_456_idk weight=2lb -tradeable=yes param=prayerbonus,5 [obj_548] @@ -114,5 +109,4 @@ wearpos=legs manwear=model_265_obj_wear,0 womanwear=model_428_idk,0 weight=2lb -tradeable=yes param=prayerbonus,4 diff --git a/data/src/scripts/skill_runecraft/configs/runecraft.obj b/data/src/scripts/skill_runecraft/configs/runecraft.obj index ef1a27d914..f31c16874a 100644 --- a/data/src/scripts/skill_runecraft/configs/runecraft.obj +++ b/data/src/scripts/skill_runecraft/configs/runecraft.obj @@ -10,7 +10,6 @@ model=model_2441_obj 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,1 @@ -26,7 +25,6 @@ model=model_2806_obj 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,4 @@ -42,7 +40,6 @@ model=model_2624_obj 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,5 @@ -58,7 +55,6 @@ model=model_2514_obj 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,3 @@ -74,7 +70,6 @@ model=model_2785_obj 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,6 @@ -90,7 +85,6 @@ model=model_2685_obj 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,2 @@ -107,7 +101,6 @@ members=yes 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,13 //1716, 3829 @@ -125,7 +118,6 @@ members=yes 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,8 @@ -142,7 +134,6 @@ members=yes 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,7 //2408, 4377 @@ -160,7 +151,6 @@ members=yes 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,11 //1860, 4639 @@ -178,7 +168,6 @@ members=yes 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,10 //2858, 3381 @@ -196,7 +185,6 @@ members=yes 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,12 //1814, 3854 @@ -214,6 +202,5 @@ members=yes 2dxan=352 iop4=Locate weight=15g -tradeable=yes category=talismans param=rune_type,9 \ No newline at end of file diff --git a/data/src/scripts/skill_smithing/configs/smelting/smelting.obj b/data/src/scripts/skill_smithing/configs/smelting/smelting.obj index 35a7613396..aa4bc957a9 100644 --- a/data/src/scripts/skill_smithing/configs/smelting/smelting.obj +++ b/data/src/scripts/skill_smithing/configs/smelting/smelting.obj @@ -12,7 +12,6 @@ recol1d=8354 2dxan=196 weight=4lb category=category_151 -tradeable=yes param=smelting_struct,smelting_bronze_bar param=smithing_anvil_struct,smithing_bronze_bar @@ -30,7 +29,6 @@ recol1d=8456 2dxan=196 weight=4lb category=category_151 -tradeable=yes respawnrate=500 param=smelting_struct,smelting_iron_bar param=smithing_anvil_struct,smithing_iron_bar @@ -49,7 +47,6 @@ recol1d=15855 2dxan=196 weight=4lb category=category_151 -tradeable=yes param=smelting_struct,smelting_steel_bar param=smithing_anvil_struct,smithing_steel_bar @@ -67,7 +64,6 @@ recol1d=22198 2dxan=196 weight=4lb category=category_151 -tradeable=yes param=smelting_struct,smelting_silver_bar [gold_bar] @@ -84,7 +80,6 @@ recol1d=31393 2dxan=196 weight=4lb category=category_151 -tradeable=yes respawnrate=1500 param=smelting_struct,smelting_gold_bar @@ -102,7 +97,6 @@ recol1d=6346 2dxan=196 weight=56oz category=category_151 -tradeable=yes param=smelting_struct,smelting_mithril_bar param=smithing_anvil_struct,smithing_mithril_bar @@ -120,7 +114,6 @@ recol1d=6438 2dxan=196 weight=72oz category=category_151 -tradeable=yes param=smelting_struct,smelting_adamantite_bar param=smithing_anvil_struct,smithing_adamantite_bar @@ -138,11 +131,10 @@ recol1d=6476 2dxan=196 weight=4lb category=category_151 -tradeable=yes param=smelting_struct,smelting_runite_bar param=smithing_anvil_struct,smithing_runite_bar -[obj_2365] +[perfect_gold_bar] name='perfect' gold bar desc=It's a bar of 'perfect' gold. cost=300 @@ -157,3 +149,5 @@ recol1d=31393 weight=4lb category=category_151 members=yes +param=smelting_struct,smelting_perfect_gold_bar +tradeable=no diff --git a/data/src/scripts/skill_smithing/configs/smelting/smelting.struct b/data/src/scripts/skill_smithing/configs/smelting/smelting.struct index 9540300eb3..de079b3e54 100644 --- a/data/src/scripts/skill_smithing/configs/smelting/smelting.struct +++ b/data/src/scripts/skill_smithing/configs/smelting/smelting.struct @@ -1,6 +1,7 @@ [smelting_bronze_bar] param=levelfailure,You need a Smithing level of 1 to smelt a bronze bar. param=processfailure,You need at least 1 Copper ore and 1 Tin ore to smelt a bronze bar. +param=processfailure_superheat,You need one copper ore and one tin ore to make bronze. param=processmessage,You smelt the copper and tin together in the furnace. param=productmessage,You retrieve a bar of bronze. param=product,bronze_bar @@ -96,5 +97,12 @@ param=bar_count,1 param=ingredient_secondary,coal param=ingredient_secondary_count,8 -//perfect gold bar -[obj_2365] \ No newline at end of file +[smelting_perfect_gold_bar] +param=levelfailure,You need a Smithing level of 40 to smelt a gold bar. +param=processmessage,You place a lump of gold in the furnace. +param=productmessage,You retrieve a bar of gold from the furnace. +param=product,perfect_gold_bar +param=levelrequired,40 +param=productexp,225 +param=ingredient,perfect_gold_ore +param=bar_count,1 \ No newline at end of file diff --git a/data/src/scripts/skill_smithing/configs/smithing/smithing.obj b/data/src/scripts/skill_smithing/configs/smithing/smithing.obj index f43e92df8b..476ac3919f 100644 --- a/data/src/scripts/skill_smithing/configs/smithing/smithing.obj +++ b/data/src/scripts/skill_smithing/configs/smithing/smithing.obj @@ -11,7 +11,6 @@ model=model_2359_obj 2dxan=340 weight=6lb members=yes -tradeable=yes [shield_right_half] cost=500000 @@ -24,7 +23,6 @@ model=model_2360_obj 2dxan=392 weight=6lb members=yes -tradeable=yes [hammer] name=Hammer @@ -38,4 +36,3 @@ womanwear=model_491_obj_wear,6 2dyan=2012 2dxan=356 weight=2lb -tradeable=yes \ No newline at end of file diff --git a/data/src/scripts/skill_smithing/scripts/smelting/smelting.rs2 b/data/src/scripts/skill_smithing/scripts/smelting/smelting.rs2 index aac4d90d97..3b173f58ca 100644 --- a/data/src/scripts/skill_smithing/scripts/smelting/smelting.rs2 +++ b/data/src/scripts/skill_smithing/scripts/smelting/smelting.rs2 @@ -1,7 +1,7 @@ [oplocu,_smithing_furnace] switch_obj (last_useitem) { - case gold_bar : @craft_gold_interface; + case gold_bar, perfect_gold_bar : @craft_gold_interface; case silver_bar : @craft_silver; case steel_bar : @smelt_cannonballs; case bucket_sand, soda_ash : @smelt_glass; @@ -76,7 +76,17 @@ if ($bar = iron_bar) { } } -stat_advance(smithing, struct_param($struct, productexp)); +// If player is wearing gold smith gauntlets, 2.5x xp. The multiplier was 1.5x in RSC, +// earliest mention of 2.5x (56.2) xp is in May 2005: +// https://web.archive.org/web/20080130035157/https://www.rscommunity.de/index.php?option=content&task=view&id=233 +// No mentioned updates to Family Crest or the gauntlets in that period. +// Maybe it got changed when it was ported to RS2 in Dec 2003? +def_int $xp = struct_param($struct, productexp); +if ($bar = gold_bar & inv_total(worn, gauntlets_of_goldsmithing) > 0) { + $xp = scale(5, 2, $xp); // 2.5x +} + +stat_advance(smithing, $xp); // add bar inv_add(inv, $bar, 1); diff --git a/data/src/scripts/skill_smithing/scripts/smithing/dragon_sq.rs2 b/data/src/scripts/skill_smithing/scripts/smithing/dragon_sq.rs2 index a95960e760..f1970aebcf 100644 --- a/data/src/scripts/skill_smithing/scripts/smithing/dragon_sq.rs2 +++ b/data/src/scripts/skill_smithing/scripts/smithing/dragon_sq.rs2 @@ -40,7 +40,9 @@ anim(human_smithing, 0); sound_synth(anvil_4, 0, 0); // 6 tick delay https://youtu.be/YJmY-RN3MuA?t=86 p_delay(6); -~mesbox("Even for an experienced armourer it is not an easy task, but eventually it is ready. You have restored the dragon square shield to its former glory."); +~mesbox("Even for an experienced armourer it is not an easy|task, but eventually it is ready. You have restored|the dragon square shield to it's former glory."); +// https://storage.googleapis.com/tannerdino/images/dragonsquare.png // archive date 2005-03-22 +//~mesbox("Even for an experienced armourer it is not an easy task, but eventually it is ready. You have restored the dragon square shield to its former glory."); // delete shield halfs inv_del(inv, shield_left_half, 1); inv_del(inv, shield_right_half, 1); diff --git a/data/src/scripts/skill_woodcutting/configs/axes/axes.obj b/data/src/scripts/skill_woodcutting/configs/axes/axes.obj index 5db5883dd3..ff153b8ea0 100644 --- a/data/src/scripts/skill_woodcutting/configs/axes/axes.obj +++ b/data/src/scripts/skill_woodcutting/configs/axes/axes.obj @@ -15,7 +15,6 @@ manwear=model_510_obj_wear,0 womanwear=model_510_obj_wear,6 category=weapon_axe weight=3lb -tradeable=yes respawnrate=500 param=woodcutting_struct,woodcutting_iron_axe param=stabattack,-2 @@ -50,7 +49,6 @@ manwear=model_510_obj_wear,0 womanwear=model_510_obj_wear,6 category=weapon_axe weight=3lb -tradeable=yes param=woodcutting_struct,woodcutting_bronze_axe param=stabattack,-2 param=slashattack,4 @@ -82,7 +80,6 @@ manwear=model_510_obj_wear,0 womanwear=model_510_obj_wear,6 category=weapon_axe weight=3lb -tradeable=yes param=woodcutting_struct,woodcutting_steel_axe param=stabattack,-2 param=slashattack,8 @@ -116,7 +113,6 @@ manwear=model_510_obj_wear,0 womanwear=model_510_obj_wear,6 category=weapon_axe weight=40oz -tradeable=yes param=woodcutting_struct,woodcutting_mithril_axe param=stabattack,-2 param=slashattack,12 @@ -150,7 +146,6 @@ manwear=model_510_obj_wear,0 womanwear=model_510_obj_wear,6 category=weapon_axe weight=56oz -tradeable=yes param=woodcutting_struct,woodcutting_adamant_axe param=stabattack,-2 param=slashattack,17 @@ -184,7 +179,6 @@ womanwear=model_510_obj_wear,6 category=weapon_axe weight=3lb cost=12800 -tradeable=yes param=woodcutting_struct,woodcutting_rune_axe param=stabattack,-2 param=slashattack,26 @@ -219,7 +213,6 @@ category=weapon_axe cost=384 iop2=Wield weight=3lb -tradeable=yes param=woodcutting_struct,woodcutting_black_axe param=stabattack,-2 param=slashattack,10 diff --git a/data/src/scripts/tutorial/configs/tutorial.obj b/data/src/scripts/tutorial/configs/tutorial.obj index 260c0886ab..e0f3125b2a 100644 --- a/data/src/scripts/tutorial/configs/tutorial.obj +++ b/data/src/scripts/tutorial/configs/tutorial.obj @@ -11,6 +11,7 @@ weight=3lb 2dxan=280 op4=Light weight=3lb +tradeable=no [tutorial_raw_shrimps] name=Raw shrimps @@ -25,7 +26,6 @@ recol2d=30319 2dxan=272 cost=5 weight=120g -tradeable=yes [tutorial_pot_of_flour] name=Pot of flour @@ -38,4 +38,3 @@ model=model_2406_obj 2dxan=112 cost=10 weight=3lb -tradeable=yes diff --git a/data/src/scripts/tutorial/scripts/guides/combat_instructor.rs2 b/data/src/scripts/tutorial/scripts/guides/combat_instructor.rs2 index 0ac7aa9a8b..13825e33ec 100644 --- a/data/src/scripts/tutorial/scripts/guides/combat_instructor.rs2 +++ b/data/src/scripts/tutorial/scripts/guides/combat_instructor.rs2 @@ -138,7 +138,7 @@ if (%tutorial_progress > ^combat_instructor_worn_inventory & ~tutorial_has_obj_on_person(wooden_shield) = false) { inv_add(inv, bronze_sword, 1); inv_add(inv, wooden_shield, 1); - ~doubleobjbox(bronze_sword, wooden_shield, "The Combat Guide gives you a |@blu@Bronze sword@bla@ |and a |@blu@Wooden Shield!"); + ~doubleobjbox(bronze_sword, wooden_shield, "The Combat Guide gives you a |@blu@Bronze sword@bla@ |and a |@blu@Wooden Shield!", 150); }else if (~tutorial_has_obj_on_person(bronze_sword) = false) { inv_add(inv, bronze_sword, 1); ~objbox(bronze_sword, "The Combat Guide gives you a |@blu@Bronze sword!", 250, 0, 0); @@ -153,7 +153,7 @@ if (%tutorial_progress > ^combat_instructor_after_rat_kill_melee) { & ~tutorial_has_obj_on_person(shortbow) = false) { inv_add(inv, bronze_arrow, 50); inv_add(inv, shortbow, 1); - ~doubleobjbox(bronze_arrow_5, shortbow, "The Combat Guide gives you some |@blu@Bronze arrows@bla@ |and a |@blu@Shortbow!"); + ~doubleobjbox(bronze_arrow_5, shortbow, "The Combat Guide gives you some |@blu@Bronze arrows@bla@ |and a |@blu@Shortbow!", 150); }else if (~tutorial_has_obj_on_person(bronze_arrow) = false) { inv_add(inv, bronze_arrow, 50); ~objbox(bronze_arrow_5, "The Combat Guide gives you some |@blu@Bronze arrows!", 250, 0, 0); diff --git a/data/src/scripts/tutorial/scripts/guides/magic_instructor.rs2 b/data/src/scripts/tutorial/scripts/guides/magic_instructor.rs2 index 1429562442..58cd91302f 100644 --- a/data/src/scripts/tutorial/scripts/guides/magic_instructor.rs2 +++ b/data/src/scripts/tutorial/scripts/guides/magic_instructor.rs2 @@ -41,7 +41,7 @@ if (inv_total(inv, airrune) >= 25 & inv_total(inv, mindrune) >= 25) { } if (inv_total(inv, airrune) < 25 & inv_total(inv, mindrune) < 25) { - ~doubleobjbox(airrune, mindrune, "Terrova gives you some |@blu@Air runes| and some |@blu@Mind runes!"); + ~doubleobjbox(airrune, mindrune, "Terrova gives you some |@blu@Air runes| and some |@blu@Mind runes!", 150); inv_add(inv, airrune, ~magic_instructor_runes_to_give(airrune)); inv_add(inv, mindrune, ~magic_instructor_runes_to_give(mindrune)); }else if (inv_total(inv, airrune) < 25) { @@ -89,7 +89,7 @@ if (%tutorial_progress = ^tutorial_successful_wind_strike) { [proc,magic_instructor_give_runes] // check inventory space... // There's no inventory full message on OSRS it still shows the interface just no runes are given... -~doubleobjbox(airrune, mindrune, "Terrova gives you five |@blu@Air runes| and five |@blu@Mind runes!"); +~doubleobjbox(airrune, mindrune, "Terrova gives you five |@blu@Air runes| and five |@blu@Mind runes!", 150); inv_add(inv, airrune, 5); inv_add(inv, mindrune, 5); diff --git a/data/src/scripts/tutorial/scripts/guides/master_chef.rs2 b/data/src/scripts/tutorial/scripts/guides/master_chef.rs2 index 84d9e97b74..75afde0e07 100644 --- a/data/src/scripts/tutorial/scripts/guides/master_chef.rs2 +++ b/data/src/scripts/tutorial/scripts/guides/master_chef.rs2 @@ -36,7 +36,7 @@ switch_int(%tutorial_progress) { if (inv_total(inv, tutorial_pot_of_flour) < 1 & inv_total(inv, bucket_water) < 1) { inv_add(inv, tutorial_pot_of_flour, 1); inv_add(inv, bucket_water, 1); - ~doubleobjbox(bucket_water, tutorial_pot_of_flour, "The Cooking Guide gives you a |@blu@Bucket of Water@bla@ |and a|@blu@Pot of Flour!"); + ~doubleobjbox(bucket_water, tutorial_pot_of_flour, "The Cooking Guide gives you a |@blu@Bucket of Water@bla@ |and a|@blu@Pot of Flour!", 150); } else if (inv_total(inv, tutorial_pot_of_flour) < 1 & inv_total(inv, bucket_water) > 0) { inv_add(inv, tutorial_pot_of_flour, 1); ~objbox(tutorial_pot_of_flour, "The Cooking Guide gives you a |@blu@Pot of Flour.", 250, 0, divide(^objbox_height, 2)); diff --git a/data/src/scripts/tutorial/scripts/guides/survival_guide.rs2 b/data/src/scripts/tutorial/scripts/guides/survival_guide.rs2 index 2799b1b540..9fc2d1cdaf 100644 --- a/data/src/scripts/tutorial/scripts/guides/survival_guide.rs2 +++ b/data/src/scripts/tutorial/scripts/guides/survival_guide.rs2 @@ -13,7 +13,7 @@ switch_int(%tutorial_progress) { [label,survival_guide_start] ~chatnpc("Hello there newcomer. My name is Brynna. My job is|to teach you a few survival tips and tricks. First off|we're going to start with the most basic survival skill of|all; making a fire."); -~doubleobjbox(tinderbox, bronze_axe, "The Survival Guide gives you a |@blu@Tinderbox@bla@ |and a |@blu@Bronze Hatchet!"); +~doubleobjbox(tinderbox, bronze_axe, "The Survival Guide gives you a |@blu@Tinderbox@bla@ |and a |@blu@Bronze Hatchet!", 150); %tutorial_progress = ^survival_guide_open_inventory; ~tutorial_step_view_inventory; @@ -32,7 +32,7 @@ switch_int(%tutorial_progress) { if (~tutorial_has_obj_on_person(bronze_axe) = false & inv_total(inv, tinderbox) < 1) { inv_add(inv, bronze_axe, 1); inv_add(inv, tinderbox, 1); - ~doubleobjbox(tinderbox, bronze_axe, "The Survival Guide gives you a |@blu@Tinderbox@bla@ |and a |@blu@Bronze Hatchet!"); + ~doubleobjbox(tinderbox, bronze_axe, "The Survival Guide gives you a |@blu@Tinderbox@bla@ |and a |@blu@Bronze Hatchet!", 150); } else if (~tutorial_has_obj_on_person(bronze_axe) = false) { inv_add(inv, bronze_axe, 1); ~objbox(bronze_axe, "The Survival Guide gives you a |@blu@Bronze Hatchet!", 250, 0, 0); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000000..06694c6727 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,71 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { + ignores: ['bundle.js', 'out/*', 'public/*', 'data/*', 'src/3rdparty/*', 'src/**/*.test.ts', 'src/**/*.bench.ts'] + }, + { languageOptions: { globals: globals.node } }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, // recommendedTypeChecked + // { + // languageOptions: { + // parserOptions: { + // projectService: true, + // tsconfigRootDir: import.meta.dirname, + // }, + // } + // }, + { + rules: { + indent: ['error', 4, { SwitchCase: 1 }], + quotes: ['error', 'single', { avoidEscape: true }], + semi: ['error', 'always'], + + /** + * https://eslint.org/docs/latest/rules/no-constant-condition#checkloops + * + * Allows constant conditions in loops but not in if statements + */ + 'no-constant-condition': ['error', { checkLoops: false }], + + /** + * (jkm) this rule is included in the default ruleset, we should consider + * resolving the issues and setting it to error + * https://eslint.org/docs/latest/rules/no-case-declarations + */ + 'no-case-declarations': 'warn', + + /** + * (jkm) + * The following rules are included in @typescript-eslint/recommended + * I have set them to warn instead of error, to avoid having to fix them + * We should consider fixing them and setting them to error + */ + '@typescript-eslint/no-namespace': 'warn', + '@typescript-eslint/no-explicit-any': 'warn', + + '@typescript-eslint/no-unused-vars': [ + // TODO: Set to error + 'warn', + { + /** + * Allow variables prefixed with underscores to skip this rule. + * There aren't many good reasons to have unused variables, + * but the codebase has 100s of them. + */ + 'vars': 'all', + 'varsIgnorePattern': '^_', + /** + * Allow parameters prefixed with underscores to skip this rule. + * This is a common practice for router methods with req and res parameters. + */ + 'args': 'all', + 'argsIgnorePattern': '^_', + } + ], + } + } +]; diff --git a/nodemon.json b/nodemon.json deleted file mode 100644 index 458be10e2e..0000000000 --- a/nodemon.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ignore": ["node_modules", "data", "dump"], - "watch": ["src"], - "exec": "node --import @swc-node/register/esm-register --enable-source-maps --no-warnings", - "ext": "ts,js,json" -} \ No newline at end of file diff --git a/package.json b/package.json index 0d153a7d70..d0542fad53 100644 --- a/package.json +++ b/package.json @@ -4,34 +4,33 @@ "type": "module", "imports": { "#3rdparty/*": "./src/3rdparty/*", - "#jagex2/*": "./src/jagex2/*", + "#jagex/*": "./src/jagex/*", "#lostcity/*": "./src/lostcity/*" }, "scripts": { - "build": "npm run ts-loader src/lostcity/tools/cache/pack.ts", + "build": "tsx src/lostcity/scripts/cache/pack.ts", "bundle": "npm run bundle:esbuild", "bundle:bun": "bun bundle.js", - "bundle:esbuild": "npm run ts-loader bundle.js", + "bundle:esbuild": "tsx bundle.js", "clean": "npm run client:clean && npm run server:clean", "client": "java -cp 225.2004-05-18.jar client 10 0 highmem members", - "client:clean": "npm run ts-loader src/lostcity/tools/cache/cleanClient.ts", + "client:clean": "tsx src/lostcity/scripts/cache/cleanClient.ts", "db:migrate": "prisma migrate deploy", "db:reset": "prisma migrate reset --force", "db:schema": "prisma migrate dev", - "dev": "nodemon src/lostcity/app.ts", - "friend": "npm run ts-loader src/lostcity/friend.ts", - "lint": "eslint src --ext .ts --ext .js", - "lint:staged": "eslint --ext .ts --ext .js", - "login": "npm run ts-loader src/lostcity/login.ts", - "maintenance": "npm run ts-loader src/lostcity/maintenance.ts", - "precommit": "prettier . --write && eslint . --ext .ts --ext .js --fix", + "dev": "tsx watch --include \"src/*\" src/lostcity/app.ts", + "friend": "tsx src/lostcity/friend.ts", + "lint": "eslint src", + "lint:staged": "eslint", + "login": "tsx src/lostcity/login.ts", + "maintenance": "tsx src/lostcity/maintenance.ts", + "precommit": "prettier . --write && eslint src --fix", "prepare": "husky", - "quickstart": "npm run ts-loader src/lostcity/app.ts", - "server:clean": "npm run ts-loader src/lostcity/tools/cache/cleanServer.ts", - "start": "npm i && npm run ts-loader src/lostcity/app.ts", + "quickstart": "tsx src/lostcity/app.ts", + "server:clean": "tsx src/lostcity/scripts/cache/cleanServer.ts", + "start": "npm i && tsx src/lostcity/app.ts", "test": "vitest run ./src", - "todo": "leasot src/ --skip-unsupported --exit-nicely", - "ts-loader": "node --import @swc-node/register/esm-register --enable-source-maps --no-warnings" + "todo": "leasot src/ --skip-unsupported --exit-nicely" }, "lint-staged": { "package.json": "sort-package-json", @@ -41,51 +40,48 @@ ] }, "dependencies": { - "@jimp/png": "^0.22.12", - "axios": "^1.7.2", + "@jimp/js-png": "^1.6.0", + "@jimp/plugin-quantize": "^1.6.0", + "axios": "^1.7.7", "bcrypt": "^5.1.1", "dotenv": "^16.4.5", "ejs": "^3.1.10", - "jimp": "^0.22.12", + "jimp": "^1.6.0", "kleur": "^4.1.5", - "kysely": "^0.27.3", - "mysql2": "^3.9.7", + "kysely": "^0.27.4", + "mysql2": "^3.11.4", "node-forge": "^1.3.1", - "ws": "^8.17.0" + "prom-client": "^15.1.3", + "ws": "^8.18.0" }, "devDependencies": { "@2004scape/rsmod-pathfinder": "^5.0.4", - "@commitlint/cli": "^19.3.0", - "@commitlint/config-conventional": "^19.2.2", - "@commitlint/types": "^19.0.3", - "@swc-node/register": "1.9.0", - "@swc/core": "1.5.7", - "@swc/helpers": "^0.5.11", + "@commitlint/cli": "^19.5.0", + "@commitlint/config-conventional": "^19.5.0", + "@commitlint/types": "^19.5.0", + "@eslint/js": "^9.15.0", "@types/bcrypt": "^5.0.2", - "@types/bun": "^1.1.6", + "@types/bun": "^1.1.13", "@types/ejs": "^3.1.5", - "@types/eslint": "^8.56.10", - "@types/node": "^20.12.12", + "@types/node": "^22.9.0", "@types/node-forge": "^1.3.11", - "@types/ws": "^8.5.10", - "@typescript-eslint/eslint-plugin": "^7.9.0", - "esbuild": "^0.23.0", - "eslint": "^8.57.0", - "eslint-plugin-unused-imports": "^3.2.0", - "eslint-plugin-vitest": "^0.5.4", - "husky": "^9.0.11", - "leasot": "^13.3.0", - "lint-staged": "^15.2.2", - "nodemon": "^3.1.0", - "prettier": "3.2.5", - "prisma": "^5.14.0", + "@types/ws": "^8.5.13", + "eslint": "^8.57.1", + "globals": "^15.12.0", + "husky": "^9.1.6", + "leasot": "^14.4.0", + "lint-staged": "^15.2.10", + "prettier": "3.3.3", + "prisma": "^5.22.0", "prisma-kysely": "^1.8.0", - "sort-package-json": "^2.10.0", - "tinybench": "^2.8.0", + "sort-package-json": "^2.10.1", + "tinybench": "^3.0.3", + "tsx": "^4.19.2", "typescript": "^5.6.3", - "vitest": "^1.6.0" + "typescript-eslint": "^8.14.0", + "vitest": "^2.1.4" }, "prisma": { - "seed": "npm run ts-loader src/lostcity/db/seed.ts" + "seed": "tsx src/lostcity/db/seed.ts" } } diff --git a/src/jagex2/Trig.test.ts b/src/jagex/Trig.test.ts similarity index 98% rename from src/jagex2/Trig.test.ts rename to src/jagex/Trig.test.ts index 366c97ef54..fa4720578c 100644 --- a/src/jagex2/Trig.test.ts +++ b/src/jagex/Trig.test.ts @@ -1,4 +1,4 @@ -import Trig from '#jagex2/Trig.js'; +import Trig from '#jagex/Trig.js'; describe('Trig', (): void => { describe('cos', (): void => { diff --git a/src/jagex2/Trig.ts b/src/jagex/Trig.ts similarity index 100% rename from src/jagex2/Trig.ts rename to src/jagex/Trig.ts diff --git a/src/jagex2/datastruct/DoublyLinkList.ts b/src/jagex/datastruct/DoublyLinkList.ts similarity index 95% rename from src/jagex2/datastruct/DoublyLinkList.ts rename to src/jagex/datastruct/DoublyLinkList.ts index 7779e9916e..a362e7b5fe 100644 --- a/src/jagex2/datastruct/DoublyLinkList.ts +++ b/src/jagex/datastruct/DoublyLinkList.ts @@ -1,4 +1,4 @@ -import DoublyLinkable from '#jagex2/datastruct/DoublyLinkable.js'; +import DoublyLinkable from '#jagex/datastruct/DoublyLinkable.js'; export default class DoublyLinkList { readonly sentinel: DoublyLinkable; diff --git a/src/jagex2/datastruct/DoublyLinkable.ts b/src/jagex/datastruct/DoublyLinkable.ts similarity index 100% rename from src/jagex2/datastruct/DoublyLinkable.ts rename to src/jagex/datastruct/DoublyLinkable.ts diff --git a/src/jagex2/datastruct/LinkList.ts b/src/jagex/datastruct/LinkList.ts similarity index 100% rename from src/jagex2/datastruct/LinkList.ts rename to src/jagex/datastruct/LinkList.ts diff --git a/src/jagex2/datastruct/Linkable.ts b/src/jagex/datastruct/Linkable.ts similarity index 100% rename from src/jagex2/datastruct/Linkable.ts rename to src/jagex/datastruct/Linkable.ts diff --git a/src/jagex2/io/BZip2.ts b/src/jagex/io/BZip2.ts similarity index 100% rename from src/jagex2/io/BZip2.ts rename to src/jagex/io/BZip2.ts diff --git a/src/jagex2/io/FileStream.ts b/src/jagex/io/FileStream.ts similarity index 99% rename from src/jagex2/io/FileStream.ts rename to src/jagex/io/FileStream.ts index 1f5605935b..7620f55015 100644 --- a/src/jagex2/io/FileStream.ts +++ b/src/jagex/io/FileStream.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import RandomAccessFile from '#lostcity/util/RandomAccessFile.js'; diff --git a/src/jagex2/io/Isaac.test.ts b/src/jagex/io/Isaac.test.ts similarity index 95% rename from src/jagex2/io/Isaac.test.ts rename to src/jagex/io/Isaac.test.ts index 0a1280ac47..76e0eafa31 100644 --- a/src/jagex2/io/Isaac.test.ts +++ b/src/jagex/io/Isaac.test.ts @@ -1,4 +1,4 @@ -import Isaac from '#jagex2/io/Isaac.js'; +import Isaac from '#jagex/io/Isaac.js'; describe('Isaac', () => { describe('seed(0, 0, 0, 0)', () => { diff --git a/src/jagex2/io/Isaac.ts b/src/jagex/io/Isaac.ts similarity index 100% rename from src/jagex2/io/Isaac.ts rename to src/jagex/io/Isaac.ts diff --git a/src/jagex2/io/Jagfile.test.ts b/src/jagex/io/Jagfile.test.ts similarity index 98% rename from src/jagex2/io/Jagfile.test.ts rename to src/jagex/io/Jagfile.test.ts index 3364f4aafe..af5e9b8a3a 100644 --- a/src/jagex2/io/Jagfile.test.ts +++ b/src/jagex/io/Jagfile.test.ts @@ -1,5 +1,5 @@ -import Jagfile, {genHash} from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile, {genHash} from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; describe('Jagfile', (): void => { describe('genHash', (): void => { diff --git a/src/jagex2/io/Jagfile.ts b/src/jagex/io/Jagfile.ts similarity index 95% rename from src/jagex2/io/Jagfile.ts rename to src/jagex/io/Jagfile.ts index 1b466f06fe..8bf3bba3ee 100644 --- a/src/jagex2/io/Jagfile.ts +++ b/src/jagex/io/Jagfile.ts @@ -1,5 +1,5 @@ -import BZip2 from '#jagex2/io/BZip2.js'; -import Packet from '#jagex2/io/Packet.js'; +import BZip2 from '#jagex/io/BZip2.js'; +import Packet from '#jagex/io/Packet.js'; export function genHash(name: string): number { let hash: number = 0; @@ -54,7 +54,7 @@ export default class Jagfile { this.data = new Uint8Array(src.data); this.unpacked = false; } else { - this.data = BZip2.decompress(src.data, unpackedSize, true); + this.data = BZip2.decompress(src.data.subarray(6), unpackedSize, true); src = new Packet(this.data); this.unpacked = true; } @@ -212,18 +212,23 @@ export default class Jagfile { const jag: Packet = Packet.alloc(5); jag.p3(buf.pos); if (compressWhole) { - buf = new Packet(BZip2.compress(buf.data, false, true)); + const sub = buf.data.subarray(0, buf.pos); + + const compressed = new Packet(BZip2.compress(sub, false, true)); + compressed.pos = compressed.data.length; + + buf.release(); + buf = compressed; } - if (compressWhole) { - jag.p3(buf.data.length); - jag.pdata(buf.data, 0, buf.data.length); - } else { - jag.p3(buf.pos); - jag.pdata(buf.data, 0, buf.pos); + + jag.p3(buf.pos); + jag.pdata(buf.data, 0, buf.pos); + + if (!compressWhole) { + buf.release(); } jag.save(path); - buf.release(); jag.release(); } diff --git a/src/jagex2/io/Packet.bench.ts b/src/jagex/io/Packet.bench.ts similarity index 82% rename from src/jagex2/io/Packet.bench.ts rename to src/jagex/io/Packet.bench.ts index 62c3a50acf..65b34b2d7d 100644 --- a/src/jagex2/io/Packet.bench.ts +++ b/src/jagex/io/Packet.bench.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { Bench } from 'tinybench'; const bench = new Bench(); @@ -12,7 +12,7 @@ bench.add('bitTest', (): void => { } }); -await bench.warmup(); +bench.warmup = true; await bench.run(); console.table(bench.table()); diff --git a/src/jagex2/io/Packet.test.ts b/src/jagex/io/Packet.test.ts similarity index 99% rename from src/jagex2/io/Packet.test.ts rename to src/jagex/io/Packet.test.ts index 566d50de3d..75e8dd196c 100644 --- a/src/jagex2/io/Packet.test.ts +++ b/src/jagex/io/Packet.test.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import forge from 'node-forge'; import fs from 'fs'; diff --git a/src/jagex2/io/Packet.ts b/src/jagex/io/Packet.ts similarity index 99% rename from src/jagex2/io/Packet.ts rename to src/jagex/io/Packet.ts index a4b2bf79bc..ed9ede984b 100644 --- a/src/jagex2/io/Packet.ts +++ b/src/jagex/io/Packet.ts @@ -6,8 +6,8 @@ import forge from 'node-forge'; import PrivateKey = forge.pki.rsa.PrivateKey; import BigInteger = forge.jsbn.BigInteger; -import LinkList from '#jagex2/datastruct/LinkList.js'; -import DoublyLinkable from '#jagex2/datastruct/DoublyLinkable.js'; +import LinkList from '#jagex/datastruct/LinkList.js'; +import DoublyLinkable from '#jagex/datastruct/DoublyLinkable.js'; import Environment from '#lostcity/util/Environment.js'; export default class Packet extends DoublyLinkable { diff --git a/src/jagex2/jstring/JString.test.ts b/src/jagex/jstring/JString.test.ts similarity index 96% rename from src/jagex2/jstring/JString.test.ts rename to src/jagex/jstring/JString.test.ts index 18a89da218..9e4e74a3a5 100644 --- a/src/jagex2/jstring/JString.test.ts +++ b/src/jagex/jstring/JString.test.ts @@ -1,4 +1,4 @@ -import {fromBase37, toBase37, toTitleCase} from '#jagex2/jstring/JString.js'; +import {fromBase37, toBase37, toTitleCase} from '#jagex/jstring/JString.js'; describe('JString', (): void => { describe('toBase37', (): void => { diff --git a/src/jagex2/jstring/JString.ts b/src/jagex/jstring/JString.ts similarity index 100% rename from src/jagex2/jstring/JString.ts rename to src/jagex/jstring/JString.ts diff --git a/src/jagex2/wordenc/WordPack.test.ts b/src/jagex/wordenc/WordPack.test.ts similarity index 91% rename from src/jagex2/wordenc/WordPack.test.ts rename to src/jagex/wordenc/WordPack.test.ts index 8a28dc7424..b5d77baefc 100644 --- a/src/jagex2/wordenc/WordPack.test.ts +++ b/src/jagex/wordenc/WordPack.test.ts @@ -1,5 +1,5 @@ -import Packet from '#jagex2/io/Packet.js'; -import WordPack from '#jagex2/wordenc/WordPack.js'; +import Packet from '#jagex/io/Packet.js'; +import WordPack from '#jagex/wordenc/WordPack.js'; describe('WordPack', (): void => { describe('unpack', (): void => { diff --git a/src/jagex2/wordenc/WordPack.ts b/src/jagex/wordenc/WordPack.ts similarity index 98% rename from src/jagex2/wordenc/WordPack.ts rename to src/jagex/wordenc/WordPack.ts index 76b7781ecc..5b1ff7a725 100644 --- a/src/jagex2/wordenc/WordPack.ts +++ b/src/jagex/wordenc/WordPack.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export default class WordPack { // prettier-ignore diff --git a/src/lostcity/app.ts b/src/lostcity/app.ts index 996cab5386..57ed529268 100644 --- a/src/lostcity/app.ts +++ b/src/lostcity/app.ts @@ -1,10 +1,10 @@ import fs from 'fs'; -import { startWeb } from '#lostcity/web.js'; +import { startManagementWeb, startWeb } from '#lostcity/web.js'; import World from '#lostcity/engine/World.js'; -import { packClient, packServer } from '#lostcity/cache/packall.js'; +import { packClient, packServer } from '#lostcity/pack/packall.js'; import TcpServer from '#lostcity/server/TcpServer.js'; import WSServer from '#lostcity/server/WSServer.js'; @@ -12,6 +12,7 @@ import WSServer from '#lostcity/server/WSServer.js'; import Environment from '#lostcity/util/Environment.js'; import { printError, printInfo } from '#lostcity/util/Logger.js'; import { updateCompiler } from '#lostcity/util/RuneScriptCompiler.js'; +import { collectDefaultMetrics, register } from 'prom-client'; if (Environment.BUILD_STARTUP_UPDATE) { await updateCompiler(); @@ -37,6 +38,10 @@ fs.mkdirSync('data/players', { recursive: true }); await World.start(); startWeb(); +startManagementWeb(); + +register.setDefaultLabels({nodeId: Environment.NODE_ID}); +collectDefaultMetrics({register}); const tcpServer = new TcpServer(); tcpServer.start(); diff --git a/src/lostcity/cache/config/CategoryType.ts b/src/lostcity/cache/config/CategoryType.ts index 9329736069..208d477fc8 100644 --- a/src/lostcity/cache/config/CategoryType.ts +++ b/src/lostcity/cache/config/CategoryType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; diff --git a/src/lostcity/cache/config/Component.test.ts b/src/lostcity/cache/config/Component.test.ts index c0ffbbbdee..9bca8fdb25 100644 --- a/src/lostcity/cache/config/Component.test.ts +++ b/src/lostcity/cache/config/Component.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import Component from '#lostcity/cache/config/Component.js'; diff --git a/src/lostcity/cache/config/Component.ts b/src/lostcity/cache/config/Component.ts index 2f5b88aef2..a7749563d1 100644 --- a/src/lostcity/cache/config/Component.ts +++ b/src/lostcity/cache/config/Component.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export default class Component { static TYPE_LAYER: number = 0; diff --git a/src/lostcity/cache/config/ConfigType.ts b/src/lostcity/cache/config/ConfigType.ts index b1bfdac6f3..cd6b39c47b 100644 --- a/src/lostcity/cache/config/ConfigType.ts +++ b/src/lostcity/cache/config/ConfigType.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export abstract class ConfigType { readonly id: number; diff --git a/src/lostcity/cache/config/DbRowType.ts b/src/lostcity/cache/config/DbRowType.ts index 6711ff7332..0cc05a3950 100644 --- a/src/lostcity/cache/config/DbRowType.ts +++ b/src/lostcity/cache/config/DbRowType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import DbTableType from '#lostcity/cache/config/DbTableType.js'; diff --git a/src/lostcity/cache/config/DbTableType.ts b/src/lostcity/cache/config/DbTableType.ts index 974f6c212c..77ca9eed5d 100644 --- a/src/lostcity/cache/config/DbTableType.ts +++ b/src/lostcity/cache/config/DbTableType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; diff --git a/src/lostcity/cache/config/EnumType.ts b/src/lostcity/cache/config/EnumType.ts index 2b2a207c9c..97bc195916 100644 --- a/src/lostcity/cache/config/EnumType.ts +++ b/src/lostcity/cache/config/EnumType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; diff --git a/src/lostcity/cache/config/FloType.ts b/src/lostcity/cache/config/FloType.ts index 1edb308980..1434d2c3f9 100644 --- a/src/lostcity/cache/config/FloType.ts +++ b/src/lostcity/cache/config/FloType.ts @@ -1,9 +1,9 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; export default class FloType extends ConfigType { static configNames: Map = new Map(); diff --git a/src/lostcity/cache/config/FontType.ts b/src/lostcity/cache/config/FontType.ts index 6357fe937f..68b7e80917 100644 --- a/src/lostcity/cache/config/FontType.ts +++ b/src/lostcity/cache/config/FontType.ts @@ -1,4 +1,4 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; export default class FontType { static CHAR_LOOKUP: number[] = []; diff --git a/src/lostcity/cache/config/HuntType.ts b/src/lostcity/cache/config/HuntType.ts index fd32a98542..e94914538d 100644 --- a/src/lostcity/cache/config/HuntType.ts +++ b/src/lostcity/cache/config/HuntType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; @@ -72,6 +72,16 @@ export default class HuntType extends ConfigType { return this.configs.length; } + public checkHuntCondition(value: number, condition: string, checkValue: number): boolean { + switch (condition) { + case '>': return value > checkValue; + case '<': return value < checkValue; + case '=': return value === checkValue; + case '!': return value !== checkValue; + } + return false; + } + // ---- type: HuntModeType = HuntModeType.OFF; checkVis: HuntVis = HuntVis.OFF; @@ -90,8 +100,9 @@ export default class HuntType extends ConfigType { checkLoc: number = -1; checkInv: number = -1; checkObjParam: number = -1; - checkInvMinQuantity: number = -1; - checkInvMaxQuantity: number = -1; + checkInvCondition: string = ''; + checkInvVal: number = -1; + checkVars: { varId: number; condition: string; val: number }[] = []; decode(code: number, dat: Packet): void { if (code === 1) { @@ -127,13 +138,15 @@ export default class HuntType extends ConfigType { } else if (code === 16) { this.checkInv = dat.g2(); this.checkObj = dat.g2(); - this.checkInvMinQuantity = dat.g4(); - this.checkInvMaxQuantity = dat.g4(); + this.checkInvCondition = dat.gjstr(); + this.checkInvVal = dat.g4(); } else if (code === 17) { this.checkInv = dat.g2(); this.checkObjParam = dat.g2(); - this.checkInvMinQuantity = dat.g4(); - this.checkInvMaxQuantity = dat.g4(); + this.checkInvCondition = dat.gjstr(); + this.checkInvVal = dat.g4(); + } else if (code > 17 && code < 21) { + this.checkVars.push({varId: dat.g2(), condition: dat.gjstr(), val: dat.g4()}); } else if (code === 250) { this.debugname = dat.gjstr(); } else { diff --git a/src/lostcity/cache/config/IdkType.ts b/src/lostcity/cache/config/IdkType.ts index 58fae76e2f..0e6b66f713 100644 --- a/src/lostcity/cache/config/IdkType.ts +++ b/src/lostcity/cache/config/IdkType.ts @@ -1,9 +1,9 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; export default class IdkType extends ConfigType { private static configNames: Map = new Map(); diff --git a/src/lostcity/cache/config/InvType.ts b/src/lostcity/cache/config/InvType.ts index 4ba18b6a55..dcafd40038 100644 --- a/src/lostcity/cache/config/InvType.ts +++ b/src/lostcity/cache/config/InvType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; diff --git a/src/lostcity/cache/config/LocType.ts b/src/lostcity/cache/config/LocType.ts index 6466da99c0..dde6afb87e 100644 --- a/src/lostcity/cache/config/LocType.ts +++ b/src/lostcity/cache/config/LocType.ts @@ -1,10 +1,12 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import { ParamHelper, ParamMap } from '#lostcity/cache/config/ParamHelper.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import { printFatalError } from '#lostcity/util/Logger.js'; +import kleur from 'kleur'; export default class LocType extends ConfigType { static configNames: Map = new Map(); @@ -182,6 +184,8 @@ export default class LocType extends ConfigType { } } else if (code === 60) { this.mapfunction = dat.g2(); + } else if (code === 61) { + this.category = dat.g2(); } else if (code === 62) { this.mirror = true; } else if (code === 64) { @@ -204,14 +208,12 @@ export default class LocType extends ConfigType { this.zoff = dat.g2s(); } else if (code === 73) { this.forcedecor = true; - } else if (code === 200) { - this.category = dat.g2(); } else if (code === 249) { this.params = ParamHelper.decodeParams(dat); } else if (code === 250) { this.debugname = dat.gjstr(); } else { - throw new Error(`Unrecognized loc config code: ${code}`); + printFatalError(`Unrecognized loc config code: ${code}\nThis error comes from the packed data being out of sync, try running ` + kleur.green().bold('npm run build') + ', then restarting this.'); } } } diff --git a/src/lostcity/cache/config/MesanimType.test.ts b/src/lostcity/cache/config/MesanimType.test.ts index 10d685abca..63a431391a 100644 --- a/src/lostcity/cache/config/MesanimType.test.ts +++ b/src/lostcity/cache/config/MesanimType.test.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MesanimType from '#lostcity/cache/config/MesanimType.js'; diff --git a/src/lostcity/cache/config/MesanimType.ts b/src/lostcity/cache/config/MesanimType.ts index e314b4e306..ab54625095 100644 --- a/src/lostcity/cache/config/MesanimType.ts +++ b/src/lostcity/cache/config/MesanimType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; diff --git a/src/lostcity/cache/config/NpcType.ts b/src/lostcity/cache/config/NpcType.ts index 0dfdcb12d7..82feae6359 100644 --- a/src/lostcity/cache/config/NpcType.ts +++ b/src/lostcity/cache/config/NpcType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import { ParamHelper, ParamMap } from '#lostcity/cache/config/ParamHelper.js'; @@ -8,7 +8,7 @@ import { ParamHelper, ParamMap } from '#lostcity/cache/config/ParamHelper.js'; import BlockWalk from '#lostcity/entity/BlockWalk.js'; import MoveRestrict from '#lostcity/entity/MoveRestrict.js'; import NpcMode from '#lostcity/entity/NpcMode.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import NpcStat from '#lostcity/entity/NpcStat.js'; export default class NpcType extends ConfigType { diff --git a/src/lostcity/cache/config/ObjType.ts b/src/lostcity/cache/config/ObjType.ts index 4ca6ae6d42..238a80a66c 100644 --- a/src/lostcity/cache/config/ObjType.ts +++ b/src/lostcity/cache/config/ObjType.ts @@ -1,12 +1,14 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import { ParamHelper, ParamMap } from '#lostcity/cache/config/ParamHelper.js'; import ParamType from '#lostcity/cache/config/ParamType.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import Environment from '#lostcity/util/Environment.js'; +import { printFatalError } from '#lostcity/util/Logger.js'; +import kleur from 'kleur'; export default class ObjType extends ConfigType { static configNames: Map = new Map(); @@ -60,6 +62,10 @@ export default class ObjType extends ConfigType { config.toCertificate(); } + if (config.dummyitem !== 0) { + config.tradeable = false; + } + if (!Environment.NODE_MEMBERS && config.members) { config.tradeable = false; config.op = null; @@ -173,7 +179,7 @@ export default class ObjType extends ConfigType { weight = 0; // in grams category = -1; dummyitem = 0; - tradeable = false; + tradeable = true; respawnrate = 100; // default to 1-minute params: ParamMap = new Map(); @@ -206,6 +212,8 @@ export default class ObjType extends ConfigType { this.wearpos = dat.g1(); } else if (code === 14) { this.wearpos2 = dat.g1(); + } else if (code === 15) { + this.tradeable = false; } else if (code === 16) { this.members = true; } else if (code === 23) { @@ -270,8 +278,6 @@ export default class ObjType extends ConfigType { } this.countobj[code - 100] = dat.g2(); this.countco[code - 100] = dat.g2(); - } else if (code === 200) { - this.tradeable = true; } else if (code === 201) { this.respawnrate = dat.g2(); } else if (code === 249) { @@ -279,7 +285,7 @@ export default class ObjType extends ConfigType { } else if (code === 250) { this.debugname = dat.gjstr(); } else { - throw new Error(`Unrecognized obj config code: ${code}`); + printFatalError(`Unrecognized obj config code: ${code}\nThis error comes from the packed data being out of sync, try running ` + kleur.green().bold('npm run build') + ', then restarting this.'); } } diff --git a/src/lostcity/cache/config/ParamHelper.ts b/src/lostcity/cache/config/ParamHelper.ts index 670feb0903..ec71a4f279 100644 --- a/src/lostcity/cache/config/ParamHelper.ts +++ b/src/lostcity/cache/config/ParamHelper.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export type ParamMap = Map; diff --git a/src/lostcity/cache/config/ParamType.ts b/src/lostcity/cache/config/ParamType.ts index 109ab78bd1..c7db4cded5 100644 --- a/src/lostcity/cache/config/ParamType.ts +++ b/src/lostcity/cache/config/ParamType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; diff --git a/src/lostcity/cache/config/SeqFrame.ts b/src/lostcity/cache/config/SeqFrame.ts index 05f046ac21..e89721753d 100644 --- a/src/lostcity/cache/config/SeqFrame.ts +++ b/src/lostcity/cache/config/SeqFrame.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; // partial frame class - only delays, not loading transforms export default class SeqFrame { diff --git a/src/lostcity/cache/config/SeqType.ts b/src/lostcity/cache/config/SeqType.ts index a4d9c89b4d..1a1583f9f8 100644 --- a/src/lostcity/cache/config/SeqType.ts +++ b/src/lostcity/cache/config/SeqType.ts @@ -1,10 +1,10 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import SeqFrame from '#lostcity/cache/config/SeqFrame.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; export default class SeqType extends ConfigType { private static configNames = new Map(); diff --git a/src/lostcity/cache/config/SpotanimType.ts b/src/lostcity/cache/config/SpotanimType.ts index 1a7d2bec20..401f4c81a7 100644 --- a/src/lostcity/cache/config/SpotanimType.ts +++ b/src/lostcity/cache/config/SpotanimType.ts @@ -1,9 +1,9 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; export default class SpotanimType extends ConfigType { private static configNames = new Map(); diff --git a/src/lostcity/cache/config/StructType.ts b/src/lostcity/cache/config/StructType.ts index 73faf89987..3d8fcd612f 100644 --- a/src/lostcity/cache/config/StructType.ts +++ b/src/lostcity/cache/config/StructType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import { ParamHelper, ParamHolder, ParamMap } from '#lostcity/cache/config/ParamHelper.js'; diff --git a/src/lostcity/cache/config/VarNpcType.ts b/src/lostcity/cache/config/VarNpcType.ts index d61eb56868..b402c2932f 100644 --- a/src/lostcity/cache/config/VarNpcType.ts +++ b/src/lostcity/cache/config/VarNpcType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; diff --git a/src/lostcity/cache/config/VarPlayerType.ts b/src/lostcity/cache/config/VarPlayerType.ts index 8e13bbf9bb..8a9c8cf434 100644 --- a/src/lostcity/cache/config/VarPlayerType.ts +++ b/src/lostcity/cache/config/VarPlayerType.ts @@ -1,10 +1,10 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import { printError } from '#lostcity/util/Logger.js'; export default class VarPlayerType extends ConfigType { diff --git a/src/lostcity/cache/config/VarSharedType.ts b/src/lostcity/cache/config/VarSharedType.ts index b940eb7226..53b0bc6a07 100644 --- a/src/lostcity/cache/config/VarSharedType.ts +++ b/src/lostcity/cache/config/VarSharedType.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { ConfigType } from '#lostcity/cache/config/ConfigType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; import { printError } from '#lostcity/util/Logger.js'; diff --git a/src/lostcity/cache/graphics/AnimBase.ts b/src/lostcity/cache/graphics/AnimBase.ts index f6115bc3c3..efac147a94 100644 --- a/src/lostcity/cache/graphics/AnimBase.ts +++ b/src/lostcity/cache/graphics/AnimBase.ts @@ -1,5 +1,5 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; export default class AnimBase { static instances: AnimBase[] = []; diff --git a/src/lostcity/cache/graphics/AnimFrame.ts b/src/lostcity/cache/graphics/AnimFrame.ts index f3cb6be719..5f881ebe62 100644 --- a/src/lostcity/cache/graphics/AnimFrame.ts +++ b/src/lostcity/cache/graphics/AnimFrame.ts @@ -1,5 +1,5 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; import AnimBase from '#lostcity/cache/graphics/AnimBase.js'; import { printError } from '#lostcity/util/Logger.js'; diff --git a/src/lostcity/cache/graphics/Model.ts b/src/lostcity/cache/graphics/Model.ts index 4598637033..f4e73429e4 100644 --- a/src/lostcity/cache/graphics/Model.ts +++ b/src/lostcity/cache/graphics/Model.ts @@ -1,5 +1,5 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; class Metadata { vertexCount: number = 0; diff --git a/src/lostcity/cache/graphics/Pix.ts b/src/lostcity/cache/graphics/Pix.ts index 2601040f09..9e452f57c5 100644 --- a/src/lostcity/cache/graphics/Pix.ts +++ b/src/lostcity/cache/graphics/Pix.ts @@ -1,8 +1,8 @@ -import Jimp from 'jimp'; +import { Jimp } from 'jimp'; import kleur from 'kleur'; -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; import { printError } from '#lostcity/util/Logger.js'; // O(sqrt(n)) @@ -95,7 +95,7 @@ export default class Pix { return new Pix(pixels, palette, width, height, cropLeft, cropTop, cropRight, cropBottom, pixelOrder); } - static unpackJagToPng(jag: Jagfile, name: string, sheetWidth: number = 0, sheetHeight: number = 0, preferHorizontal: boolean = true): Jimp | null { + static unpackJagToPng(jag: Jagfile, name: string, sheetWidth: number = 0, sheetHeight: number = 0, preferHorizontal: boolean = true) { const all = []; for (let i = 0; i < 1000; i++) { @@ -152,7 +152,11 @@ export default class Pix { const cellWidth = all[0].width; const cellHeight = all[0].height; - const sheet = new Jimp(sheetWidth * cellWidth, sheetHeight * cellHeight, 0xff00ffff).colorType(2); + const sheet = new Jimp({ + width: sheetWidth * cellWidth, + height: sheetHeight * cellHeight, + color: 0xff00ffff + }); for (let index = 0; index < count; index++) { const pix = all[index]; @@ -161,7 +165,15 @@ export default class Pix { const x = index % sheetWidth; const y = Math.floor(index / sheetWidth); - sheet.blit(img, x * cellWidth, y * cellHeight, 0, 0, cellWidth, cellHeight); + sheet.blit({ + src: img, + x: x * cellWidth, + y: y * cellHeight, + srcX: 0, + srcY: 0, + srcW: cellWidth, + srcH: cellHeight + }); } return sheet; @@ -201,8 +213,12 @@ export default class Pix { } } - packPng(): Jimp { - const img = new Jimp(this.width, this.height, 0xff00ffff).colorType(2); + packPng() { + const img = new Jimp({ + width: this.width, + height: this.height, + color: 0xff00ffff + }); // if we could perform a memcpy this would be <0.05ms instead of 1-2ms if (this.pixelOrder === 0) { diff --git a/src/lostcity/cache/packall.ts b/src/lostcity/cache/packall.ts deleted file mode 100644 index 254d990ee6..0000000000 --- a/src/lostcity/cache/packall.ts +++ /dev/null @@ -1,61 +0,0 @@ -import fs from 'fs'; -import child_process from 'child_process'; - -import { packServerInterface } from '#lostcity/cache/packinterface/PackServer.js'; -import { packServerMap } from '#lostcity/cache/packmap/PackServer.js'; -import { generateServerSymbols } from '#lostcity/cache/symbols.js'; -import { packConfigs } from '#lostcity/cache/packconfig/PackShared.js'; -import { packWorldmap } from '#lostcity/cache/packmap/Worldmap.js'; -import Environment from '#lostcity/util/Environment.js'; -import { revalidatePack } from '#lostcity/util/PackFile.js'; - -import { packClientInterface } from '#lostcity/cache/packinterface/PackClient.js'; -import { packClientMap } from '#lostcity/cache/packmap/PackClient.js'; -import { packClientModel } from '#lostcity/cache/packgraphics/pack.js'; -import { packClientMusic } from '#lostcity/cache/packmidi/pack.js'; -import { packClientSound } from '#lostcity/cache/packsound/pack.js'; -import { packClientWordenc } from '#lostcity/cache/packchat/pack.js'; -import { packClientTitle } from '#lostcity/cache/packsprite/title/pack.js'; -import { packClientTexture } from '#lostcity/cache/packsprite/textures/pack.js'; -import { packClientMedia } from '#lostcity/cache/packsprite/media/pack.js'; -import { CrcBuffer } from '#lostcity/server/CrcTable.js'; - -export async function packServer() { - if (!fs.existsSync('RuneScriptCompiler.jar')) { - throw new Error('The RuneScript compiler is missing and the build process cannot continue.'); - } - - revalidatePack(); - packConfigs(); - packServerInterface(); - - packServerMap(); - await packWorldmap(); - - generateServerSymbols(); - - try { - child_process.execSync(`"${Environment.BUILD_JAVA_PATH}" -jar RuneScriptCompiler.jar`, { stdio: 'inherit' }); - } catch (err) { - throw new Error('Failed to compile scripts.'); - } - - fs.writeFileSync('data/pack/server/lastbuild.pack', ''); -} - -export async function packClient() { - await packClientTitle(); - packConfigs(); - packClientInterface(); - await packClientMedia(); - packClientModel(); - await packClientTexture(); - packClientWordenc(); - packClientSound(); - - packClientMap(); - packClientMusic(); - - fs.writeFileSync('data/pack/client/crc', CrcBuffer.data); - fs.writeFileSync('data/pack/client/lastbuild.pack', ''); -} diff --git a/src/lostcity/cache/wordenc/WordEnc.test.ts b/src/lostcity/cache/wordenc/WordEnc.test.ts index e92a9f50fc..71fad26bce 100644 --- a/src/lostcity/cache/wordenc/WordEnc.test.ts +++ b/src/lostcity/cache/wordenc/WordEnc.test.ts @@ -1,10 +1,10 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import fs from 'fs'; import WordEnc from '#lostcity/cache/wordenc/WordEnc.js'; -import WordPack from '#jagex2/wordenc/WordPack.js'; -import { packClientWordenc } from '#lostcity/cache/packchat/pack.js'; +import WordPack from '#jagex/wordenc/WordPack.js'; +import { packClientWordenc } from '#lostcity/pack/chat/pack.js'; /** * TODO: Remove race condition in how files are written to data/pack/client/wordenc diff --git a/src/lostcity/cache/wordenc/WordEnc.ts b/src/lostcity/cache/wordenc/WordEnc.ts index a300214932..2b1c5ac859 100644 --- a/src/lostcity/cache/wordenc/WordEnc.ts +++ b/src/lostcity/cache/wordenc/WordEnc.ts @@ -1,12 +1,12 @@ import fs from 'fs'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import WordEncFragments from '#lostcity/cache/wordenc/WordEncFragments.js'; import WordEncBadWords from '#lostcity/cache/wordenc/WordEncBadWords.js'; import WordEncDomains from '#lostcity/cache/wordenc/WordEncDomains.js'; import WordEncTlds from '#lostcity/cache/wordenc/WordEncTlds.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export default class WordEnc { static PERIOD = new Uint16Array( @@ -35,7 +35,7 @@ export default class WordEnc { private static whitelist = ['cook', "cook's", 'cooks', 'seeks', 'sheet']; - static async load(dir: string): Promise { + static load(dir: string): void { if (!fs.existsSync(`${dir}/client/wordenc`)) { return; } diff --git a/src/lostcity/engine/GameMap.ts b/src/lostcity/engine/GameMap.ts index e0784e57bb..2eb7c15bc4 100644 --- a/src/lostcity/engine/GameMap.ts +++ b/src/lostcity/engine/GameMap.ts @@ -3,7 +3,7 @@ import fs from 'fs'; import {CollisionFlag, CollisionType, LocAngle, LocLayer} from '@2004scape/rsmod-pathfinder'; import * as rsmod from '@2004scape/rsmod-pathfinder'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import NpcType from '#lostcity/cache/config/NpcType.js'; import ObjType from '#lostcity/cache/config/ObjType.js'; diff --git a/src/lostcity/engine/Login.ts b/src/lostcity/engine/Login.ts index c8ada55536..503123b373 100644 --- a/src/lostcity/engine/Login.ts +++ b/src/lostcity/engine/Login.ts @@ -1,10 +1,9 @@ import { Worker as NodeWorker } from 'worker_threads'; -import Isaac from '#jagex2/io/Isaac.js'; -import Packet from '#jagex2/io/Packet.js'; +import Isaac from '#jagex/io/Isaac.js'; +import Packet from '#jagex/io/Packet.js'; import World from '#lostcity/engine/World.js'; -import {changeNpcCollision} from '#lostcity/engine/GameMap.js'; import Player from '#lostcity/entity/Player.js'; @@ -16,7 +15,7 @@ import { CrcBuffer32 } from '#lostcity/server/CrcTable.js'; import Environment from '#lostcity/util/Environment.js'; class Login { - loginThread: Worker | NodeWorker = createWorker(Environment.STANDALONE_BUNDLE ? 'LoginThread.js' : './src/lostcity/server/LoginThread.ts'); + loginThread: Worker | NodeWorker = createWorker(Environment.STANDALONE_BUNDLE ? 'LoginThread.js' : './lostcity/server/LoginThread.ts'); loginRequests: Map = new Map(); logoutRequests: Set = new Set(); @@ -40,7 +39,7 @@ class Login { } } - async readIn(socket: ClientSocket, data: Packet) { + readIn(socket: ClientSocket, data: Packet) { const opcode = data.g1(); // todo: reconnect (opcode 18) @@ -97,6 +96,8 @@ class Login { save: save.data.subarray(0, save.pos) }); save.release(); + + this.logoutRequests.delete(player.username37); } autosave(player: Player) { @@ -170,21 +171,6 @@ class Login { World.addPlayer(player); break; } - case 'logoutreply': { - const { username } = msg; - - const player = World.getPlayerByUsername(username); - if (player) { - World.gameMap.getZone(player.x, player.z, player.level).leave(player); - World.players.remove(player.pid); - changeNpcCollision(player.width, player.x, player.z, player.level, false); - player.pid = -1; - player.terminate(); - - this.logoutRequests.delete(player.username37); - } - break; - } default: throw new Error('Unknown message type: ' + msg.type); } diff --git a/src/lostcity/engine/World.ts b/src/lostcity/engine/World.ts index e5bb89cb60..3932bc5395 100644 --- a/src/lostcity/engine/World.ts +++ b/src/lostcity/engine/World.ts @@ -4,12 +4,12 @@ import { Worker as NodeWorker } from 'worker_threads'; // deps import kleur from 'kleur'; -// jagex2 -import LinkList from '#jagex2/datastruct/LinkList.js'; +// jagex +import LinkList from '#jagex/datastruct/LinkList.js'; -import { fromBase37, toBase37 } from '#jagex2/jstring/JString.js'; +import { fromBase37, toBase37 } from '#jagex/jstring/JString.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; // lostcity import CategoryType from '#lostcity/cache/config/CategoryType.js'; @@ -46,8 +46,11 @@ import ScriptProvider from '#lostcity/engine/script/ScriptProvider.js'; import ScriptRunner from '#lostcity/engine/script/ScriptRunner.js'; import ScriptState from '#lostcity/engine/script/ScriptState.js'; import ServerTriggerType from '#lostcity/engine/script/ServerTriggerType.js'; - import Zone from '#lostcity/engine/zone/Zone.js'; +import PlayerRenderer from '#lostcity/engine/renderer/PlayerRenderer.js'; +import NpcRenderer from '#lostcity/engine/renderer/NpcRenderer.js'; + +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; import BlockWalk from '#lostcity/entity/BlockWalk.js'; import Loc from '#lostcity/entity/Loc.js'; @@ -76,9 +79,11 @@ import { FriendsServerOpcodes } from '#lostcity/server/FriendServer.js'; import Environment from '#lostcity/util/Environment.js'; import { printDebug, printError, printInfo } from '#lostcity/util/Logger.js'; import { createWorker } from '#lostcity/util/WorkerFactory.js'; +import HuntModeType from '#lostcity/entity/hunt/HuntModeType.js'; +import { trackCycleBandwidthInBytes, trackCycleBandwidthOutBytes, trackCycleClientInTime, trackCycleClientOutTime, trackCycleLoginTime, trackCycleLogoutTime, trackCycleNpcTime, trackCyclePlayerTime, trackCycleTime, trackCycleWorldTime, trackCycleZoneTime, trackNpcCount, trackPlayerCount } from '#lostcity/prometheus.js'; class World { - private friendThread: Worker | NodeWorker = createWorker(Environment.STANDALONE_BUNDLE ? 'FriendThread.js' : './src/lostcity/server/FriendThread.ts'); + private friendThread: Worker | NodeWorker = createWorker(Environment.STANDALONE_BUNDLE ? 'FriendThread.js' : './lostcity/server/FriendThread.ts'); private devThread: Worker | NodeWorker | null = null; private static readonly PLAYERS: number = 2048; @@ -106,11 +111,15 @@ class World { readonly newPlayers: Set; // players joining at the end of this tick readonly players: PlayerList; readonly npcs: NpcList; + readonly playerGrid: Map; // store player coords for player_info for fast lookup // zones readonly zonesTracking: Map>; readonly queue: LinkList; + readonly playerRenderer: PlayerRenderer; + readonly npcRenderer: NpcRenderer; + // debug data readonly lastCycleStats: number[]; readonly cycleStats: number[]; @@ -129,8 +138,11 @@ class World { this.newPlayers = new Set(); this.players = new PlayerList(World.PLAYERS - 1); this.npcs = new NpcList(World.NPCS - 1); + this.playerGrid = new Map(); this.zonesTracking = new Map(); this.queue = new LinkList(); + this.playerRenderer = new PlayerRenderer(); + this.npcRenderer = new NpcRenderer(); this.lastCycleStats = new Array(12).fill(0); this.cycleStats = new Array(12).fill(0); @@ -395,12 +407,12 @@ class World { } if (startCycle) { - await this.cycle(); + this.cycle(); } } private createDevThread() { - this.devThread = createWorker('./src/lostcity/server/DevThread.ts'); + this.devThread = createWorker('./lostcity/server/DevThread.ts'); if (this.devThread instanceof NodeWorker) { this.devThread.on('message', msg => { @@ -413,6 +425,14 @@ class World { this.broadcastMes(msg.error.replaceAll('data/src/scripts/', '')); this.broadcastMes('Check the console for more information.'); } + } else if (msg.type === 'dev_progress') { + if (msg.broadcast) { + console.log(msg.broadcast); + + this.broadcastMes(msg.broadcast); + } else if (msg.text) { + console.log(msg.text); + } } }); @@ -435,7 +455,7 @@ class World { } } - async cycle(continueCycle: boolean = true): Promise { + cycle(continueCycle: boolean = true): void { try { const start: number = Date.now(); @@ -450,7 +470,7 @@ class World { // - resume active script // - process packets // - process pathfinding/following request - await this.processPlayerSetup(); + this.processPlayerSetup(); // npc processing (if npc is not busy) // - resume suspended script @@ -470,13 +490,13 @@ class World { // - interactions // - movement // - close interface if attempting to logout - await this.processPlayers(); + this.processPlayers(); // player logout - await this.processLogouts(); + this.processLogouts(); // player login, good spot for it (before packets so they immediately load but after processing so nothing hits them) - await this.processLogins(); + this.processLogins(); // process zones // - build list of active zones around players @@ -484,10 +504,12 @@ class World { // - compute shared buffer this.processZones(); - // process movement directions + // process player & npc update info // - convert player movements + // - compute player info // - convert npc movements - this.processMovementDirections(); + // - compute npc info + this.processInfo(); // client output // - map update @@ -498,7 +520,7 @@ class World { // - stat changes // - afk zones changes // - flush packets - await this.processClientsOut(); + this.processClientsOut(); // cleanup // - reset zones @@ -517,7 +539,7 @@ class World { // server shutdown if (this.shutdownTick > -1 && tick >= this.shutdownTick) { - await this.processShutdown(); + this.processShutdown(); } if (tick % World.PLAYER_SAVERATE === 0 && tick > 0) { @@ -525,9 +547,10 @@ class World { this.savePlayers(); } - this.currentTick++; this.cycleStats[WorldStat.CYCLE] = Date.now() - start; + // ---- + this.lastCycleStats[WorldStat.CYCLE] = this.cycleStats[WorldStat.CYCLE]; this.lastCycleStats[WorldStat.WORLD] = this.cycleStats[WorldStat.WORLD]; this.lastCycleStats[WorldStat.CLIENT_IN] = this.cycleStats[WorldStat.CLIENT_IN]; @@ -541,14 +564,34 @@ class World { this.lastCycleStats[WorldStat.BANDWIDTH_IN] = this.cycleStats[WorldStat.BANDWIDTH_IN]; this.lastCycleStats[WorldStat.BANDWIDTH_OUT] = this.cycleStats[WorldStat.BANDWIDTH_OUT]; - if (continueCycle) { - setTimeout(this.cycle.bind(this), this.tickRate - this.cycleStats[WorldStat.CYCLE]); + // push stats to prometheus + // todo: lock this behind a feature flag? most users may never use this feature + trackPlayerCount.set(this.getTotalPlayers()); + trackNpcCount.set(this.getTotalNpcs()); + + trackCycleTime.observe(this.cycleStats[WorldStat.CYCLE]); + trackCycleWorldTime.observe(this.cycleStats[WorldStat.WORLD]); + trackCycleClientInTime.observe(this.cycleStats[WorldStat.CLIENT_IN]); + trackCycleClientOutTime.observe(this.cycleStats[WorldStat.CLIENT_OUT]); + trackCycleNpcTime.observe(this.cycleStats[WorldStat.NPC]); + trackCyclePlayerTime.observe(this.cycleStats[WorldStat.PLAYER]); + trackCycleZoneTime.observe(this.cycleStats[WorldStat.ZONE]); + trackCycleLoginTime.observe(this.cycleStats[WorldStat.LOGIN]); + trackCycleLogoutTime.observe(this.cycleStats[WorldStat.LOGOUT]); + + trackCycleBandwidthInBytes.inc(this.cycleStats[WorldStat.BANDWIDTH_IN]); + trackCycleBandwidthOutBytes.inc(this.cycleStats[WorldStat.BANDWIDTH_OUT]); + + if (Environment.NODE_DEBUG_PROFILE) { + printDebug(`| [tick ${this.currentTick}; ${this.cycleStats[WorldStat.CYCLE]}/${this.tickRate}ms] | ${this.getTotalPlayers()} players | ${this.getTotalNpcs()} npcs | ${this.gameMap.getTotalZones()} zones | ${this.gameMap.getTotalLocs()} locs | ${this.gameMap.getTotalObjs()} objs |`); + printDebug(`| ${this.cycleStats[WorldStat.WORLD]}ms world | ${this.cycleStats[WorldStat.CLIENT_IN]}ms client in | ${this.cycleStats[WorldStat.NPC]}ms npcs | ${this.cycleStats[WorldStat.PLAYER]}ms players | ${this.cycleStats[WorldStat.LOGOUT]}ms logout | ${this.cycleStats[WorldStat.LOGIN]}ms login | ${this.cycleStats[WorldStat.ZONE]}ms zones | ${this.cycleStats[WorldStat.CLIENT_OUT]}ms client out | ${this.cycleStats[WorldStat.CLEANUP]}ms cleanup |`); + printDebug('----'); } - if (Environment.NODE_DEBUG_PROFILER) { - printDebug(`tick ${this.currentTick} took ${this.cycleStats[WorldStat.CYCLE]}ms: ${this.getTotalPlayers()} players`); - printDebug(`${this.cycleStats[WorldStat.WORLD]} ms world | ${this.cycleStats[WorldStat.CLIENT_IN]} ms client in | ${this.cycleStats[WorldStat.NPC]} ms npcs | ${this.cycleStats[WorldStat.PLAYER]} ms players | ${this.cycleStats[WorldStat.LOGOUT]} ms logout | ${this.cycleStats[WorldStat.LOGIN]} ms login | ${this.cycleStats[WorldStat.ZONE]} ms zones | ${this.cycleStats[WorldStat.CLIENT_OUT]} ms client out | ${this.cycleStats[WorldStat.CLEANUP]} ms cleanup`); - printDebug('----'); + this.currentTick++; + + if (continueCycle) { + setTimeout(this.cycle.bind(this), this.tickRate - this.cycleStats[WorldStat.CYCLE]); } } catch (err) { if (err instanceof Error) { @@ -558,7 +601,7 @@ class World { printError('Removing all players...'); for (const player of this.players) { - await this.removePlayer(player); + this.removePlayer(player); } // TODO inform Friends server that the world has gone offline @@ -606,48 +649,36 @@ class World { } } - // - npc spawn scripts + // - npc ai_spawn scripts + // - npc hunt players if not busy for (const npc of this.npcs) { - if (!npc.updateLifeCycle(tick)) { + if (!npc.checkLifeCycle(tick)) { continue; } - try { - if (npc.lifecycle === EntityLifeCycle.RESPAWN) { - this.addNpc(npc, -1, false); - } else if (npc.lifecycle === EntityLifeCycle.DESPAWN) { - this.removeNpc(npc, -1); - } - } catch (err) { - // there was an error adding or removing them, try again next tick... - // ex: server is full on npc IDs (did we have a leak somewhere?) and we don't want to re-use the last ID (syncing related) - if (npc.lifecycle === EntityLifeCycle.RESPAWN) { - printError('[World] An unhandled error occurred while respawning a NPC'); - } else if (npc.lifecycle === EntityLifeCycle.DESPAWN) { - printError('[World] An unhandled error occurred while despawning a NPC'); + // check if spawned last tick + if (npc.lastLifecycleTick === tick - 1 && npc.lifecycle !== EntityLifeCycle.FOREVER) { + const type = NpcType.get(npc.type); + const script = ScriptProvider.getByTrigger(ServerTriggerType.AI_SPAWN, type.id, type.category); + if (script) { + npc.executeScript(ScriptRunner.init(script, npc)); } - - printError(`[World] NPC type:${npc.type} lifecycle:${npc.lifecycle} ID:${npc.nid}`); - console.error(err); - - npc.setLifeCycle(this.currentTick + 1); // retry next tick } - } - - // - npc hunt - for (const npc of this.npcs) { - if (!npc.checkLifeCycle(tick) || npc.delayed()) { + if (npc.delayed()) { continue; } - if (npc.huntMode !== -1) { - npc.huntAll(); + const hunt = HuntType.get(npc.huntMode); + if (hunt && hunt.type === HuntModeType.PLAYER) { + npc.huntAll(); + } } + } this.cycleStats[WorldStat.WORLD] = Date.now() - start; } - private async processPlayerSetup(): Promise { + private processPlayerSetup(): void { const start: number = Date.now(); this.cycleStats[WorldStat.BANDWIDTH_IN] = 0; @@ -672,6 +703,7 @@ class World { } if (isNetworkPlayer(player) && player.decodeIn()) { + const followingPlayer = (player.targetOp === ServerTriggerType.APPLAYER3 || player.targetOp === ServerTriggerType.OPPLAYER3); if (player.userPath.length > 0 || player.opcalled) { if (player.delayed()) { player.unsetMapFlag(); @@ -680,15 +712,15 @@ class World { if ((!player.target || player.target instanceof Loc || player.target instanceof Obj) && player.faceEntity !== -1) { player.faceEntity = -1; - player.mask |= Player.FACE_ENTITY; + player.masks |= InfoProt.PLAYER_FACE_ENTITY.id; } if (player.busy() || !player.opcalled) { player.moveClickRequest = true; } - if (player.opcalled && (player.userPath.length === 0 || !Environment.NODE_CLIENT_ROUTEFINDER)) { - player.pathToPathingTarget(); + if (!followingPlayer && player.opcalled && (player.userPath.length === 0 || !Environment.NODE_CLIENT_ROUTEFINDER)) { + player.pathToTarget(); continue; } @@ -699,7 +731,7 @@ class World { } } - if (player.target instanceof Player && (player.targetOp === ServerTriggerType.APPLAYER3 || player.targetOp === ServerTriggerType.OPPLAYER3)) { + if (player.target instanceof Player && followingPlayer) { if (CoordGrid.distanceToSW(player, player.target) <= 25) { player.pathToPathingTarget(); } else { @@ -709,7 +741,7 @@ class World { } } catch (err) { console.error(err); - await this.removePlayer(player); + this.removePlayer(player); } } @@ -730,28 +762,58 @@ class World { if (npc.timerInterval !== 0) { npc.timerClock++; } - if (!npc.checkLifeCycle(this.currentTick)) { - continue; + if (npc.checkLifeCycle(this.currentTick)) { + if (npc.delayed()) { + npc.delay--; + } + if (!npc.delayed()) { + // - resume suspended script + if (npc.activeScript && npc.activeScript.execution === ScriptState.NPC_SUSPENDED) { + npc.executeScript(npc.activeScript); + } + } } - - if (npc.delayed()) { - npc.delay--; + + // - respawn + if (npc.updateLifeCycle(this.currentTick)) { + try { + if (npc.lifecycle === EntityLifeCycle.RESPAWN) { + this.addNpc(npc, -1, false); + } else if (npc.lifecycle === EntityLifeCycle.DESPAWN) { + this.removeNpc(npc, -1); + } + } catch (err) { + // there was an error adding or removing them, try again next tick... + // ex: server is full on npc IDs (did we have a leak somewhere?) and we don't want to re-use the last ID (syncing related) + if (npc.lifecycle === EntityLifeCycle.RESPAWN) { + printError('[World] An unhandled error occurred while respawning a NPC'); + } else if (npc.lifecycle === EntityLifeCycle.DESPAWN) { + printError('[World] An unhandled error occurred while despawning a NPC'); + } + + printError(`[World] NPC type:${npc.type} lifecycle:${npc.lifecycle} ID:${npc.nid}`); + console.error(err); + + npc.setLifeCycle(this.currentTick + 1); // retry next tick + } } if (npc.delayed()) { continue; } - // - resume suspended script - if (npc.activeScript && npc.activeScript.execution === ScriptState.NPC_SUSPENDED) { - npc.executeScript(npc.activeScript); - } - if (!npc.checkLifeCycle(this.currentTick)) { // if the npc just despawned then don't do anything else. continue; } + // - hunt npc/obj/loc + if (npc.huntMode !== -1) { + const hunt = HuntType.get(npc.huntMode); + if (hunt && hunt.type !== HuntModeType.PLAYER) { + npc.huntAll(); + } + } // - stat regen npc.processRegen(); // - timer @@ -779,7 +841,7 @@ class World { // - interactions // - movement // - close interface if attempting to logout - private async processPlayers(): Promise { + private processPlayers(): void { const start: number = Date.now(); for (const player of this.players) { try { @@ -796,7 +858,7 @@ class World { // - movement player.processInteraction(); - if ((player.mask & Player.EXACT_MOVE) == 0) { + if ((player.masks & InfoProt.PLAYER_EXACT_MOVE.id) == 0) { player.validateDistanceWalked(); } @@ -814,13 +876,13 @@ class World { } } catch (err) { console.error(err); - await this.removePlayer(player); + this.removePlayer(player); } } this.cycleStats[WorldStat.PLAYER] = Date.now() - start; } - private async processLogouts(): Promise { + private processLogouts(): void { const start: number = Date.now(); for (const player of this.players) { if (Environment.NODE_SOCKET_TIMEOUT && this.currentTick - player.lastResponse >= World.TIMEOUT_LOGOUT_TICKS) { @@ -856,7 +918,7 @@ class World { } if (player.logoutRequested) { - await this.removePlayer(player); + this.removePlayer(player); } } else { player.messageGame('[DEBUG]: Waiting for queue to empty before logging out.'); @@ -865,7 +927,7 @@ class World { this.cycleStats[WorldStat.LOGOUT] = Date.now() - start; } - private async processLogins(): Promise { + private processLogins(): void { const start: number = Date.now(); player: for (const player of this.newPlayers) { for (const other of this.players) { @@ -924,13 +986,8 @@ class World { private processZones(): void { const start: number = Date.now(); const tick: number = this.currentTick; - const zones: Set | undefined = this.zonesTracking.get(tick); - if (typeof zones !== 'undefined') { - // - loc/obj despawn/respawn - for (const zone of zones) { - zone.tick(tick); - } - } + // - loc/obj despawn/respawn + this.zonesTracking.get(tick)?.forEach(zone => zone.tick(tick)); // - build list of active zones around players // - compute shared buffer this.computeSharedEvents(); @@ -938,15 +995,28 @@ class World { } // - convert player movements + // - compute player info // - convert npc movements - private processMovementDirections(): void { + // - compute npc info + private processInfo(): void { // TODO: benchmark this? for (const player of this.players) { player.convertMovementDir(); + + const grid = this.playerGrid; + const coord = CoordGrid.packCoord(player.level, player.x, player.z); + const players = grid.get(coord) ?? []; + players.push(player); + if (!grid.has(coord)) { + grid.set(coord, players); + } + + this.playerRenderer.computeInfo(player); } for (const npc of this.npcs) { npc.convertMovementDir(); + this.npcRenderer.computeInfo(npc); } } @@ -958,7 +1028,7 @@ class World { // - stat changes // - afk zones changes // - flush packets - private async processClientsOut(): Promise { + private processClientsOut(): void { const start: number = Date.now(); this.cycleStats[WorldStat.BANDWIDTH_OUT] = 0; // reset bandwidth counter @@ -972,9 +1042,9 @@ class World { // - map update player.updateMap(); // - player info - player.updatePlayers(); + player.updatePlayers(this.playerRenderer); // - npc info - player.updateNpcs(); + player.updateNpcs(this.npcRenderer); // - zone updates player.updateZones(); // - inv changes @@ -988,7 +1058,7 @@ class World { player.encodeOut(); } catch (err) { console.error(err); - await this.removePlayer(player); + this.removePlayer(player); } } this.cycleStats[WorldStat.CLIENT_OUT] = Date.now() - start; @@ -1000,19 +1070,14 @@ class World { // - reset invs private processCleanup(): void { const start: number = Date.now(); - const tick: number = this.currentTick; // - reset zones - const zones: Set | undefined = this.zonesTracking.get(tick); - if (typeof zones !== 'undefined') { - for (const zone of zones) { - zone.reset(); - } - } + this.zonesTracking.get(tick)?.forEach(zone => zone.reset()); this.zonesTracking.delete(tick); // - reset players + this.playerRenderer.removeTemporary(); for (const player of this.players) { player.resetEntity(false); @@ -1027,6 +1092,7 @@ class World { } // - reset npcs + this.npcRenderer.removeTemporary(); for (const npc of this.npcs) { if (!npc.checkLifeCycle(tick)) { continue; @@ -1072,6 +1138,9 @@ class World { } } } + + this.playerGrid.clear(); + this.cycleStats[WorldStat.CLEANUP] = Date.now() - start; } @@ -1087,7 +1156,7 @@ class World { }); } - private async processShutdown(): Promise { + private processShutdown(): void { const duration: number = this.currentTick - this.shutdownTick; // how long have we been trying to shutdown const online: number = this.getTotalPlayers(); @@ -1118,7 +1187,7 @@ class World { // if we've exceeded 24000 ticks then we *really* need to shut down now if (duration > World.SHUTDOWN_TICKS) { for (const player of this.players) { - await this.removePlayer(player); + this.removePlayer(player); } this.tickRate = World.NORMAL_TICKRATE; @@ -1174,9 +1243,7 @@ class World { zones.add(zone); } } - for (const zoneIndex of zones) { - this.gameMap.getZoneIndex(zoneIndex).computeShared(); - } + zones.forEach(zoneIndex => this.gameMap.getZoneIndex(zoneIndex).computeShared()); } addNpc(npc: Npc, duration: number, firstSpawn: boolean = true): void { @@ -1221,8 +1288,12 @@ class World { break; } + this.npcRenderer.removePermanent(npc.nid); + if (npc.lifecycle === EntityLifeCycle.DESPAWN) { this.npcs.remove(npc.nid); + npc.nid = -1; + npc.uid = -1; } else if (npc.lifecycle === EntityLifeCycle.RESPAWN) { npc.setLifeCycle(this.currentTick + adjustedDuration); } @@ -1241,15 +1312,11 @@ class World { } trackZone(tick: number, zone: Zone): void { - let zones: Set; - const active: Set | undefined = this.zonesTracking.get(tick); - if (!active) { - zones = new Set(); - } else { - zones = active; + const tracking: Map> = this.zonesTracking; + const zones: Set = (tracking.get(tick) ?? new Set()).add(zone); + if (!tracking.has(tick)) { + tracking.set(tick, zones); } - zones.add(zone); - this.zonesTracking.set(tick, zones); } addLoc(loc: Loc, duration: number): void { @@ -1370,7 +1437,7 @@ class World { // ---- - async readIn(socket: ClientSocket, stream: Packet): Promise { + readIn(socket: ClientSocket, stream: Packet): void { while (stream.available > 0) { const start = stream.pos; let opcode = stream.g1(); @@ -1469,7 +1536,7 @@ class World { }); } - async removePlayer(player: Player): Promise { + removePlayer(player: Player): void { if (player.pid === -1) { return; } @@ -1482,6 +1549,14 @@ class World { player.client = null; } + this.playerRenderer.removePermanent(player.pid); + this.gameMap.getZone(player.x, player.z, player.level).leave(player); + this.players.remove(player.pid); + changeNpcCollision(player.width, player.x, player.z, player.level, false); + player.pid = -1; + player.uid = -1; + player.terminate(); + Login.logout(player); this.friendThread.postMessage({ diff --git a/src/lostcity/engine/renderer/NpcRenderer.ts b/src/lostcity/engine/renderer/NpcRenderer.ts new file mode 100644 index 0000000000..f105162f9a --- /dev/null +++ b/src/lostcity/engine/renderer/NpcRenderer.ts @@ -0,0 +1,81 @@ +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import Renderer from '#lostcity/engine/renderer/Renderer.js'; +import Npc from '#lostcity/entity/Npc.js'; +import NpcInfoAnim from '#lostcity/network/outgoing/model/NpcInfoAnim.js'; +import NpcInfoFaceEntity from '#lostcity/network/outgoing/model/NpcInfoFaceEntity.js'; +import NpcInfoSay from '#lostcity/network/outgoing/model/NpcInfoSay.js'; +import NpcInfoDamage from '#lostcity/network/outgoing/model/NpcInfoDamage.js'; +import NpcInfoChangeType from '#lostcity/network/outgoing/model/NpcInfoChangeType.js'; +import NpcInfoSpotanim from '#lostcity/network/outgoing/model/NpcInfoSpotanim.js'; +import NpcInfoFaceCoord from '#lostcity/network/outgoing/model/NpcInfoFaceCoord.js'; +import NpcStat from '#lostcity/entity/NpcStat.js'; + +export default class NpcRenderer extends Renderer { + constructor() { + super( + new Map([ + [InfoProt.NPC_ANIM, new Map()], + [InfoProt.NPC_FACE_ENTITY, new Map()], + [InfoProt.NPC_SAY, new Map()], + [InfoProt.NPC_DAMAGE, new Map()], + [InfoProt.NPC_CHANGE_TYPE, new Map()], + [InfoProt.NPC_SPOTANIM, new Map()], + [InfoProt.NPC_FACE_COORD, new Map()] + ]) + ); + } + + computeInfo(npc: Npc): void { + const masks: number = npc.masks; + const nid: number = npc.nid; + + if (nid === -1 || masks === 0) { + return; + } + + let lows: number = 0; + let highs: number = 0; + + if (masks & InfoProt.NPC_ANIM.id) { + highs += this.cache(nid, new NpcInfoAnim(npc.animId, npc.animDelay), InfoProt.NPC_ANIM); + } + if (masks & InfoProt.NPC_FACE_ENTITY.id) { + highs += lows += this.cache(nid, new NpcInfoFaceEntity(npc.faceEntity), InfoProt.NPC_FACE_ENTITY); + } + if (masks & InfoProt.NPC_SAY.id && npc.chat) { + highs += this.cache(nid, new NpcInfoSay(npc.chat), InfoProt.NPC_SAY); + } + if (masks & InfoProt.NPC_DAMAGE.id) { + highs += this.cache(nid, new NpcInfoDamage(npc.damageTaken, npc.damageType, npc.levels[NpcStat.HITPOINTS], npc.baseLevels[NpcStat.HITPOINTS]), InfoProt.NPC_DAMAGE); + } + if (masks & InfoProt.NPC_CHANGE_TYPE.id) { + highs += this.cache(nid, new NpcInfoChangeType(npc.type), InfoProt.NPC_CHANGE_TYPE); + } + if (masks & InfoProt.NPC_SPOTANIM.id) { + highs += this.cache(nid, new NpcInfoSpotanim(npc.graphicId, npc.graphicHeight, npc.graphicDelay), InfoProt.NPC_SPOTANIM); + } + if (masks & InfoProt.NPC_FACE_COORD.id) { + highs += lows += this.cache(nid, new NpcInfoFaceCoord(npc.faceX, npc.faceZ), InfoProt.NPC_FACE_COORD); + } + + if (highs > 0) { + this.highs.set(nid, highs + this.header(masks)); + } + + if (lows > 0) { + const header: number = this.header(InfoProt.NPC_FACE_ENTITY.id + InfoProt.NPC_FACE_COORD.id); + this.lows.set(nid, header + InfoProt.NPC_FACE_ENTITY.length + InfoProt.NPC_FACE_COORD.length); + } + } + + removeTemporary() { + super.removeTemporary(); + this.caches.get(InfoProt.NPC_ANIM)?.clear(); + this.caches.get(InfoProt.NPC_FACE_ENTITY)?.clear(); + this.caches.get(InfoProt.NPC_SAY)?.clear(); + this.caches.get(InfoProt.NPC_DAMAGE)?.clear(); + this.caches.get(InfoProt.NPC_CHANGE_TYPE)?.clear(); + this.caches.get(InfoProt.NPC_SPOTANIM)?.clear(); + this.caches.get(InfoProt.NPC_FACE_COORD)?.clear(); + } +} \ No newline at end of file diff --git a/src/lostcity/engine/renderer/PlayerRenderer.ts b/src/lostcity/engine/renderer/PlayerRenderer.ts new file mode 100644 index 0000000000..0038ab77f4 --- /dev/null +++ b/src/lostcity/engine/renderer/PlayerRenderer.ts @@ -0,0 +1,107 @@ +import Player from '#lostcity/entity/Player.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoAppearance from '#lostcity/network/outgoing/model/PlayerInfoAppearance.js'; +import PlayerInfoAnim from '#lostcity/network/outgoing/model/PlayerInfoAnim.js'; +import PlayerInfoFaceEntity from '#lostcity/network/outgoing/model/PlayerInfoFaceEntity.js'; +import PlayerInfoSay from '#lostcity/network/outgoing/model/PlayerInfoSay.js'; +import PlayerInfoFaceCoord from '#lostcity/network/outgoing/model/PlayerInfoFaceCoord.js'; +import PlayerInfoChat from '#lostcity/network/outgoing/model/PlayerInfoChat.js'; +import PlayerInfoSpotanim from '#lostcity/network/outgoing/model/PlayerInfoSpotanim.js'; +import Renderer from '#lostcity/engine/renderer/Renderer.js'; +import PlayerInfoDamage from '#lostcity/network/outgoing/model/PlayerInfoDamage.js'; +import PlayerStat from '#lostcity/entity/PlayerStat.js'; +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; +import Packet from '#jagex/io/Packet.js'; +import PlayerInfoExactMove from '#lostcity/network/outgoing/model/PlayerInfoExactMove.js'; +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import ServerProtRepository from '#lostcity/network/225/outgoing/prot/ServerProtRepository.js'; + +export default class PlayerRenderer extends Renderer { + constructor() { + super(new Map([ + [InfoProt.PLAYER_APPEARANCE, new Map()], + [InfoProt.PLAYER_ANIM, new Map()], + [InfoProt.PLAYER_FACE_ENTITY, new Map()], + [InfoProt.PLAYER_SAY, new Map()], + [InfoProt.PLAYER_DAMAGE, new Map()], + [InfoProt.PLAYER_FACE_COORD, new Map()], + [InfoProt.PLAYER_CHAT, new Map()], + [InfoProt.PLAYER_SPOTANIM, new Map()], + // exact move does not get cached, that is built on demand. + ])); + } + + computeInfo(player: Player): void { + const masks: number = player.masks; + const pid: number = player.pid; + + if (pid === -1 || masks === 0) { + return; + } + + let lows: number = 0; + let highs: number = 0; + + if (masks & InfoProt.PLAYER_APPEARANCE.id && player.appearance) { + highs += lows += this.cache(pid, new PlayerInfoAppearance(player.appearance), InfoProt.PLAYER_APPEARANCE); + } + if (masks & InfoProt.PLAYER_ANIM.id) { + highs += this.cache(pid, new PlayerInfoAnim(player.animId, player.animDelay), InfoProt.PLAYER_ANIM); + } + if (masks & InfoProt.PLAYER_FACE_ENTITY.id) { + highs += lows += this.cache(pid, new PlayerInfoFaceEntity(player.faceEntity), InfoProt.PLAYER_FACE_ENTITY); + } + if (masks & InfoProt.PLAYER_SAY.id && player.chat) { + highs += this.cache(pid, new PlayerInfoSay(player.chat), InfoProt.PLAYER_SAY); + } + if (masks & InfoProt.PLAYER_DAMAGE.id) { + highs += this.cache(pid, new PlayerInfoDamage(player.damageTaken, player.damageType, player.levels[PlayerStat.HITPOINTS], player.baseLevels[PlayerStat.HITPOINTS]), InfoProt.PLAYER_DAMAGE); + } + if (masks & InfoProt.PLAYER_FACE_COORD.id) { + highs += lows += this.cache(pid, new PlayerInfoFaceCoord(player.faceX, player.faceZ), InfoProt.PLAYER_FACE_COORD); + } + if (masks & InfoProt.PLAYER_CHAT.id && player.messageColor !== null && player.messageEffect !== null && player.messageType !== null && player.message) { + highs += this.cache(pid, new PlayerInfoChat(player.messageColor, player.messageEffect, player.messageType, player.message), InfoProt.PLAYER_CHAT); + } + if (masks & InfoProt.PLAYER_SPOTANIM.id) { + highs += this.cache(pid, new PlayerInfoSpotanim(player.graphicId, player.graphicHeight, player.graphicDelay), InfoProt.PLAYER_SPOTANIM); + } + if (masks & InfoProt.PLAYER_EXACT_MOVE.id) { + highs += InfoProt.PLAYER_EXACT_MOVE.length; + } + + if (highs > 0) { + this.highs.set(pid, highs + this.header(masks)); + } + if (lows > 0) { + const header: number = this.header(InfoProt.PLAYER_APPEARANCE.id + InfoProt.PLAYER_FACE_ENTITY.id + InfoProt.PLAYER_FACE_COORD.id); + const appearance: number = this.caches.get(InfoProt.PLAYER_APPEARANCE)?.get(pid)?.length ?? 0; + this.lows.set(pid, header + InfoProt.PLAYER_FACE_ENTITY.length + InfoProt.PLAYER_FACE_COORD.length + appearance); + } + } + + writeExactmove(buf: Packet, startX: number, startZ: number, endX: number, endZ: number, start: number, end: number, direction: number): void { + const message: InfoMessage = new PlayerInfoExactMove(startX, startZ, endX, endZ, start, end, direction); + const encoder: InfoMessageEncoder | undefined = ServerProtRepository.getInfoEncoder(message); + if (typeof encoder === 'undefined') { + throw new Error(`Encoder not found for info message! ${message}`); + } + encoder.encode(buf, message); + } + + removeTemporary() { + super.removeTemporary(); + this.caches.get(InfoProt.PLAYER_ANIM)?.clear(); + this.caches.get(InfoProt.PLAYER_FACE_ENTITY)?.clear(); + this.caches.get(InfoProt.PLAYER_SAY)?.clear(); + this.caches.get(InfoProt.PLAYER_DAMAGE)?.clear(); + this.caches.get(InfoProt.PLAYER_FACE_COORD)?.clear(); + this.caches.get(InfoProt.PLAYER_SPOTANIM)?.clear(); + this.caches.get(InfoProt.PLAYER_CHAT)?.clear(); + } + + removePermanent(pid: number) { + super.removePermanent(pid); + this.caches.get(InfoProt.PLAYER_APPEARANCE)?.delete(pid); + } +} \ No newline at end of file diff --git a/src/lostcity/engine/renderer/Renderer.ts b/src/lostcity/engine/renderer/Renderer.ts new file mode 100644 index 0000000000..e73bbaaf10 --- /dev/null +++ b/src/lostcity/engine/renderer/Renderer.ts @@ -0,0 +1,104 @@ +import Entity from '#lostcity/entity/Entity.js'; +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import ServerProtRepository from '#lostcity/network/225/outgoing/prot/ServerProtRepository.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; + +export default abstract class Renderer { + protected readonly caches: Map>; + + protected readonly highs: Map; + protected readonly lows: Map; + + protected constructor(caches: Map>) { + this.caches = caches; + this.highs = new Map(); + this.lows = new Map(); + } + + abstract computeInfo(entity: T): void; + + write1(buf: Packet, masks: number): void { + buf.p1(masks & 0xff); + } + + write2(buf: Packet, masks: number, big: number): void { + if (masks > 0xff) { + masks |= big; + } + buf.p1(masks & 0xff); + if (masks & big) { + buf.p1(masks >> 8); + } + } + + cache(id: number, message: InfoMessage, prot: InfoProt): number { + const cache = this.caches.get(prot); + if (typeof cache === 'undefined') { + throw new Error('[Renderer] tried to cache to empty!'); + } + if (cache.has(id) && !message.persists) { + return 0; + } + return this.encodeInfo(cache, id, message); + } + + write(buf: Packet, id: number, prot: InfoProt): void { + const cache: Map | undefined = this.caches.get(prot); + if (typeof cache === 'undefined') { + throw new Error('[Renderer] tried to write a buf not cached!'); + } + this.writeBlock(buf, cache, id); + } + + has(id: number, prot: InfoProt): boolean { + const cache: Map | undefined = this.caches.get(prot); + return cache ? cache.has(id) : false; + } + + highdefinitions(id: number): number { + return this.highs.get(id) ?? 0; + } + + lowdefinitions(id: number): number { + return this.lows.get(id) ?? 0; + } + + removeTemporary() { + this.highs.clear(); + } + + removePermanent(id: number) { + this.highs.delete(id); + this.lows.delete(id); + } + + protected encodeInfo(messages: Map, id: number, message: T): number { + const encoder: InfoMessageEncoder | undefined = ServerProtRepository.getInfoEncoder(message); + if (typeof encoder === 'undefined') { + throw new Error(`Encoder not found for info message! ${message}`); + } + const test = encoder.test(message); + const bytes = new Uint8Array(test); + encoder.encode(new Packet(bytes), message); + messages.set(id, bytes); + return test; + } + + protected writeBlock(buf: Packet, messages: Map, id: number): void { + const bytes: Uint8Array | undefined = messages.get(id); + if (typeof bytes === 'undefined') { + throw new Error('[Renderer] Tried to write empty block!'); + } + buf.pdata(bytes, 0, bytes.length); + } + + protected header(masks: number): number { + let length = 1; + if (masks > 0xff) { + length += 1; + } + return length; + } +} \ No newline at end of file diff --git a/src/lostcity/engine/script/ScriptFile.ts b/src/lostcity/engine/script/ScriptFile.ts index b56ee90336..dbadf0ca4c 100644 --- a/src/lostcity/engine/script/ScriptFile.ts +++ b/src/lostcity/engine/script/ScriptFile.ts @@ -1,6 +1,6 @@ import path from 'path'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ScriptOpcode from '#lostcity/engine/script/ScriptOpcode.js'; import Environment from '#lostcity/util/Environment.js'; diff --git a/src/lostcity/engine/script/ScriptOpcode.ts b/src/lostcity/engine/script/ScriptOpcode.ts index 3469fce28e..94a9fe4a63 100644 --- a/src/lostcity/engine/script/ScriptOpcode.ts +++ b/src/lostcity/engine/script/ScriptOpcode.ts @@ -72,7 +72,7 @@ enum ScriptOpcode { ZONECOUNT, LOCCOUNT, OBJCOUNT, - MAP_MULTI, + MAP_MULTIWAY, // official // Player ops (2000-2499) ALLOWDESIGN = 2000, @@ -435,6 +435,8 @@ enum ScriptOpcode { MAP_LASTCLEANUP, MAP_LASTBANDWIDTHIN, MAP_LASTBANDWIDTHOUT, + TIMESPENT, // custom: used to profile script execution (record start time) + GETTIMESPENT, // custom: used to profile script execution (current duration) } export default ScriptOpcode; diff --git a/src/lostcity/engine/script/ScriptProvider.ts b/src/lostcity/engine/script/ScriptProvider.ts index 8d6ebee5ee..c609fc0cb3 100644 --- a/src/lostcity/engine/script/ScriptProvider.ts +++ b/src/lostcity/engine/script/ScriptProvider.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ScriptFile from '#lostcity/engine/script/ScriptFile.js'; import ServerTriggerType from '#lostcity/engine/script/ServerTriggerType.js'; diff --git a/src/lostcity/engine/script/ScriptRunner.ts b/src/lostcity/engine/script/ScriptRunner.ts index 23d6abfbb4..820ccc8d75 100644 --- a/src/lostcity/engine/script/ScriptRunner.ts +++ b/src/lostcity/engine/script/ScriptRunner.ts @@ -147,7 +147,7 @@ export default class ScriptRunner { ScriptRunner.executeInner(state, state.script.opcodes[++state.pc]); } const time: number = ((performance.now() * 1000) - start) | 0; - if (Environment.NODE_DEBUG_PROFILER && time > 1000) { + if (Environment.NODE_DEBUG_PROFILE && time > 1000) { const message: string = `Warning [cpu time]: Script: ${state.script.info.scriptName}, time: ${time}us, opcount: ${state.opcount}`; if (state.self instanceof Player) { state.self.wrappedMessageGame(message); diff --git a/src/lostcity/engine/script/ScriptState.ts b/src/lostcity/engine/script/ScriptState.ts index fb464bbd48..3745f628ab 100644 --- a/src/lostcity/engine/script/ScriptState.ts +++ b/src/lostcity/engine/script/ScriptState.ts @@ -27,14 +27,14 @@ export interface JumpStackFrame { } export default class ScriptState { - static ABORTED = -1; - static RUNNING = 0; - static FINISHED = 1; - static SUSPENDED = 2; // suspended to move to player - static PAUSEBUTTON = 3; - static COUNTDIALOG = 4; - static NPC_SUSPENDED = 5; // suspended to move to npc - static WORLD_SUSPENDED = 6; // suspended to move to world + static readonly ABORTED = -1; + static readonly RUNNING = 0; + static readonly FINISHED = 1; + static readonly SUSPENDED = 2; // suspended to move to player + static readonly PAUSEBUTTON = 3; + static readonly COUNTDIALOG = 4; + static readonly NPC_SUSPENDED = 5; // suspended to move to npc + static readonly WORLD_SUSPENDED = 6; // suspended to move to world // interpreter script: ScriptFile; @@ -120,6 +120,11 @@ export default class ScriptState { dbRow: number = -1; dbRowQuery: number[] = []; + /** + * Used for debug commands + */ + timespent: number = 0; + huntIterator: IterableIterator | null = null; npcIterator: IterableIterator | null = null; locIterator: IterableIterator | null = null; @@ -335,11 +340,58 @@ export default class ScriptState { return strings; } - pushString(value: string) { + pushString(value: string): void { this.stringStack[this.ssp++] = value; } - reset() { + popFrame(): void { + const frame = this.frames[--this.fp]; + this.pc = frame.pc; + this.script = frame.script; + this.intLocals = frame.intLocals; + this.stringLocals = frame.stringLocals; + } + + gosubFrame(proc: ScriptFile): void { + this.frames[this.fp++] = { + script: this.script, + pc: this.pc, + intLocals: this.intLocals, + stringLocals: this.stringLocals + }; + this.setupNewScript(proc); + } + + gotoFrame(label: ScriptFile): void { + this.debugFrames[this.debugFp++] = { + script: this.script, + pc: this.pc + }; + this.fp = 0; + this.frames.length = 0; + this.setupNewScript(label); + } + + setupNewScript(script: ScriptFile): void { + const intLocals: number[] = new Array(script.intLocalCount).fill(0); + const intArgCount: number = script.intArgCount; + for (let index: number = 0; index < intArgCount; index++) { + intLocals[intArgCount - index - 1] = this.popInt(); + } + + const stringLocals: string[] = new Array(script.stringLocalCount); + const stringArgCount: number = script.stringArgCount; + for (let index: number = 0; index < stringArgCount; index++) { + stringLocals[stringArgCount - index - 1] = this.popString(); + } + + this.pc = -1; + this.script = script; + this.intLocals = intLocals; + this.stringLocals = stringLocals; + } + + reset(): void { this.pc = -1; this.frames = []; this.fp = 0; diff --git a/src/lostcity/engine/script/ServerTriggerType.ts b/src/lostcity/engine/script/ServerTriggerType.ts index f17a430d1e..d8a4e8d281 100644 --- a/src/lostcity/engine/script/ServerTriggerType.ts +++ b/src/lostcity/engine/script/ServerTriggerType.ts @@ -156,7 +156,9 @@ enum ServerTriggerType { MAPZONE = 161, MAPZONEEXIT = 162, ZONE = 163, - ZONEEXIT = 164 + ZONEEXIT = 164, + CHANGESTAT = 165, + AI_SPAWN = 166 } namespace ServerTriggerType { diff --git a/src/lostcity/engine/script/handlers/CoreOps.ts b/src/lostcity/engine/script/handlers/CoreOps.ts index 2d116507f5..d9bb02a375 100644 --- a/src/lostcity/engine/script/handlers/CoreOps.ts +++ b/src/lostcity/engine/script/handlers/CoreOps.ts @@ -13,50 +13,6 @@ import ScriptState from '#lostcity/engine/script/ScriptState.js'; import {check, VarNpcValid, VarPlayerValid, VarSharedValid} from '#lostcity/engine/script/ScriptValidators.js'; import {ProtectedActivePlayer} from '#lostcity/engine/script/ScriptPointer.js'; -function gosub(state: ScriptState, id: number) { - if (state.fp >= 50) { - throw new Error('stack overflow'); - } - - // set up the gosub frame - state.frames[state.fp++] = { - script: state.script, - pc: state.pc, - intLocals: state.intLocals, - stringLocals: state.stringLocals - }; - - // lookup script and set it up - const script = ScriptProvider.get(id); - if (!script) { - throw new Error(`unable to find proc ${script}`); - } - setupNewScript(state, script); -} - -function jump(state: ScriptState, id: number) { - const label = ScriptProvider.get(id); - if (!label) { - throw new Error(`unable to find label ${id}`); - } - - state.debugFrames[state.debugFp++] = { - script: state.script, - pc: state.pc - }; - - setupNewScript(state, label); - state.fp = 0; - state.frames = []; -} - -function setupNewScript(state: ScriptState, script: ScriptFile) { - state.script = script; - state.pc = -1; - state.intLocals = state.popInts(script.intArgCount); - state.stringLocals = state.popStrings(script.stringArgCount); -} - const CoreOps: CommandHandlers = { [ScriptOpcode.PUSH_CONSTANT_INT]: state => { state.pushInt(state.intOperand); @@ -241,12 +197,7 @@ const CoreOps: CommandHandlers = { state.execution = ScriptState.FINISHED; return; } - - const frame = state.frames[--state.fp]; - state.pc = frame.pc; - state.script = frame.script; - state.intLocals = frame.intLocals; - state.stringLocals = frame.stringLocals; + state.popFrame(); }, [ScriptOpcode.JOIN_STRING]: state => { @@ -261,19 +212,41 @@ const CoreOps: CommandHandlers = { }, [ScriptOpcode.GOSUB]: state => { - gosub(state, state.popInt()); + if (state.fp >= 50) { + throw new Error('stack overflow'); + } + const proc: ScriptFile | undefined = ScriptProvider.get(state.popInt()); + if (!proc) { + throw new Error(`unable to find proc ${proc}`); + } + state.gosubFrame(proc); }, [ScriptOpcode.GOSUB_WITH_PARAMS]: state => { - gosub(state, state.intOperand); + if (state.fp >= 50) { + throw new Error('stack overflow'); + } + const proc: ScriptFile | undefined = ScriptProvider.get(state.intOperand); + if (!proc) { + throw new Error(`unable to find proc ${proc}`); + } + state.gosubFrame(proc); }, [ScriptOpcode.JUMP]: state => { - jump(state, state.popInt()); + const label: ScriptFile | undefined = ScriptProvider.get(state.popInt()); + if (!label) { + throw new Error(`unable to find proc ${label}`); + } + state.gotoFrame(label); }, [ScriptOpcode.JUMP_WITH_PARAMS]: state => { - jump(state, state.intOperand); + const label: ScriptFile | undefined = ScriptProvider.get(state.intOperand); + if (!label) { + throw new Error(`unable to find proc ${label}`); + } + state.gotoFrame(label); }, [ScriptOpcode.DEFINE_ARRAY]: state => { diff --git a/src/lostcity/engine/script/handlers/DebugOps.ts b/src/lostcity/engine/script/handlers/DebugOps.ts index 2d46aa95a1..8ce54d41e3 100644 --- a/src/lostcity/engine/script/handlers/DebugOps.ts +++ b/src/lostcity/engine/script/handlers/DebugOps.ts @@ -60,7 +60,23 @@ const DebugOps: CommandHandlers = { [ScriptOpcode.MAP_LASTBANDWIDTHOUT]: state => { state.pushInt(World.lastCycleStats[WorldStat.BANDWIDTH_OUT]); - } + }, + + [ScriptOpcode.TIMESPENT]: state => { + state.timespent = performance.now(); + }, + + [ScriptOpcode.GETTIMESPENT]: state => { + const elapsed = performance.now() - state.timespent; + + if (state.popInt() === 1) { + // microseconds + state.pushInt(elapsed * 1000); + } else { + // milliseconds + state.pushInt(elapsed); + } + }, }; export default DebugOps; diff --git a/src/lostcity/engine/script/handlers/NumberOps.ts b/src/lostcity/engine/script/handlers/NumberOps.ts index 2f51c637d9..433500630d 100644 --- a/src/lostcity/engine/script/handlers/NumberOps.ts +++ b/src/lostcity/engine/script/handlers/NumberOps.ts @@ -3,7 +3,7 @@ import { CommandHandlers } from '#lostcity/engine/script/ScriptRunner.js'; import { bitcount, clearBitRange, MASK, setBitRange } from '#lostcity/util/Numbers.js'; -import Trig from '#jagex2/Trig.js'; +import Trig from '#jagex/Trig.js'; const NumberOps: CommandHandlers = { [ScriptOpcode.ADD]: state => { diff --git a/src/lostcity/engine/script/handlers/PlayerOps.ts b/src/lostcity/engine/script/handlers/PlayerOps.ts index cf4ba64df3..32b16de7e8 100644 --- a/src/lostcity/engine/script/handlers/PlayerOps.ts +++ b/src/lostcity/engine/script/handlers/PlayerOps.ts @@ -448,6 +448,9 @@ const PlayerOps: CommandHandlers = { if (stat === 3 && player.levels[3] >= player.baseLevels[3]) { player.resetHeroPoints(); } + if (added !== current) { + player.changeStat(stat); + } }), [ScriptOpcode.STAT_SUB]: checkedHandler(ActivePlayer, state => { @@ -461,6 +464,9 @@ const PlayerOps: CommandHandlers = { const current = player.levels[stat]; const subbed = current - (constant + (current * percent) / 100); player.levels[stat] = Math.max(subbed, 0); + if (subbed !== current) { + player.changeStat(stat); + } }), [ScriptOpcode.SPOTANIM_PL]: checkedHandler(ActivePlayer, state => { @@ -487,6 +493,10 @@ const PlayerOps: CommandHandlers = { if (stat === 3 && player.levels[3] >= player.baseLevels[3]) { player.resetHeroPoints(); } + + if (healed !== current) { + player.changeStat(stat); + } }), [ScriptOpcode.UID]: checkedHandler(ActivePlayer, state => { diff --git a/src/lostcity/engine/script/handlers/ServerOps.ts b/src/lostcity/engine/script/handlers/ServerOps.ts index 6160f6c3da..e83b805cd8 100644 --- a/src/lostcity/engine/script/handlers/ServerOps.ts +++ b/src/lostcity/engine/script/handlers/ServerOps.ts @@ -531,7 +531,7 @@ const ServerOps: CommandHandlers = { state.pushInt(coord); }, - [ScriptOpcode.MAP_MULTI]: state => { + [ScriptOpcode.MAP_MULTIWAY]: state => { const coord = state.popInt(); state.pushInt(World.gameMap.isMulti(coord) ? 1 : 0); diff --git a/src/lostcity/entity/BuildArea.ts b/src/lostcity/entity/BuildArea.ts index 75917913db..abcf6fe4e0 100644 --- a/src/lostcity/entity/BuildArea.ts +++ b/src/lostcity/entity/BuildArea.ts @@ -1,14 +1,7 @@ -import ZoneMap from '#lostcity/engine/zone/ZoneMap.js'; import {CoordGrid} from '#lostcity/engine/CoordGrid.js'; import Player from '#lostcity/entity/Player.js'; import World from '#lostcity/engine/World.js'; import Npc from '#lostcity/entity/Npc.js'; -import Entity from '#lostcity/entity/Entity.js'; - -export type ExtendedInfo = { - id: number, - added: boolean -} export default class BuildArea { public static readonly INTERVAL: number = 10; @@ -17,12 +10,15 @@ export default class BuildArea { public static readonly PREFERRED_VIEW_DISTANCE: number = 15; // constructor - readonly npcs: Set; // observed npcs - readonly players: Set; // observed players + readonly npcs: Set; // observed npcs + readonly players: Set; // observed players readonly loadedZones: Set; readonly activeZones: Set; - readonly extendedInfo: Set; - readonly appearances: Map; + readonly highPlayers: Set; // cleared after player_info + readonly lowPlayers: Set; // cleared after player_info + readonly highNpcs: Set; // cleared after npc_info + readonly lowNpcs: Set; // cleared after npc_info + readonly appearances: Map; // cached appearance ticks // runtime forceViewDistance: boolean = false; @@ -35,7 +31,10 @@ export default class BuildArea { this.players = new Set(); this.loadedZones = new Set(); this.activeZones = new Set(); - this.extendedInfo = new Set(); + this.highPlayers = new Set(); + this.lowPlayers = new Set(); + this.highNpcs = new Set(); + this.lowNpcs = new Set(); this.appearances = new Map(); } @@ -59,10 +58,6 @@ export default class BuildArea { } } - clearExtended(): void { - this.extendedInfo.clear(); - } - hasAppearance(pid: number, tick: number): boolean { const appearance: number | undefined = this.appearances.get(pid); if (typeof appearance === 'undefined') { @@ -75,64 +70,91 @@ export default class BuildArea { this.appearances.set(pid, tick); } - *getNearbyPlayers(uid: number, x: number, z: number, originX: number, originZ: number): IterableIterator { - players: for (const zoneIndex of this.proximitySort(x, z, this.activeZones)) { - for (const other of this.getNearby(World.gameMap.getZoneIndex(zoneIndex).getAllPlayersSafe(), x, z, originX, originZ, this.viewDistance)) { - if (this.players.size >= BuildArea.PREFERRED_PLAYERS) { - break players; - } - if (this.players.has(other.uid)) { - continue; - } - if (other.uid === uid) { - continue; - } - yield other; - } - } + clearPlayerInfo(): void { + this.highPlayers.clear(); + this.lowPlayers.clear(); } - *getNearbyNpcs(x: number, z: number, originX: number, originZ: number): IterableIterator { - npcs: for (const zoneIndex of this.proximitySort(x, z, this.activeZones)) { - for (const npc of this.getNearby(World.gameMap.getZoneIndex(zoneIndex).getAllNpcsSafe(), x, z, originX, originZ, 15)) { - if (this.npcs.size >= BuildArea.PREFERRED_NPCS) { - break npcs; - } - if (this.npcs.has(npc.nid)) { - continue; - } - yield npc; - } - } + clearNpcInfo(): void { + this.highNpcs.clear(); + this.lowNpcs.clear(); } - private *getNearby(entities: IterableIterator, x: number, z: number, originX: number, originZ: number, distance: number): IterableIterator { + *getNearbyPlayers(pid: number, level: number, x: number, z: number, originX: number, originZ: number): IterableIterator { const absLeftX: number = originX - 48; const absRightX: number = originX + 48; const absTopZ: number = originZ + 48; const absBottomZ: number = originZ - 48; - for (const entity of entities) { - if (entity.x <= absLeftX || entity.x >= absRightX || entity.z >= absTopZ || entity.z <= absBottomZ) { - continue; + const radius = this.viewDistance * 2; + const min = -radius >> 1; + const max = radius >> 1; + const length = radius ** 2; + + let dx = 0; + let dz = 0; + let ldx = 0; + let ldz = -1; + + for (let index = 1; index <= length; index++) { + if (min < dx && dx <= max && min < dz && dz <= max) { + const players = World.playerGrid.get(CoordGrid.packCoord(level, x + dx, z + dz)); + if (typeof players !== 'undefined') { + for (const player of players) { + if (this.players.size >= BuildArea.PREFERRED_PLAYERS) { + return; + } + if ( + player.pid !== -1 && + player.pid !== pid && + CoordGrid.isWithinDistanceSW({ x: x + dx, z: z + dz }, player, this.viewDistance) && + !this.players.has(player) && + player.level === level && + !(player.x <= absLeftX || player.x >= absRightX || player.z >= absTopZ || player.z <= absBottomZ) + ) { + yield player; + } + } + } } - if (!CoordGrid.isWithinDistanceSW({x, z}, entity, distance)) { - continue; + + if (dx === dz || (dx < 0 && dx === -dz) || (dx > 0 && dx === 1 - dz)) { + const tmp = ldx; + ldx = -ldz; + ldz = tmp; } - yield entity; + + dx += ldx; + dz += ldz; } } - private proximitySort(zoneX: number, zoneZ: number, zones: Set): number[] { - return Array.from(zones.values()) - .map(zoneIndex => this.zoneToDistance(zoneIndex, zoneX, zoneZ)) - .sort((a, b) => a.distance - b.distance) - .map(({zoneIndex}) => zoneIndex); - } + *getNearbyNpcs(level: number, x: number, z: number, originX: number, originZ: number): IterableIterator { + const absLeftX: number = originX - 48; + const absRightX: number = originX + 48; + const absTopZ: number = originZ + 48; + const absBottomZ: number = originZ - 48; - private zoneToDistance(zoneIndex: number, zoneX: number, zoneZ: number): {distance: number, zoneIndex: number} { - const pos: CoordGrid = ZoneMap.unpackIndex(zoneIndex); - const distance: number = Math.abs(pos.x - zoneX) + Math.abs(pos.z - zoneZ); - return {zoneIndex, distance}; + const centerX = CoordGrid.zone(x); + const centerZ = CoordGrid.zone(z); + + const minx = centerX - 2; + const minz = centerZ - 2; + const maxx = centerX + 2; + const maxz = centerZ + 2; + + for (let cx = minx; cx <= maxx; cx++) { + for (let cz = minz; cz <= maxz; cz++) { + for (const npc of World.gameMap.getZone(cx << 3, cz << 3, level).getAllNpcsSafe()) { + if (this.npcs.size >= BuildArea.PREFERRED_NPCS) { + return; + } + if (!CoordGrid.isWithinDistanceSW({ x, z }, npc, BuildArea.PREFERRED_VIEW_DISTANCE) || npc.nid === -1 || this.npcs.has(npc) || npc.level !== level || npc.x <= absLeftX || npc.x >= absRightX || npc.z >= absTopZ || npc.z <= absBottomZ) { + continue; + } + yield npc; + } + } + } } -} \ No newline at end of file +} diff --git a/src/lostcity/entity/CameraInfo.ts b/src/lostcity/entity/CameraInfo.ts index 94ef8ad606..49f01ee074 100644 --- a/src/lostcity/entity/CameraInfo.ts +++ b/src/lostcity/entity/CameraInfo.ts @@ -1,4 +1,4 @@ -import Linkable from '#jagex2/datastruct/Linkable.js'; +import Linkable from '#jagex/datastruct/Linkable.js'; import { CameraProt } from '#lostcity/network/225/outgoing/prot/ServerProt.js'; export default class CameraInfo extends Linkable { diff --git a/src/lostcity/entity/EntityList.ts b/src/lostcity/entity/EntityList.ts index 3a279ada15..30cebd8dd1 100644 --- a/src/lostcity/entity/EntityList.ts +++ b/src/lostcity/entity/EntityList.ts @@ -48,11 +48,7 @@ abstract class EntityList extends Array { } get count(): number { - let count: number = 0; - for (const _ of this[Symbol.iterator]()) { - count++; - } - return count; + return Math.max(this.length - this.free.size, 0); } get(id: number): T | undefined { diff --git a/src/lostcity/entity/EntityQueueRequest.ts b/src/lostcity/entity/EntityQueueRequest.ts index 61c2e93b60..f84b164aa6 100644 --- a/src/lostcity/entity/EntityQueueRequest.ts +++ b/src/lostcity/entity/EntityQueueRequest.ts @@ -1,4 +1,4 @@ -import Linkable from '#jagex2/datastruct/Linkable.js'; +import Linkable from '#jagex/datastruct/Linkable.js'; import ScriptFile from '#lostcity/engine/script/ScriptFile.js'; import ScriptState from '#lostcity/engine/script/ScriptState.js'; diff --git a/src/lostcity/entity/NetworkPlayer.ts b/src/lostcity/entity/NetworkPlayer.ts index 13ed35614c..5ca0ac7ca5 100644 --- a/src/lostcity/entity/NetworkPlayer.ts +++ b/src/lostcity/entity/NetworkPlayer.ts @@ -1,7 +1,7 @@ import 'dotenv/config'; import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; @@ -37,6 +37,8 @@ import NpcInfo from '#lostcity/network/outgoing/model/NpcInfo.js'; import WorldStat from '#lostcity/engine/WorldStat.js'; import SetMultiway from '#lostcity/network/outgoing/model/SetMultiway.js'; import { printError } from '#lostcity/util/Logger.js'; +import NpcRenderer from '#lostcity/engine/renderer/NpcRenderer.js'; +import PlayerRenderer from '#lostcity/engine/renderer/PlayerRenderer.js'; export class NetworkPlayer extends Player { client: ClientSocket | null = null; @@ -136,7 +138,7 @@ export class NetworkPlayer extends Player { } const encoder: MessageEncoder | undefined = ServerProtRepository.getEncoder(message); if (!encoder) { - printError('No encoder for message ' + message); + printError(`No encoder for message ${message.constructor.name}`); return; } const prot: ServerProt = encoder.prot; @@ -274,12 +276,26 @@ export class NetworkPlayer extends Player { } } - updatePlayers() { - this.write(new PlayerInfo(this.buildArea, this.level, this.x, this.z, this.originX, this.originZ, this.uid, this.mask, this.tele, this.jump, this.walkDir, this.runDir, Math.abs(this.lastTickX - this.x), Math.abs(this.lastTickZ - this.z), this.lastLevel !== this.level)); + updatePlayers(renderer: PlayerRenderer) { + this.write(new PlayerInfo( + World.currentTick, + renderer, + this, + Math.abs(this.lastTickX - this.x), + Math.abs(this.lastTickZ - this.z), + this.lastLevel !== this.level + )); } - updateNpcs() { - this.write(new NpcInfo(this.buildArea, this.level, this.x, this.z, this.originX, this.originZ, Math.abs(this.lastTickX - this.x), Math.abs(this.lastTickZ - this.z), this.lastLevel !== this.level)); + updateNpcs(renderer: NpcRenderer) { + this.write(new NpcInfo( + World.currentTick, + renderer, + this, + Math.abs(this.lastTickX - this.x), + Math.abs(this.lastTickZ - this.z), + this.lastLevel !== this.level) + ); } updateZones() { diff --git a/src/lostcity/entity/Npc.ts b/src/lostcity/entity/Npc.ts index a934970795..31d699fb6a 100644 --- a/src/lostcity/entity/Npc.ts +++ b/src/lostcity/entity/Npc.ts @@ -33,20 +33,13 @@ import EntityLifeCycle from '#lostcity/entity/EntityLifeCycle.js'; import NpcStat from '#lostcity/entity/NpcStat.js'; import HuntNobodyNear from '#lostcity/entity/hunt/HuntNobodyNear.js'; -import LinkList from '#jagex2/datastruct/LinkList.js'; +import LinkList from '#jagex/datastruct/LinkList.js'; import {CollisionFlag} from '@2004scape/rsmod-pathfinder'; import {isFlagged} from '#lostcity/engine/GameMap.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; export default class Npc extends PathingEntity { - static readonly ANIM = 0x2; - static readonly FACE_ENTITY = 0x4; - static readonly SAY = 0x8; - static readonly DAMAGE = 0x10; - static readonly CHANGE_TYPE = 0x20; - static readonly SPOTANIM = 0x40; - static readonly FACE_COORD = 0x80; - // constructor properties nid: number; type: number; @@ -54,12 +47,13 @@ export default class Npc extends PathingEntity { origType: number; startX: number; startZ: number; + startLevel: number; levels: Uint8Array = new Uint8Array(6); baseLevels: Uint8Array = new Uint8Array(6); // runtime variables - vars: Int32Array; - varsString: string[]; + readonly vars: Int32Array; + readonly varsString: (string | undefined)[]; // script variables activeScript: ScriptState | null = null; @@ -77,18 +71,21 @@ export default class Npc extends PathingEntity { nextPatrolPoint : number = 0; delayedPatrol : boolean = false; + lastWanderTick: number = 0; + heroPoints: { uid: number; points: number; }[] = new Array(16); // be sure to reset when stats are recovered/reset constructor(level: number, x: number, z: number, width: number, length: number, lifecycle: EntityLifeCycle, nid: number, type: number, moveRestrict: MoveRestrict, blockWalk: BlockWalk) { - super(level, x, z, width, length, lifecycle, moveRestrict, blockWalk, MoveStrategy.NAIVE, Npc.FACE_COORD, Npc.FACE_ENTITY); + super(level, x, z, width, length, lifecycle, moveRestrict, blockWalk, MoveStrategy.NAIVE, InfoProt.NPC_FACE_COORD.id, InfoProt.NPC_FACE_ENTITY.id); this.nid = nid; this.type = type; this.uid = (type << 16) | nid; this.startX = this.x; this.startZ = this.z; + this.startLevel = this.level; this.origType = type; const npcType = NpcType.get(type); @@ -106,6 +103,7 @@ export default class Npc extends PathingEntity { this.targetOp = npcType.defaultmode; this.huntMode = npcType.huntmode; this.huntrange = npcType.huntrange; + this.lastWanderTick = World.currentTick; } resetHeroPoints() { @@ -166,6 +164,8 @@ export default class Npc extends PathingEntity { } this.resetHeroPoints(); this.queue.clear(); + this.vars.fill(0); + this.varsString.fill(undefined); this.defaultMode(); const npcType: NpcType = NpcType.get(this.type); @@ -438,7 +438,7 @@ export default class Npc extends PathingEntity { this.updateMovement(false); this.targetOp = NpcMode.NONE; this.faceEntity = -1; - this.mask |= Npc.FACE_ENTITY; + this.masks |= InfoProt.NPC_FACE_ENTITY.id; } defaultMode(): void { @@ -446,8 +446,9 @@ export default class Npc extends PathingEntity { this.updateMovement(false); const type: NpcType = NpcType.get(this.type); this.targetOp = type.defaultmode; + this.lastWanderTick = World.currentTick; // osrs this.faceEntity = -1; - this.mask |= Npc.FACE_ENTITY; + this.masks |= InfoProt.NPC_FACE_ENTITY.id; } wanderMode(): void { @@ -455,6 +456,14 @@ export default class Npc extends PathingEntity { if (type.moverestrict !== MoveRestrict.NOMOVE && Math.random() < 0.125) { // 1/8 chance to move every tick (even if they already have a destination) this.randomWalk(type.wanderrange); + const moved = this.updateMovement(false); + if (moved) { + this.lastWanderTick = World.currentTick; + } else if (World.currentTick > this.lastWanderTick + 500) { + this.teleport(this.startX, this.startZ, this.startLevel); + this.lastWanderTick = World.currentTick; + } + return; } this.updateMovement(false); } @@ -704,7 +713,6 @@ export default class Npc extends PathingEntity { this.defaultMode(); return; } - this.alreadyFacedEntity = false; } if (this.target && !this.interacted) { @@ -864,7 +872,7 @@ export default class Npc extends PathingEntity { if (this.nextHuntTick > World.currentTick) { return; } - if (NpcType.get(this.type).huntrange < 1) { + if (this.huntrange < 1) { return; } const hunt: HuntType = HuntType.get(this.huntMode); @@ -895,7 +903,15 @@ export default class Npc extends PathingEntity { if (hunted.length > 0) { const entity: Entity = hunted[Math.floor(Math.random() * hunted.length)]; this.huntTarget = entity; - this.setInteraction(Interaction.SCRIPT, entity, hunt.findNewMode); + if (NpcMode.QUEUE1 <= hunt.findNewMode && hunt.findNewMode <= NpcMode.QUEUE20) { + const npcType = NpcType.get(this.type); + const script = ScriptProvider.getByTrigger(ServerTriggerType.AI_QUEUE1 + (hunt.findNewMode - NpcMode.QUEUE1), npcType.id, npcType.category); + if (script) { + this.enqueueScript(script, 0, 0); + } + } else { + this.setInteraction(Interaction.SCRIPT, entity, hunt.findNewMode); + } } this.nextHuntTick = World.currentTick + hunt.rate; } @@ -909,6 +925,9 @@ export default class Npc extends PathingEntity { if (!(player instanceof Player)) { throw new Error('[Npc] huntAll must be of type Player here.'); } + if (hunt.checkNotBusy && player.busy()) { + continue; + } if (hunt.checkAfk && player.zonesAfk()) { continue; @@ -925,7 +944,12 @@ export default class Npc extends PathingEntity { continue; } } - + if (hunt.checkVars && !hunt.checkVars.every(checkVar => { + return checkVar.varId === -1 || hunt.checkHuntCondition(player.getVar(checkVar.varId) as number, checkVar.condition, checkVar.val); + })) { + continue; + } + if (hunt.checkInv !== -1) { let quantity: number = 0; if (hunt.checkObj !== -1) { @@ -933,14 +957,10 @@ export default class Npc extends PathingEntity { } else if (hunt.checkObjParam !== -1) { quantity = player.invTotalParam(hunt.checkInv, hunt.checkObjParam); } - if (quantity < hunt.checkInvMinQuantity || quantity > hunt.checkInvMaxQuantity) { + if (!hunt.checkHuntCondition(quantity, hunt.checkInvCondition, hunt.checkInvVal)) { continue; } } - - if (hunt.checkNotBusy && player.busy()) { - continue; - } players.push(player); } return players; @@ -968,7 +988,7 @@ export default class Npc extends PathingEntity { if (anim == -1 || this.animId == -1 || SeqType.get(anim).priority > SeqType.get(this.animId).priority || SeqType.get(this.animId).priority === 0) { this.animId = anim; this.animDelay = delay; - this.mask |= Npc.ANIM; + this.masks |= InfoProt.NPC_ANIM.id; } } @@ -976,7 +996,7 @@ export default class Npc extends PathingEntity { this.graphicId = spotanim; this.graphicHeight = height; this.graphicDelay = delay; - this.mask |= Npc.SPOTANIM; + this.masks |= InfoProt.NPC_SPOTANIM.id; } applyDamage(damage: number, type: number) { @@ -991,7 +1011,7 @@ export default class Npc extends PathingEntity { this.levels[NpcStat.HITPOINTS] = current - damage; } - this.mask |= Npc.DAMAGE; + this.masks |= InfoProt.NPC_DAMAGE.id; } say(text: string) { @@ -1000,7 +1020,7 @@ export default class Npc extends PathingEntity { } this.chat = text; - this.mask |= Npc.SAY; + this.masks |= InfoProt.NPC_SAY.id; } faceSquare(x: number, z: number) { @@ -1008,12 +1028,12 @@ export default class Npc extends PathingEntity { this.faceZ = z * 2 + 1; this.orientationX = this.faceX; this.orientationZ = this.faceZ; - this.mask |= Npc.FACE_COORD; + this.masks |= InfoProt.NPC_FACE_COORD.id; } changeType(type: number) { this.type = type; - this.mask |= Npc.CHANGE_TYPE; + this.masks |= InfoProt.NPC_CHANGE_TYPE.id; this.uid = (type << 16) | this.nid; const npcType: NpcType = NpcType.get(type); diff --git a/src/lostcity/entity/PathingEntity.ts b/src/lostcity/entity/PathingEntity.ts index ab3db0f677..437d8b064b 100644 --- a/src/lostcity/entity/PathingEntity.ts +++ b/src/lostcity/entity/PathingEntity.ts @@ -49,7 +49,7 @@ export default abstract class PathingEntity extends Entity { readonly blockWalk: BlockWalk; moveStrategy: MoveStrategy; private readonly coordmask: number; - private readonly entitymask: number; + readonly entitymask: number; // runtime properties moveSpeed: MoveSpeed = MoveSpeed.INSTANT; @@ -82,9 +82,8 @@ export default abstract class PathingEntity extends Entity { targetZ: number = -1; apRange: number = 10; apRangeCalled: boolean = false; - alreadyFacedEntity: boolean = false; - mask: number = 0; + masks: number = 0; exactStartX: number = -1; exactStartZ: number = -1; exactEndX: number = -1; @@ -402,6 +401,10 @@ export default abstract class PathingEntity extends Entity { pathToMoveClick(input: number[], needsfinding: boolean): void { if (this.moveStrategy === MoveStrategy.SMART) { + if (this.target && this.target instanceof PathingEntity && Environment.NODE_CLIENT_ROUTEFINDER && CoordGrid.intersects(this.x, this.z, this.width, this.length, this.target.x, this.target.z, this.target.width, this.target.length)) { + this.queueWaypoints(findNaivePath(this.level, this.x, this.z, this.target.x, this.target.z, this.width, this.length, this.target.width, this.target.length, 0, CollisionType.NORMAL)); + return; + } if (needsfinding) { const { x, z } = CoordGrid.unpackCoord(input[0]); this.queueWaypoints(findPath(this.level, this.x, this.z, x, z)); @@ -455,7 +458,11 @@ export default abstract class PathingEntity extends Entity { if (this.moveStrategy === MoveStrategy.SMART) { if (this.target instanceof PathingEntity) { - this.queueWaypoints(findPathToEntity(this.level, this.x, this.z, this.target.x, this.target.z, this.width, this.target.width, this.target.length)); + if (Environment.NODE_CLIENT_ROUTEFINDER && CoordGrid.intersects(this.x, this.z, this.width, this.length, this.target.x, this.target.z, this.target.width, this.target.length)) { + this.queueWaypoints(findNaivePath(this.level, this.x, this.z, this.target.x, this.target.z, this.width, this.length, this.target.width, this.target.length, 0, CollisionType.NORMAL)); + } else { + this.queueWaypoints(findPathToEntity(this.level, this.x, this.z, this.target.x, this.target.z, this.width, this.target.width, this.target.length)); + } } else if (this.target instanceof Loc) { const forceapproach = LocType.get(this.target.type).forceapproach; this.queueWaypoints(findPathToLoc(this.level, this.x, this.z, this.target.x, this.target.z, this.width, this.target.width, this.target.length, this.target.angle, this.target.shape, forceapproach)); @@ -477,6 +484,21 @@ export default abstract class PathingEntity extends Entity { return; } if (this.target instanceof PathingEntity) { + if (this.width > 1 && !CoordGrid.intersects(this.x, this.z, this.width, this.length, this.target.x, this.target.z, this.target.width, this.target.length)) { + // west/east + let dir = CoordGrid.face(this.x, 0, this.target.x, 0); + const distanceToTarget = CoordGrid.distanceTo({x: this.x, z: this.z, width: this.width, length: this.length}, {x: this.target.x, z: this.target.z, width: this.target.width, length: this.target.length}); + if (canTravel(this.level, this.x, this.z, CoordGrid.deltaX(dir), 0, this.width, extraFlag, collisionStrategy) || distanceToTarget <= 1) { + this.queueWaypoint(CoordGrid.moveX(this.x, dir), this.z); + return; + } + // north/south + dir = CoordGrid.face(0, this.z, 0, this.target.z); + if (canTravel(this.level, this.x, this.z, 0, CoordGrid.deltaZ(dir), this.width, extraFlag, collisionStrategy)) { + this.queueWaypoint(this.x, CoordGrid.moveZ(this.z, dir)); + return; + } + } this.queueWaypoints(findNaivePath(this.level, this.x, this.z, this.target.x, this.target.z, this.width, this.length, this.target.width, this.target.length, extraFlag, collisionStrategy)); } else { this.queueWaypoint(this.target.x, this.target.z); @@ -513,13 +535,13 @@ export default abstract class PathingEntity extends Entity { const pid: number = target.pid + 32768; if (this.faceEntity !== pid) { this.faceEntity = pid; - this.mask |= this.entitymask; + this.masks |= this.entitymask; } } else if (target instanceof Npc) { const nid: number = target.nid; if (this.faceEntity !== nid) { this.faceEntity = nid; - this.mask |= this.entitymask; + this.masks |= this.entitymask; } } else { // direction when the player is first observed (updates on movement) @@ -532,7 +554,7 @@ export default abstract class PathingEntity extends Entity { if (interaction === Interaction.ENGINE) { // mask updates will be sent every time from the packet handler - this.mask |= this.coordmask; + this.masks |= this.coordmask; } } @@ -549,7 +571,6 @@ export default abstract class PathingEntity extends Entity { this.targetZ = -1; this.apRange = 10; this.apRangeCalled = false; - this.alreadyFacedEntity = true; } protected getCollisionStrategy(): CollisionType | null { @@ -584,7 +605,7 @@ export default abstract class PathingEntity extends Entity { this.interacted = false; this.apRangeCalled = false; - this.mask = 0; + this.masks = 0; this.exactStartX = -1; this.exactStartZ = -1; this.exactEndX = -1; @@ -603,10 +624,9 @@ export default abstract class PathingEntity extends Entity { this.graphicHeight = -1; this.graphicDelay = -1; - if (this.alreadyFacedEntity && !this.target && this.faceEntity !== -1) { - this.mask |= this.entitymask; + if (!this.target && this.faceEntity !== -1) { + this.masks |= this.entitymask; this.faceEntity = -1; - this.alreadyFacedEntity = false; } } diff --git a/src/lostcity/entity/Player.ts b/src/lostcity/entity/Player.ts index 50f6b893a9..8f97ad0c84 100644 --- a/src/lostcity/entity/Player.ts +++ b/src/lostcity/entity/Player.ts @@ -1,7 +1,7 @@ import 'dotenv/config'; -import Packet from '#jagex2/io/Packet.js'; -import {fromBase37, toDisplayName} from '#jagex2/jstring/JString.js'; +import Packet from '#jagex/io/Packet.js'; +import {fromBase37, toDisplayName} from '#jagex/jstring/JString.js'; import FontType from '#lostcity/cache/config/FontType.js'; import Component from '#lostcity/cache/config/Component.js'; @@ -40,8 +40,8 @@ import ScriptPointer from '#lostcity/engine/script/ScriptPointer.js'; import Environment from '#lostcity/util/Environment.js'; -import LinkList from '#jagex2/datastruct/LinkList.js'; -import DoublyLinkList from '#jagex2/datastruct/DoublyLinkList.js'; +import LinkList from '#jagex/datastruct/LinkList.js'; +import DoublyLinkList from '#jagex/datastruct/DoublyLinkList.js'; import {CollisionFlag} from '@2004scape/rsmod-pathfinder'; import {PRELOADED, PRELOADED_CRC} from '#lostcity/server/PreloadedPacks.js'; @@ -68,6 +68,7 @@ import BuildArea from '#lostcity/entity/BuildArea.js'; import ChatFilterSettings from '#lostcity/network/outgoing/model/ChatFilterSettings.js'; import { ChatModePrivate, ChatModePublic, ChatModeTradeDuel } from '#lostcity/util/ChatModes.js'; import { isNetworkPlayer } from '#lostcity/entity/NetworkPlayer.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; const levelExperience = new Int32Array(99); @@ -94,18 +95,7 @@ export function getExpByLevel(level: number) { } export default class Player extends PathingEntity { - static readonly APPEARANCE = 0x1; - static readonly ANIM = 0x2; - static readonly FACE_ENTITY = 0x4; - static readonly SAY = 0x8; - static readonly DAMAGE = 0x10; - static readonly FACE_COORD = 0x20; - static readonly CHAT = 0x40; - static readonly BIG_UPDATE = 0x80; - static readonly SPOTANIM = 0x100; - static readonly EXACT_MOVE = 0x200; - - static SKILLS = [ + static readonly SKILLS = [ 'attack', 'defence', 'strength', @@ -129,7 +119,7 @@ export default class Player extends PathingEntity { 'runecraft' ]; - static DESIGN_BODY_COLORS: number[][] = [ + static readonly DESIGN_BODY_COLORS: number[][] = [ [6798, 107, 10283, 16, 4797, 7744, 5799, 4634, 33697, 22433, 2983, 54193], [8741, 12, 64030, 43162, 7735, 8404, 1701, 38430, 24094, 10153, 56621, 4783, 1341, 16578, 35003, 25239], [25238, 8742, 12, 64030, 43162, 7735, 8404, 1701, 38430, 24094, 10153, 56621, 4783, 1341, 16578, 35003], @@ -140,7 +130,7 @@ export default class Player extends PathingEntity { save() { const sav = Packet.alloc(1); sav.p2(0x2004); // magic - sav.p2(4); // version + sav.p2(5); // version sav.p2(this.x); sav.p2(this.z); @@ -181,6 +171,7 @@ export default class Player extends PathingEntity { } sav.p2(typeId); + sav.p2(inventory.capacity); for (let slot = 0; slot < inventory.capacity; slot++) { const obj = inventory.get(slot); if (!obj) { @@ -348,8 +339,7 @@ export default class Player extends PathingEntity { lastZone: number = -1; constructor(username: string, username37: bigint) { - super(0, 3094, 3106, 1, 1, EntityLifeCycle.FOREVER, MoveRestrict.NORMAL, BlockWalk.NPC, MoveStrategy.SMART, Player.FACE_COORD, Player.FACE_ENTITY); // tutorial island. - + super(0, 3094, 3106, 1, 1, EntityLifeCycle.FOREVER, MoveRestrict.NORMAL, BlockWalk.NPC, MoveStrategy.SMART, InfoProt.PLAYER_FACE_COORD.id, InfoProt.PLAYER_FACE_ENTITY.id); // tutorial island. this.username = username; this.username37 = username37; this.displayName = toDisplayName(username); @@ -570,7 +560,7 @@ export default class Player extends PathingEntity { } if (!this.hasWaypoints()) { this.moveClickRequest = false; - this.unsetMapFlag(); + // this.unsetMapFlag(); // should be handled client-sided } return moved; } @@ -909,10 +899,7 @@ export default class Player extends PathingEntity { this.processWalktrigger(); } const moved: boolean = this.updateMovement(false); - if (moved) { - // we need to keep the mask if the player had to move. - this.alreadyFacedEntity = false; - } else if (walktrigger !== -1 && this.target instanceof Player && (this.x !== this.target.lastStepX || this.z !== this.target.lastStepZ)) { + if (!moved && walktrigger !== -1 && this.target instanceof Player && (this.x !== this.target.lastStepX || this.z !== this.target.lastStepZ)) { this.clearInteraction(); this.unsetMapFlag(); } @@ -989,10 +976,6 @@ export default class Player extends PathingEntity { this.interacted = false; this.processWalktrigger(); moved = this.updateMovement(); - if (moved) { - // we need to keep the mask if the player had to move. - this.alreadyFacedEntity = false; - } if (opTrigger && (this.target instanceof PathingEntity || !moved) && this.inOperableDistance(this.target)) { const target = this.target; @@ -1167,7 +1150,7 @@ export default class Player extends PathingEntity { stream.p8(this.username37); stream.p1(this.combatLevel); - this.mask |= Player.APPEARANCE; + this.masks |= InfoProt.PLAYER_APPEARANCE.id; this.appearance = new Uint8Array(stream.pos); stream.pos = 0; @@ -1488,7 +1471,7 @@ export default class Player extends PathingEntity { const varp = VarPlayerType.get(id); if (varp.type === ScriptVarType.STRING && typeof value === 'string') { - this.varsString[varp.id] = value as string; + this.varsString[varp.id] = value; } else if (typeof value === 'number') { this.vars[varp.id] = value; @@ -1537,6 +1520,7 @@ export default class Player extends PathingEntity { // replenish 1 of the stat upon levelup. this.levels[stat] += 1; } + this.changeStat(stat); const script = ScriptProvider.getByTriggerSpecific(ServerTriggerType.ADVANCESTAT, stat, -1); if (script) { @@ -1550,6 +1534,13 @@ export default class Player extends PathingEntity { } } + changeStat(stat: number) { + const script = ScriptProvider.getByTrigger(ServerTriggerType.CHANGESTAT, stat, -1); + if (script) { + this.enqueueScript(script, PlayerQueueType.ENGINE); + } + } + setLevel(stat: number, level: number) { level = Math.min(99, Math.max(1, level)); @@ -1571,7 +1562,7 @@ export default class Player extends PathingEntity { if (anim == -1 || this.animId == -1 || SeqType.get(anim).priority > SeqType.get(this.animId).priority || SeqType.get(this.animId).priority === 0) { this.animId = anim; this.animDelay = delay; - this.mask |= Player.ANIM; + this.masks |= InfoProt.PLAYER_ANIM.id; } } @@ -1579,7 +1570,7 @@ export default class Player extends PathingEntity { this.graphicId = spotanim; this.graphicHeight = height; this.graphicDelay = delay; - this.mask |= Player.SPOTANIM; + this.masks |= InfoProt.PLAYER_SPOTANIM.id; } applyDamage(damage: number, type: number) { @@ -1594,12 +1585,12 @@ export default class Player extends PathingEntity { this.levels[PlayerStat.HITPOINTS] = current - damage; } - this.mask |= Player.DAMAGE; + this.masks |= InfoProt.PLAYER_DAMAGE.id; } say(message: string) { this.chat = message; - this.mask |= Player.SAY; + this.masks |= InfoProt.PLAYER_SAY.id; } faceSquare(x: number, z: number) { @@ -1607,7 +1598,7 @@ export default class Player extends PathingEntity { this.faceZ = z * 2 + 1; this.orientationX = this.faceX; this.orientationZ = this.faceZ; - this.mask |= Player.FACE_COORD; + this.masks |= InfoProt.PLAYER_FACE_COORD.id; } playSong(name: string) { @@ -1689,7 +1680,7 @@ export default class Player extends PathingEntity { this.exactMoveStart = startCycle; this.exactMoveEnd = endCycle; this.exactMoveDirection = direction; - this.mask |= Player.EXACT_MOVE; + this.masks |= InfoProt.PLAYER_EXACT_MOVE.id; // todo: interpolate over time? instant teleport? verify with true tile on osrs this.x = endX; diff --git a/src/lostcity/entity/PlayerLoading.ts b/src/lostcity/entity/PlayerLoading.ts index 9337af1510..82d842e663 100644 --- a/src/lostcity/entity/PlayerLoading.ts +++ b/src/lostcity/entity/PlayerLoading.ts @@ -1,8 +1,8 @@ import 'dotenv/config'; import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; -import { fromBase37, toBase37 } from '#jagex2/jstring/JString.js'; +import Packet from '#jagex/io/Packet.js'; +import { fromBase37, toBase37 } from '#jagex/jstring/JString.js'; import ClientSocket from '#lostcity/server/ClientSocket.js'; @@ -13,6 +13,7 @@ import Player, { getExpByLevel, getLevelByExp } from '#lostcity/entity/Player.js import PlayerStat from '#lostcity/entity/PlayerStat.js'; import Environment from '#lostcity/util/Environment.js'; +import InvType from '#lostcity/cache/config/InvType.js'; export class PlayerLoading { /** @@ -68,7 +69,7 @@ export class PlayerLoading { } const version = sav.g2(); - if (version > 4) { + if (version > 5) { throw new Error('Unsupported player save format'); } @@ -114,24 +115,27 @@ export class PlayerLoading { const invCount = sav.g1(); for (let i = 0; i < invCount; i++) { const type = sav.g2(); + const size = version >= 5 ? sav.g2() : InvType.get(type).size; + + const objs = []; + for (let slot = 0; slot < size; slot++) { + const id = sav.g2() - 1; + if (id === -1) { + continue; + } + + let count = sav.g1(); + if (count === 255) { + count = sav.g4(); + } + + objs.push({ slot, id, count }); + } const inv = player.getInventory(type); if (inv) { - for (let j = 0; j < inv.capacity; j++) { - const id = sav.g2(); - if (id === 0) { - continue; - } - - let count = sav.g1(); - if (count === 255) { - count = sav.g4(); - } - - inv.set(j, { - id: id - 1, - count - }); + for (const obj of objs) { + inv.set(obj.slot, { id: obj.id, count: obj.count }); } } } diff --git a/src/lostcity/network/225/incoming/codec/ChatSetModeDecoder.ts b/src/lostcity/network/225/incoming/codec/ChatSetModeDecoder.ts index 3b898b8273..ad4643970c 100644 --- a/src/lostcity/network/225/incoming/codec/ChatSetModeDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/ChatSetModeDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import ChatSetMode from '#lostcity/network/incoming/model/ChatSetMode.js'; diff --git a/src/lostcity/network/225/incoming/codec/ClientCheatDecoder.ts b/src/lostcity/network/225/incoming/codec/ClientCheatDecoder.ts index 679c4d26d1..f6b4812d6d 100644 --- a/src/lostcity/network/225/incoming/codec/ClientCheatDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/ClientCheatDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import ClientCheat from '#lostcity/network/incoming/model/ClientCheat.js'; diff --git a/src/lostcity/network/225/incoming/codec/FriendListAddDecoder.ts b/src/lostcity/network/225/incoming/codec/FriendListAddDecoder.ts index 3480d1b7ea..505ea9164a 100644 --- a/src/lostcity/network/225/incoming/codec/FriendListAddDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/FriendListAddDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import FriendListAdd from '#lostcity/network/incoming/model/FriendListAdd.js'; diff --git a/src/lostcity/network/225/incoming/codec/FriendListDelDecoder.ts b/src/lostcity/network/225/incoming/codec/FriendListDelDecoder.ts index 141f647d11..d9e7df2e87 100644 --- a/src/lostcity/network/225/incoming/codec/FriendListDelDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/FriendListDelDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import FriendListDel from '#lostcity/network/incoming/model/FriendListDel.js'; diff --git a/src/lostcity/network/225/incoming/codec/IfButtonDecoder.ts b/src/lostcity/network/225/incoming/codec/IfButtonDecoder.ts index 3a55421dae..ed7f60016c 100644 --- a/src/lostcity/network/225/incoming/codec/IfButtonDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/IfButtonDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import IfButton from '#lostcity/network/incoming/model/IfButton.js'; diff --git a/src/lostcity/network/225/incoming/codec/IfPlayerDesignDecoder.ts b/src/lostcity/network/225/incoming/codec/IfPlayerDesignDecoder.ts index 95e998ee90..66bd794cea 100644 --- a/src/lostcity/network/225/incoming/codec/IfPlayerDesignDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/IfPlayerDesignDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import IfPlayerDesign from '#lostcity/network/incoming/model/IfPlayerDesign.js'; diff --git a/src/lostcity/network/225/incoming/codec/IgnoreListAddDecoder.ts b/src/lostcity/network/225/incoming/codec/IgnoreListAddDecoder.ts index ff7e263ff0..b5f9ee09c8 100644 --- a/src/lostcity/network/225/incoming/codec/IgnoreListAddDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/IgnoreListAddDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import IgnoreListAdd from '#lostcity/network/incoming/model/IgnoreListAdd.js'; diff --git a/src/lostcity/network/225/incoming/codec/IgnoreListDelDecoder.ts b/src/lostcity/network/225/incoming/codec/IgnoreListDelDecoder.ts index 19083085a0..70724e28f8 100644 --- a/src/lostcity/network/225/incoming/codec/IgnoreListDelDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/IgnoreListDelDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import IgnoreListDel from '#lostcity/network/incoming/model/IgnoreListDel.js'; diff --git a/src/lostcity/network/225/incoming/codec/InvButtonDDecoder.ts b/src/lostcity/network/225/incoming/codec/InvButtonDDecoder.ts index 790b1babf8..249f7c45a1 100644 --- a/src/lostcity/network/225/incoming/codec/InvButtonDDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/InvButtonDDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import InvButtonD from '#lostcity/network/incoming/model/InvButtonD.js'; diff --git a/src/lostcity/network/225/incoming/codec/InvButtonDecoder.ts b/src/lostcity/network/225/incoming/codec/InvButtonDecoder.ts index 5498ad4a33..c0f1a21753 100644 --- a/src/lostcity/network/225/incoming/codec/InvButtonDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/InvButtonDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import InvButton from '#lostcity/network/incoming/model/InvButton.js'; diff --git a/src/lostcity/network/225/incoming/codec/MessagePrivateDecoder.ts b/src/lostcity/network/225/incoming/codec/MessagePrivateDecoder.ts index 93608960a5..0434958962 100644 --- a/src/lostcity/network/225/incoming/codec/MessagePrivateDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/MessagePrivateDecoder.ts @@ -1,8 +1,8 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import MessagePrivate from '#lostcity/network/incoming/model/MessagePrivate.js'; -import WordPack from '#jagex2/wordenc/WordPack.js'; +import WordPack from '#jagex/wordenc/WordPack.js'; export default class MessagePrivateDecoder extends MessageDecoder { prot = ClientProt.MESSAGE_PRIVATE; diff --git a/src/lostcity/network/225/incoming/codec/MessagePublicDecoder.ts b/src/lostcity/network/225/incoming/codec/MessagePublicDecoder.ts index 503b178925..4b0eaa9c57 100644 --- a/src/lostcity/network/225/incoming/codec/MessagePublicDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/MessagePublicDecoder.ts @@ -1,8 +1,8 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import MessagePublic from '#lostcity/network/incoming/model/MessagePublic.js'; -import WordPack from '#jagex2/wordenc/WordPack.js'; +import WordPack from '#jagex/wordenc/WordPack.js'; export default class MessagePublicDecoder extends MessageDecoder { prot = ClientProt.MESSAGE_PUBLIC; diff --git a/src/lostcity/network/225/incoming/codec/MoveClickDecoder.ts b/src/lostcity/network/225/incoming/codec/MoveClickDecoder.ts index e81538821f..fd5dcd9979 100644 --- a/src/lostcity/network/225/incoming/codec/MoveClickDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/MoveClickDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import MoveClick from '#lostcity/network/incoming/model/MoveClick.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpHeldDecoder.ts b/src/lostcity/network/225/incoming/codec/OpHeldDecoder.ts index 25b687c732..5fba5b8e13 100644 --- a/src/lostcity/network/225/incoming/codec/OpHeldDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpHeldDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpHeld from '#lostcity/network/incoming/model/OpHeld.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpHeldTDecoder.ts b/src/lostcity/network/225/incoming/codec/OpHeldTDecoder.ts index 9322e1a48a..a58cd5af87 100644 --- a/src/lostcity/network/225/incoming/codec/OpHeldTDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpHeldTDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpHeldT from '#lostcity/network/incoming/model/OpHeldT.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpHeldUDecoder.ts b/src/lostcity/network/225/incoming/codec/OpHeldUDecoder.ts index 51adc92de0..95ad4bcea2 100644 --- a/src/lostcity/network/225/incoming/codec/OpHeldUDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpHeldUDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpHeldU from '#lostcity/network/incoming/model/OpHeldU.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpLocDecoder.ts b/src/lostcity/network/225/incoming/codec/OpLocDecoder.ts index cd861b6761..4415c16afa 100644 --- a/src/lostcity/network/225/incoming/codec/OpLocDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpLocDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpLoc from '#lostcity/network/incoming/model/OpLoc.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpLocTDecoder.ts b/src/lostcity/network/225/incoming/codec/OpLocTDecoder.ts index 915f12b5dd..a3f28a784d 100644 --- a/src/lostcity/network/225/incoming/codec/OpLocTDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpLocTDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpLocT from '#lostcity/network/incoming/model/OpLocT.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpLocUDecoder.ts b/src/lostcity/network/225/incoming/codec/OpLocUDecoder.ts index eec84ce90a..42152888aa 100644 --- a/src/lostcity/network/225/incoming/codec/OpLocUDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpLocUDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpLocU from '#lostcity/network/incoming/model/OpLocU.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpNpcDecoder.ts b/src/lostcity/network/225/incoming/codec/OpNpcDecoder.ts index 61f5d80cdb..116fa55cf3 100644 --- a/src/lostcity/network/225/incoming/codec/OpNpcDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpNpcDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpNpc from '#lostcity/network/incoming/model/OpNpc.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpNpcTDecoder.ts b/src/lostcity/network/225/incoming/codec/OpNpcTDecoder.ts index 53fd7004c2..05241fe96c 100644 --- a/src/lostcity/network/225/incoming/codec/OpNpcTDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpNpcTDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpNpcT from '#lostcity/network/incoming/model/OpNpcT.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpNpcUDecoder.ts b/src/lostcity/network/225/incoming/codec/OpNpcUDecoder.ts index fcfedb8cb9..8d64648154 100644 --- a/src/lostcity/network/225/incoming/codec/OpNpcUDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpNpcUDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpNpcU from '#lostcity/network/incoming/model/OpNpcU.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpObjDecoder.ts b/src/lostcity/network/225/incoming/codec/OpObjDecoder.ts index 443bdb70e0..b96485bcd5 100644 --- a/src/lostcity/network/225/incoming/codec/OpObjDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpObjDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpObj from '#lostcity/network/incoming/model/OpObj.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpObjTDecoder.ts b/src/lostcity/network/225/incoming/codec/OpObjTDecoder.ts index 6f1bede84c..f912b4ce83 100644 --- a/src/lostcity/network/225/incoming/codec/OpObjTDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpObjTDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpObjT from '#lostcity/network/incoming/model/OpObjT.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpObjUDecoder.ts b/src/lostcity/network/225/incoming/codec/OpObjUDecoder.ts index 8ed1795e2b..b6ab121684 100644 --- a/src/lostcity/network/225/incoming/codec/OpObjUDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpObjUDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpObjU from '#lostcity/network/incoming/model/OpObjU.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpPlayerDecoder.ts b/src/lostcity/network/225/incoming/codec/OpPlayerDecoder.ts index 11a47163cc..b7fc7614fd 100644 --- a/src/lostcity/network/225/incoming/codec/OpPlayerDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpPlayerDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpPlayer from '#lostcity/network/incoming/model/OpPlayer.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpPlayerTDecoder.ts b/src/lostcity/network/225/incoming/codec/OpPlayerTDecoder.ts index 2df67486d0..33599e9039 100644 --- a/src/lostcity/network/225/incoming/codec/OpPlayerTDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpPlayerTDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpPlayerT from '#lostcity/network/incoming/model/OpPlayerT.js'; diff --git a/src/lostcity/network/225/incoming/codec/OpPlayerUDecoder.ts b/src/lostcity/network/225/incoming/codec/OpPlayerUDecoder.ts index 6e6b1a42ac..72f1ad92c9 100644 --- a/src/lostcity/network/225/incoming/codec/OpPlayerUDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/OpPlayerUDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import OpPlayerU from '#lostcity/network/incoming/model/OpPlayerU.js'; diff --git a/src/lostcity/network/225/incoming/codec/RebuildGetMapsDecoder.ts b/src/lostcity/network/225/incoming/codec/RebuildGetMapsDecoder.ts index 403247583c..f0186788f2 100644 --- a/src/lostcity/network/225/incoming/codec/RebuildGetMapsDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/RebuildGetMapsDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import RebuildGetMaps from '#lostcity/network/incoming/model/RebuildGetMaps.js'; diff --git a/src/lostcity/network/225/incoming/codec/ResumePCountDialogDecoder.ts b/src/lostcity/network/225/incoming/codec/ResumePCountDialogDecoder.ts index 3eccc65c9f..0ab3976e68 100644 --- a/src/lostcity/network/225/incoming/codec/ResumePCountDialogDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/ResumePCountDialogDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import ResumePCountDialog from '#lostcity/network/incoming/model/ResumePCountDialog.js'; diff --git a/src/lostcity/network/225/incoming/codec/TutorialClickSideDecoder.ts b/src/lostcity/network/225/incoming/codec/TutorialClickSideDecoder.ts index 427bd01916..66f7698cea 100644 --- a/src/lostcity/network/225/incoming/codec/TutorialClickSideDecoder.ts +++ b/src/lostcity/network/225/incoming/codec/TutorialClickSideDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import MessageDecoder from '#lostcity/network/incoming/codec/MessageDecoder.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; import TutorialClickSide from '#lostcity/network/incoming/model/TutorialClickSide.js'; diff --git a/src/lostcity/network/225/incoming/handler/ClientCheatHandler.ts b/src/lostcity/network/225/incoming/handler/ClientCheatHandler.ts index 7792d09e2b..c12bf95325 100644 --- a/src/lostcity/network/225/incoming/handler/ClientCheatHandler.ts +++ b/src/lostcity/network/225/incoming/handler/ClientCheatHandler.ts @@ -21,7 +21,7 @@ import ScriptRunner from '#lostcity/engine/script/ScriptRunner.js'; import PlayerStat from '#lostcity/entity/PlayerStat.js'; import MoveStrategy from '#lostcity/entity/MoveStrategy.js'; import { PlayerLoading } from '#lostcity/entity/PlayerLoading.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { printInfo } from '#lostcity/util/Logger.js'; import {findPath, isMapBlocked} from '#lostcity/engine/GameMap.js'; @@ -45,10 +45,6 @@ export default class ClientCheatHandler extends MessageHandler { // developer commands if (cmd === 'reload' && !Environment.STANDALONE_BUNDLE && !Environment.NODE_PRODUCTION) { World.reload(); - - // todo: we're probably reloading twice now, just to get count? - const count = ScriptProvider.load('data/pack'); - player.messageGame(`Reloaded ${count} scripts.`); } else if (cmd === 'rebuild' && !Environment.STANDALONE_BUNDLE && !Environment.NODE_PRODUCTION) { player.messageGame('Rebuilding scripts...'); diff --git a/src/lostcity/network/225/incoming/handler/MessagePublicHandler.ts b/src/lostcity/network/225/incoming/handler/MessagePublicHandler.ts index a238b140b0..92e3bcbbdb 100644 --- a/src/lostcity/network/225/incoming/handler/MessagePublicHandler.ts +++ b/src/lostcity/network/225/incoming/handler/MessagePublicHandler.ts @@ -1,9 +1,10 @@ import MessageHandler from '#lostcity/network/incoming/handler/MessageHandler.js'; import Player from '#lostcity/entity/Player.js'; import MessagePublic from '#lostcity/network/incoming/model/MessagePublic.js'; -import Packet from '#jagex2/io/Packet.js'; -import WordPack from '#jagex2/wordenc/WordPack.js'; +import Packet from '#jagex/io/Packet.js'; +import WordPack from '#jagex/wordenc/WordPack.js'; import WordEnc from '#lostcity/cache/wordenc/WordEnc.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; export default class MessagePublicHandler extends MessageHandler { handle(message: MessagePublic, player: Player): boolean { @@ -22,7 +23,7 @@ export default class MessagePublicHandler extends MessageHandler out.pos = 0; out.gdata(player.message, 0, player.message.length); out.release(); - player.mask |= Player.CHAT; + player.masks |= InfoProt.PLAYER_CHAT.id; return true; } } diff --git a/src/lostcity/network/225/incoming/handler/OpHeldHandler.ts b/src/lostcity/network/225/incoming/handler/OpHeldHandler.ts index 5749e12679..8e7582f1a0 100644 --- a/src/lostcity/network/225/incoming/handler/OpHeldHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpHeldHandler.ts @@ -41,6 +41,8 @@ export default class OpHeldHandler extends MessageHandler { player.clearInteraction(); player.closeModal(); + player.faceEntity = -1; + player.masks |= player.entitymask; let trigger: ServerTriggerType; if (message.op === 1) { diff --git a/src/lostcity/network/225/incoming/handler/OpHeldTHandler.ts b/src/lostcity/network/225/incoming/handler/OpHeldTHandler.ts index 950102fbdc..79aa4727ad 100644 --- a/src/lostcity/network/225/incoming/handler/OpHeldTHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpHeldTHandler.ts @@ -44,6 +44,8 @@ export default class OpHeldTHandler extends MessageHandler { player.clearInteraction(); player.closeModal(); + player.faceEntity = -1; + player.masks |= player.entitymask; const script = ScriptProvider.getByTrigger(ServerTriggerType.OPHELDT, spellComId, -1); if (script) { diff --git a/src/lostcity/network/225/incoming/handler/OpHeldUHandler.ts b/src/lostcity/network/225/incoming/handler/OpHeldUHandler.ts index e4a0c8fd52..6b5a2b0595 100644 --- a/src/lostcity/network/225/incoming/handler/OpHeldUHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpHeldUHandler.ts @@ -67,6 +67,8 @@ export default class OpHeldUHandler extends MessageHandler { player.clearInteraction(); player.closeModal(); + player.faceEntity = -1; + player.masks |= player.entitymask; if ((objType.members || useObjType.members) && !Environment.NODE_MEMBERS) { player.messageGame("To use this item please login to a members' server."); diff --git a/src/lostcity/network/225/incoming/handler/OpNpcHandler.ts b/src/lostcity/network/225/incoming/handler/OpNpcHandler.ts index 3ba259a139..b161d4185a 100644 --- a/src/lostcity/network/225/incoming/handler/OpNpcHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpNpcHandler.ts @@ -22,7 +22,7 @@ export default class OpNpcHandler extends MessageHandler { return false; } - if (!player.buildArea.npcs.has(npc.nid)) { + if (!player.buildArea.npcs.has(npc)) { player.unsetMapFlag(); return false; } diff --git a/src/lostcity/network/225/incoming/handler/OpNpcTHandler.ts b/src/lostcity/network/225/incoming/handler/OpNpcTHandler.ts index f8cf69bfd8..f1b862a355 100644 --- a/src/lostcity/network/225/incoming/handler/OpNpcTHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpNpcTHandler.ts @@ -28,7 +28,7 @@ export default class OpNpcTHandler extends MessageHandler { return false; } - if (!player.buildArea.npcs.has(npc.nid)) { + if (!player.buildArea.npcs.has(npc)) { player.unsetMapFlag(); return false; } diff --git a/src/lostcity/network/225/incoming/handler/OpNpcUHandler.ts b/src/lostcity/network/225/incoming/handler/OpNpcUHandler.ts index e0a0c911ff..40ac3ef618 100644 --- a/src/lostcity/network/225/incoming/handler/OpNpcUHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpNpcUHandler.ts @@ -42,7 +42,7 @@ export default class OpNpcUHandler extends MessageHandler { return false; } - if (!player.buildArea.npcs.has(npc.nid)) { + if (!player.buildArea.npcs.has(npc)) { player.unsetMapFlag(); return false; } diff --git a/src/lostcity/network/225/incoming/handler/OpPlayerHandler.ts b/src/lostcity/network/225/incoming/handler/OpPlayerHandler.ts index 6ec3885fa5..2e53668bfd 100644 --- a/src/lostcity/network/225/incoming/handler/OpPlayerHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpPlayerHandler.ts @@ -21,7 +21,7 @@ export default class OpPlayerHandler extends MessageHandler { return false; } - if (!player.buildArea.players.has(other.uid)) { + if (!player.buildArea.players.has(other)) { player.unsetMapFlag(); return false; } diff --git a/src/lostcity/network/225/incoming/handler/OpPlayerTHandler.ts b/src/lostcity/network/225/incoming/handler/OpPlayerTHandler.ts index 91d4277ffe..81f769eec8 100644 --- a/src/lostcity/network/225/incoming/handler/OpPlayerTHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpPlayerTHandler.ts @@ -28,7 +28,7 @@ export default class OpPlayerTHandler extends MessageHandler { return false; } - if (!player.buildArea.players.has(other.uid)) { + if (!player.buildArea.players.has(other)) { player.unsetMapFlag(); return false; } diff --git a/src/lostcity/network/225/incoming/handler/OpPlayerUHandler.ts b/src/lostcity/network/225/incoming/handler/OpPlayerUHandler.ts index da7ac36e96..434ac70726 100644 --- a/src/lostcity/network/225/incoming/handler/OpPlayerUHandler.ts +++ b/src/lostcity/network/225/incoming/handler/OpPlayerUHandler.ts @@ -42,7 +42,7 @@ export default class OpPlayerUHandler extends MessageHandler { return false; } - if (!player.buildArea.players.has(other.uid)) { + if (!player.buildArea.players.has(other)) { player.unsetMapFlag(); return false; } diff --git a/src/lostcity/network/225/outgoing/codec/CamLookAtEncoder.ts b/src/lostcity/network/225/outgoing/codec/CamLookAtEncoder.ts index b3862e3db9..f760ffabd9 100644 --- a/src/lostcity/network/225/outgoing/codec/CamLookAtEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/CamLookAtEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import CamLookAt from '#lostcity/network/outgoing/model/CamLookAt.js'; diff --git a/src/lostcity/network/225/outgoing/codec/CamMoveToEncoder.ts b/src/lostcity/network/225/outgoing/codec/CamMoveToEncoder.ts index 35bc2652e7..92701f3f84 100644 --- a/src/lostcity/network/225/outgoing/codec/CamMoveToEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/CamMoveToEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import CamMoveTo from '#lostcity/network/outgoing/model/CamMoveTo.js'; diff --git a/src/lostcity/network/225/outgoing/codec/CamResetEncoder.ts b/src/lostcity/network/225/outgoing/codec/CamResetEncoder.ts index 8dba637dfc..4940166c13 100644 --- a/src/lostcity/network/225/outgoing/codec/CamResetEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/CamResetEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import CamReset from '#lostcity/network/outgoing/model/CamReset.js'; diff --git a/src/lostcity/network/225/outgoing/codec/CamShakeEncoder.ts b/src/lostcity/network/225/outgoing/codec/CamShakeEncoder.ts index cca08a6937..44e3f0bef5 100644 --- a/src/lostcity/network/225/outgoing/codec/CamShakeEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/CamShakeEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import CamShake from '#lostcity/network/outgoing/model/CamShake.js'; diff --git a/src/lostcity/network/225/outgoing/codec/ChatFilterSettingsEncoder.ts b/src/lostcity/network/225/outgoing/codec/ChatFilterSettingsEncoder.ts index 0476b9691a..a328938590 100644 --- a/src/lostcity/network/225/outgoing/codec/ChatFilterSettingsEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/ChatFilterSettingsEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import ChatFilterSettings from '#lostcity/network/outgoing/model/ChatFilterSettings.js'; diff --git a/src/lostcity/network/225/outgoing/codec/DataLandDoneEncoder.ts b/src/lostcity/network/225/outgoing/codec/DataLandDoneEncoder.ts index d193543028..1b6aed7b6a 100644 --- a/src/lostcity/network/225/outgoing/codec/DataLandDoneEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/DataLandDoneEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import DataLandDone from '#lostcity/network/outgoing/model/DataLandDone.js'; diff --git a/src/lostcity/network/225/outgoing/codec/DataLandEncoder.ts b/src/lostcity/network/225/outgoing/codec/DataLandEncoder.ts index 52b0829350..acde532bf4 100644 --- a/src/lostcity/network/225/outgoing/codec/DataLandEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/DataLandEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import DataLand from '#lostcity/network/outgoing/model/DataLand.js'; diff --git a/src/lostcity/network/225/outgoing/codec/DataLocDoneEncoder.ts b/src/lostcity/network/225/outgoing/codec/DataLocDoneEncoder.ts index 7705cea2e8..f8d29e0b50 100644 --- a/src/lostcity/network/225/outgoing/codec/DataLocDoneEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/DataLocDoneEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import DataLocDone from '#lostcity/network/outgoing/model/DataLocDone.js'; diff --git a/src/lostcity/network/225/outgoing/codec/DataLocEncoder.ts b/src/lostcity/network/225/outgoing/codec/DataLocEncoder.ts index f20788f500..bd93c6aab3 100644 --- a/src/lostcity/network/225/outgoing/codec/DataLocEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/DataLocEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import DataLoc from '#lostcity/network/outgoing/model/DataLoc.js'; diff --git a/src/lostcity/network/225/outgoing/codec/EnableTrackingEncoder.ts b/src/lostcity/network/225/outgoing/codec/EnableTrackingEncoder.ts index 642fd221ae..a949947251 100644 --- a/src/lostcity/network/225/outgoing/codec/EnableTrackingEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/EnableTrackingEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import EnableTracking from '#lostcity/network/outgoing/model/EnableTracking.js'; diff --git a/src/lostcity/network/225/outgoing/codec/FinishTrackingEncoder.ts b/src/lostcity/network/225/outgoing/codec/FinishTrackingEncoder.ts index d7b12bf65b..09ac288417 100644 --- a/src/lostcity/network/225/outgoing/codec/FinishTrackingEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/FinishTrackingEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import FinishTracking from '#lostcity/network/outgoing/model/FinishTracking.js'; diff --git a/src/lostcity/network/225/outgoing/codec/HintArrowEncoder.ts b/src/lostcity/network/225/outgoing/codec/HintArrowEncoder.ts index 91863c2a99..43d5ab44dc 100644 --- a/src/lostcity/network/225/outgoing/codec/HintArrowEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/HintArrowEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import HintArrow from '#lostcity/network/outgoing/model/HintArrow.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfCloseEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfCloseEncoder.ts index c76a53613f..36be191b4e 100644 --- a/src/lostcity/network/225/outgoing/codec/IfCloseEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfCloseEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfClose from '#lostcity/network/outgoing/model/IfClose.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfOpenChatEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfOpenChatEncoder.ts index bb57f37cdd..1b4077503f 100644 --- a/src/lostcity/network/225/outgoing/codec/IfOpenChatEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfOpenChatEncoder.ts @@ -1,6 +1,6 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; import IfOpenChat from '#lostcity/network/outgoing/model/IfOpenChat.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; export default class IfOpenChatEncoder extends MessageEncoder { diff --git a/src/lostcity/network/225/outgoing/codec/IfOpenMainEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfOpenMainEncoder.ts index 723f86d3b3..ca6077af8e 100644 --- a/src/lostcity/network/225/outgoing/codec/IfOpenMainEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfOpenMainEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfOpenMain from '#lostcity/network/outgoing/model/IfOpenMain.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfOpenMainSideEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfOpenMainSideEncoder.ts index 729ea6ea0d..cf8f09a93f 100644 --- a/src/lostcity/network/225/outgoing/codec/IfOpenMainSideEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfOpenMainSideEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfOpenMainSide from '#lostcity/network/outgoing/model/IfOpenMainSide.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfOpenSideEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfOpenSideEncoder.ts index 8bdc8fccd1..74c8c36ebe 100644 --- a/src/lostcity/network/225/outgoing/codec/IfOpenSideEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfOpenSideEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfOpenSide from '#lostcity/network/outgoing/model/IfOpenSide.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetAnimEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetAnimEncoder.ts index b6414f50ce..05ddc6f4ec 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetAnimEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetAnimEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetAnim from '#lostcity/network/outgoing/model/IfSetAnim.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetColourEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetColourEncoder.ts index d37ec1357e..9cf1a8ff48 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetColourEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetColourEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetColour from '#lostcity/network/outgoing/model/IfSetColour.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetHideEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetHideEncoder.ts index ad6bd5e5df..d3e8cef650 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetHideEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetHideEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetHide from '#lostcity/network/outgoing/model/IfSetHide.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetModelEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetModelEncoder.ts index 766ac78f0b..a865fdc1f1 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetModelEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetModelEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetModel from '#lostcity/network/outgoing/model/IfSetModel.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetNpcHeadEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetNpcHeadEncoder.ts index 03679ded77..9a6e4df21c 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetNpcHeadEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetNpcHeadEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetNpcHead from '#lostcity/network/outgoing/model/IfSetNpcHead.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetObjectEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetObjectEncoder.ts index fc082e8377..3f0ee13703 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetObjectEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetObjectEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetObject from '#lostcity/network/outgoing/model/IfSetObject.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetPlayerHeadEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetPlayerHeadEncoder.ts index a0e7ff6f29..337288adff 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetPlayerHeadEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetPlayerHeadEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetPlayerHead from '#lostcity/network/outgoing/model/IfSetPlayerHead.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetPositionEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetPositionEncoder.ts index 56006d01f6..2127ef615b 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetPositionEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetPositionEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetPosition from '#lostcity/network/outgoing/model/IfSetPosition.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetRecolEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetRecolEncoder.ts index fbae52a6fb..4c1d109e0e 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetRecolEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetRecolEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetRecol from '#lostcity/network/outgoing/model/IfSetRecol.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetTabActiveEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetTabActiveEncoder.ts index 45306578cf..6d3089ab47 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetTabActiveEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetTabActiveEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetTabActive from '#lostcity/network/outgoing/model/IfSetTab.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetTabEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetTabEncoder.ts index 22f025301a..1395825dd9 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetTabEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetTabEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetTab from '#lostcity/network/outgoing/model/IfSetTab.js'; diff --git a/src/lostcity/network/225/outgoing/codec/IfSetTextEncoder.ts b/src/lostcity/network/225/outgoing/codec/IfSetTextEncoder.ts index a616a09736..4128eafdd9 100644 --- a/src/lostcity/network/225/outgoing/codec/IfSetTextEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/IfSetTextEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import IfSetText from '#lostcity/network/outgoing/model/IfSetText.js'; diff --git a/src/lostcity/network/225/outgoing/codec/LastLoginInfoEncoder.ts b/src/lostcity/network/225/outgoing/codec/LastLoginInfoEncoder.ts index 70d110b14b..d99dc604f0 100644 --- a/src/lostcity/network/225/outgoing/codec/LastLoginInfoEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/LastLoginInfoEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import LastLoginInfo from '#lostcity/network/outgoing/model/LastLoginInfo.js'; diff --git a/src/lostcity/network/225/outgoing/codec/LocAddChangeEncoder.ts b/src/lostcity/network/225/outgoing/codec/LocAddChangeEncoder.ts index 4fb45ad9f4..ea8dcd7e70 100644 --- a/src/lostcity/network/225/outgoing/codec/LocAddChangeEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/LocAddChangeEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import LocAddChange from '#lostcity/network/outgoing/model/LocAddChange.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/LocAnimEncoder.ts b/src/lostcity/network/225/outgoing/codec/LocAnimEncoder.ts index 4115a88c26..3ca8d643ff 100644 --- a/src/lostcity/network/225/outgoing/codec/LocAnimEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/LocAnimEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import LocAnim from '#lostcity/network/outgoing/model/LocAnim.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/LocDelEncoder.ts b/src/lostcity/network/225/outgoing/codec/LocDelEncoder.ts index b8dd0facbb..13527bc387 100644 --- a/src/lostcity/network/225/outgoing/codec/LocDelEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/LocDelEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import LocDel from '#lostcity/network/outgoing/model/LocDel.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/LocMergeEncoder.ts b/src/lostcity/network/225/outgoing/codec/LocMergeEncoder.ts index b16205754c..777295b647 100644 --- a/src/lostcity/network/225/outgoing/codec/LocMergeEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/LocMergeEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import LocMerge from '#lostcity/network/outgoing/model/LocMerge.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/LogoutEncoder.ts b/src/lostcity/network/225/outgoing/codec/LogoutEncoder.ts index 013344399c..ca48ea7fba 100644 --- a/src/lostcity/network/225/outgoing/codec/LogoutEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/LogoutEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import Logout from '#lostcity/network/outgoing/model/Logout.js'; diff --git a/src/lostcity/network/225/outgoing/codec/MapAnimEncoder.ts b/src/lostcity/network/225/outgoing/codec/MapAnimEncoder.ts index 886ba5fa10..faaa8a8173 100644 --- a/src/lostcity/network/225/outgoing/codec/MapAnimEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/MapAnimEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import MapAnim from '#lostcity/network/outgoing/model/MapAnim.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/MapProjAnimEncoder.ts b/src/lostcity/network/225/outgoing/codec/MapProjAnimEncoder.ts index 9d7949d022..4ea81bd902 100644 --- a/src/lostcity/network/225/outgoing/codec/MapProjAnimEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/MapProjAnimEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import MapProjAnim from '#lostcity/network/outgoing/model/MapProjAnim.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/MessageGameEncoder.ts b/src/lostcity/network/225/outgoing/codec/MessageGameEncoder.ts index 8c58a59621..52a23647cb 100644 --- a/src/lostcity/network/225/outgoing/codec/MessageGameEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/MessageGameEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import MessageGame from '#lostcity/network/outgoing/model/MessageGame.js'; diff --git a/src/lostcity/network/225/outgoing/codec/MessagePrivateEncoder.ts b/src/lostcity/network/225/outgoing/codec/MessagePrivateEncoder.ts index 8d6cd226a4..55b67ca3b3 100644 --- a/src/lostcity/network/225/outgoing/codec/MessagePrivateEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/MessagePrivateEncoder.ts @@ -1,8 +1,8 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import MessagePrivate from '#lostcity/network/outgoing/model/MessagePrivate.js'; -import WordPack from '#jagex2/wordenc/WordPack.js'; +import WordPack from '#jagex/wordenc/WordPack.js'; import WordEnc from '#lostcity/cache/wordenc/WordEnc.js'; export default class MessagePrivateEncoder extends MessageEncoder { diff --git a/src/lostcity/network/225/outgoing/codec/MidiJingleEncoder.ts b/src/lostcity/network/225/outgoing/codec/MidiJingleEncoder.ts index 49da6163b0..d50433ebbd 100644 --- a/src/lostcity/network/225/outgoing/codec/MidiJingleEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/MidiJingleEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import MidiJingle from '#lostcity/network/outgoing/model/MidiJingle.js'; diff --git a/src/lostcity/network/225/outgoing/codec/MidiSongEncoder.ts b/src/lostcity/network/225/outgoing/codec/MidiSongEncoder.ts index 19455172a5..f065f4e85b 100644 --- a/src/lostcity/network/225/outgoing/codec/MidiSongEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/MidiSongEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import MidiSong from '#lostcity/network/outgoing/model/MidiSong.js'; diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoAnimEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoAnimEncoder.ts new file mode 100644 index 0000000000..b3033f3217 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoAnimEncoder.ts @@ -0,0 +1,13 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoAnim from '#lostcity/network/outgoing/model/NpcInfoAnim.js'; + +export default class NpcInfoAnimEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.NPC_ANIM; + + encode(buf: Packet, message: NpcInfoAnim): void { + buf.p2(message.anim); + buf.p1(message.delay); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoChangeTypeEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoChangeTypeEncoder.ts new file mode 100644 index 0000000000..50cd71dad7 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoChangeTypeEncoder.ts @@ -0,0 +1,12 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoChangeType from '#lostcity/network/outgoing/model/NpcInfoChangeType.js'; + +export default class NpcInfoChangeTypeEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.NPC_CHANGE_TYPE; + + encode(buf: Packet, message: NpcInfoChangeType): void { + buf.p2(message.type); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoDamageEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoDamageEncoder.ts new file mode 100644 index 0000000000..579ad69ce3 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoDamageEncoder.ts @@ -0,0 +1,15 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoDamage from '#lostcity/network/outgoing/model/NpcInfoDamage.js'; + +export default class NpcInfoDamageEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.NPC_DAMAGE; + + encode(buf: Packet, message: NpcInfoDamage): void { + buf.p1(message.damage); + buf.p1(message.type); + buf.p1(message.currentHitpoints); + buf.p1(message.baseHitpoints); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoEncoder.ts index 687077a817..8bcd31c4fd 100644 --- a/src/lostcity/network/225/outgoing/codec/NpcInfoEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoEncoder.ts @@ -1,16 +1,19 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import NpcInfo from '#lostcity/network/outgoing/model/NpcInfo.js'; -import World from '#lostcity/engine/World.js'; import { CoordGrid } from '#lostcity/engine/CoordGrid.js'; -import NpcStat from '#lostcity/entity/NpcStat.js'; import Npc from '#lostcity/entity/Npc.js'; -import BuildArea, { ExtendedInfo } from '#lostcity/entity/BuildArea.js'; +import BuildArea from '#lostcity/entity/BuildArea.js'; +import Renderer from '#lostcity/engine/renderer/Renderer.js'; +import Player from '#lostcity/entity/Player.js'; +import NpcInfoFaceEntity from '#lostcity/network/outgoing/model/NpcInfoFaceEntity.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoFaceCoord from '#lostcity/network/outgoing/model/NpcInfoFaceCoord.js'; +import NpcRenderer from '#lostcity/engine/renderer/NpcRenderer.js'; export default class NpcInfoEncoder extends MessageEncoder { private static readonly BITS_NEW: number = 13 + 11 + 5 + 5 + 1; - private static readonly BITS_IDLE: number = 1; private static readonly BITS_RUN: number = 1 + 2 + 3 + 3 + 1; private static readonly BITS_WALK: number = 1 + 2 + 3 + 1; private static readonly BITS_EXTENDED: number = 1 + 2; @@ -19,239 +22,188 @@ export default class NpcInfoEncoder extends MessageEncoder { prot = ServerProt.NPC_INFO; encode(buf: Packet, message: NpcInfo): void { - const buildArea: BuildArea = message.buildArea; + const player = message.player; + const buildArea: BuildArea = player.buildArea; if (message.changedLevel || message.deltaX > buildArea.viewDistance || message.deltaZ > buildArea.viewDistance) { // optimization to avoid sending 3 bits * observed npcs when everything has to be removed anyways buildArea.npcs.clear(); } - this.writeNpcs(buf, message); - this.writeNewNpcs(buf, message); - - const extended: Set = buildArea.extendedInfo; - if (extended.size > 0) { - for (const info of extended) { - const npc: Npc | undefined = World.getNpc(info.id); - if (!npc) { - // safeguard against a potential crash point - // things WILL act weird if this happens - buf.p1(0); - continue; - } - - this.writeExtendedInfo(npc, buf, info.added); - } + buf.bits(); + let bytes: number = 0; + bytes = this.writeNpcs(buf, message, bytes); + this.writeNewNpcs(buf, message, bytes); + if (buildArea.highNpcs.size > 0 || buildArea.lowNpcs.size > 0) { + buf.pBit(13, 8191); } + buf.bytes(); - buildArea.clearExtended(); + const renderer: NpcRenderer = message.renderer; + for (const high of buildArea.highNpcs) { + this.highdefinition(buf, renderer, player, high, false); + } + for (const low of buildArea.lowNpcs) { + this.lowdefinition(buf, renderer, player, low); + } + buildArea.clearNpcInfo(); } test(_: NpcInfo): number { return NpcInfoEncoder.BYTES_LIMIT; } - willFit(message: NpcInfo, buf: Packet, bitsToAdd: number, bytesToAdd: number): boolean { - // 7 aligns to the next byte - return ((buf.bitPos + bitsToAdd + 7) >>> 3) + (message.accumulator + bytesToAdd) <= NpcInfoEncoder.BYTES_LIMIT; - } - - private writeNpcs(buf: Packet, message: NpcInfo): void { - const buildArea: BuildArea = message.buildArea; + private writeNpcs(buf: Packet, message: NpcInfo, bytes: number): number { + const {currentTick, renderer, player } = message; + const buildArea: BuildArea = player.buildArea; // update existing npcs (255 max - 8 bits) - buf.bits(); buf.pBit(8, buildArea.npcs.size); - - for (const nid of buildArea.npcs) { - const npc: Npc | undefined = World.getNpc(nid); - if (!npc || npc.tele || npc.level !== message.level || !CoordGrid.isWithinDistanceSW(message, npc, 15) || !npc.checkLifeCycle(World.currentTick)) { + for (const npc of buildArea.npcs) { + const nid: number = npc.nid; + if (nid === -1 || npc.tele || npc.level !== player.level || !CoordGrid.isWithinDistanceSW(player, npc, 15) || !npc.checkLifeCycle(currentTick)) { // if the npc was teleported, it needs to be removed and re-added - buf.pBit(1, 1); - buf.pBit(2, 3); - buildArea.npcs.delete(nid); + this.remove(buf, buildArea, npc); continue; } - - const extendedInfoSize: number = this.calculateExtendedInfo(npc, false); - let extendedInfo: boolean = extendedInfoSize > 0; - + const length: number = renderer.highdefinitions(nid); + const extend: boolean = length > 0; const { walkDir, runDir } = npc; - let bits: number = NpcInfoEncoder.BITS_IDLE; - if (runDir !== -1) { - bits = NpcInfoEncoder.BITS_RUN; - } else if (walkDir !== -1) { - bits = NpcInfoEncoder.BITS_WALK; - } else if (extendedInfo) { - bits = NpcInfoEncoder.BITS_EXTENDED; - } - - if (!this.willFit(message, buf, bits, extendedInfoSize)) { - extendedInfo = false; - } - - buf.pBit(1, runDir !== -1 || walkDir !== -1 || extendedInfo ? 1 : 0); if (runDir !== -1) { - buf.pBit(2, 2); - buf.pBit(3, walkDir); - buf.pBit(3, runDir); - buf.pBit(1, extendedInfo ? 1 : 0); + this.run(buf, buildArea, npc, walkDir, runDir, extend && this.willFit(bytes, buf, NpcInfoEncoder.BITS_RUN, length)); } else if (walkDir !== -1) { - buf.pBit(2, 1); - buf.pBit(3, walkDir); - buf.pBit(1, extendedInfo ? 1 : 0); - } else if (extendedInfo) { - buf.pBit(2, 0); - } - - if (extendedInfo) { - buildArea.extendedInfo.add({ id: nid, added: false }); - message.accumulator += extendedInfoSize; + this.walk(buf, buildArea, npc, walkDir, extend && this.willFit(bytes, buf, NpcInfoEncoder.BITS_WALK, length)); + } else if (extend && this.willFit(bytes, buf, NpcInfoEncoder.BITS_EXTENDED, length)) { + this.extend(buf, buildArea, npc); + } else { + this.idle(buf); } + bytes += length; } + return bytes; } - private writeNewNpcs(buf: Packet, message: NpcInfo): void { - const buildArea: BuildArea = message.buildArea; - for (const npc of buildArea.getNearbyNpcs(message.x, message.z, message.originX, message.originZ)) { - const extendedInfoSize: number = this.calculateExtendedInfo(npc, true); - const extendedInfo: boolean = extendedInfoSize > 0; - + private writeNewNpcs(buf: Packet, message: NpcInfo, bytes: number): void { + const renderer: Renderer = message.renderer; + const {buildArea, level, x, z, originX, originZ} = message.player; + for (const npc of buildArea.getNearbyNpcs(level, x, z, originX, originZ)) { + const nid: number = npc.nid; + const length: number = renderer.lowdefinitions(nid) + renderer.highdefinitions(nid); // bits to add npc + extended info size + bits to break loop (13) - if (!this.willFit(message, buf, NpcInfoEncoder.BITS_NEW + 13, extendedInfoSize)) { + if (!this.willFit(bytes, buf, NpcInfoEncoder.BITS_NEW + 13, length)) { // more npcs get added next tick break; } - - buf.pBit(13, npc.nid); - buf.pBit(11, npc.type); - buf.pBit(5, npc.x - message.x); - buf.pBit(5, npc.z - message.z); - buf.pBit(1, extendedInfo ? 1 : 0); - - if (extendedInfo) { - buildArea.extendedInfo.add({ id: npc.nid, added: true }); - message.accumulator += extendedInfoSize; - } - - buildArea.npcs.add(npc.nid); - } - - if (buildArea.extendedInfo.size > 0) { - buf.pBit(13, 8191); + this.add(buf, buildArea, npc, nid, npc.x - x, npc.z - z, npc.type); + bytes += length; } - - buf.bytes(); } - private writeExtendedInfo(npc: Npc, buf: Packet, newlyObserved: boolean): void { - let mask: number = npc.mask; + private add(buf: Packet, buildArea: BuildArea, npc: Npc, nid: number, x: number, z: number, type: number): void { + buf.pBit(13, nid); + buf.pBit(11, type); + buf.pBit(5, x); + buf.pBit(5, z); + buf.pBit(1, 1); // extend + buildArea.lowNpcs.add(npc); + buildArea.npcs.add(npc); + } - if (newlyObserved) { - if (npc.orientationX !== -1 || npc.faceX !== -1) { - mask |= Npc.FACE_COORD; - } + private remove(buf: Packet, buildArea: BuildArea, npc: Npc): void { + buf.pBit(1, 1); + buf.pBit(2, 3); + buildArea.npcs.delete(npc); + } - if (npc.faceEntity !== -1) { - mask |= Npc.FACE_ENTITY; - } + private run(buf: Packet, buildArea: BuildArea, npc: Npc, walkDir: number, runDir: number, extend: boolean): void { + buf.pBit(1, 1); + buf.pBit(2, 2); + buf.pBit(3, walkDir); + buf.pBit(3, runDir); + if (extend) { + buf.pBit(1, 1); + buildArea.highNpcs.add(npc); + } else { + buf.pBit(1, 0); } + } - buf.p1(mask); - - if (mask & Npc.ANIM) { - buf.p2(npc.animId); - buf.p1(npc.animDelay); + private walk(buf: Packet, buildArea: BuildArea, npc: Npc, walkDir: number, extend: boolean): void { + buf.pBit(1, 1); + buf.pBit(2, 1); + buf.pBit(3, walkDir); + if (extend) { + buf.pBit(1, 1); + buildArea.highNpcs.add(npc); + } else { + buf.pBit(1, 0); } + } - if (mask & Npc.FACE_ENTITY) { - // todo: get rid of alreadyFacedEntity - if (npc.faceEntity !== -1) { - npc.alreadyFacedEntity = true; - } - - buf.p2(npc.faceEntity); - } + private extend(buf: Packet, buildArea: BuildArea, npc: Npc): void { + buf.pBit(1, 1); + buf.pBit(2, 0); + buildArea.highNpcs.add(npc); + } - if (mask & Npc.SAY) { - buf.pjstr(npc.chat ?? ''); - } + private idle(buf: Packet): void { + buf.pBit(1, 0); + } - if (mask & Npc.DAMAGE) { - buf.p1(npc.damageTaken); - buf.p1(npc.damageType); - buf.p1(npc.levels[NpcStat.HITPOINTS]); - buf.p1(npc.baseLevels[NpcStat.HITPOINTS]); - } + private highdefinition(buf: Packet, renderer: NpcRenderer, _: Player, other: Npc, __: boolean): void { + this.writeBlocks(buf, renderer, other.nid, other.masks); + } - if (mask & Npc.CHANGE_TYPE) { - buf.p2(npc.type); - } + private lowdefinition(buf: Packet, renderer: NpcRenderer, _: Player, other: Npc): void { + const nid: number = other.nid; + let masks: number = other.masks; - if (mask & Npc.SPOTANIM) { - buf.p2(npc.graphicId); - buf.p2(npc.graphicHeight); - buf.p2(npc.graphicDelay); + if (other.faceEntity !== -1 && !renderer.has(nid, InfoProt.NPC_FACE_ENTITY)) { + renderer.cache(nid, new NpcInfoFaceEntity(other.faceEntity), InfoProt.NPC_FACE_ENTITY); + masks |= InfoProt.NPC_FACE_ENTITY.id; } - if (mask & Npc.FACE_COORD) { - if (newlyObserved && npc.orientationX != -1) { - buf.p2(npc.orientationX); - buf.p2(npc.orientationZ); + if (!renderer.has(nid, InfoProt.NPC_FACE_COORD)) { + if (other.orientationX !== -1) { + renderer.cache(nid, new NpcInfoFaceCoord(other.orientationX, other.orientationZ), InfoProt.NPC_FACE_COORD); + } else if (other.faceX !== -1) { + renderer.cache(nid, new NpcInfoFaceCoord(other.faceX, other.faceZ), InfoProt.NPC_FACE_COORD); } else { - buf.p2(npc.faceX); - buf.p2(npc.faceZ); + renderer.cache(nid, new NpcInfoFaceCoord(other.x * 2 + 1, (other.z - 1) * 2 + 1), InfoProt.NPC_FACE_COORD); } } - } - private calculateExtendedInfo(npc: Npc, newlyObserved: boolean): number { - let length: number = 0; - let mask: number = npc.mask; + masks |= InfoProt.NPC_FACE_COORD.id; - if (newlyObserved) { - if (npc.orientationX !== -1 || npc.faceX !== -1) { - mask |= Npc.FACE_COORD; - } - - if (npc.faceEntity !== -1) { - mask |= Npc.FACE_ENTITY; - } - } - - if (mask === 0) { - return 0; - } - - length += 1; + this.writeBlocks(buf, renderer, nid, masks); + } - if (mask & Npc.ANIM) { - length += 3; + private writeBlocks(buf: Packet, renderer: NpcRenderer, nid: number, masks: number): void { + renderer.write1(buf, masks); + if (masks & InfoProt.NPC_ANIM.id) { + renderer.write(buf, nid, InfoProt.NPC_ANIM); } - - if (mask & Npc.FACE_ENTITY) { - length += 2; + if (masks & InfoProt.NPC_FACE_ENTITY.id) { + renderer.write(buf, nid, InfoProt.NPC_FACE_ENTITY); } - - if (mask & Npc.SAY) { - length += 1 + npc.chat!.length; + if (masks & InfoProt.NPC_SAY.id) { + renderer.write(buf, nid, InfoProt.NPC_SAY); } - - if (mask & Npc.DAMAGE) { - length += 4; + if (masks & InfoProt.NPC_DAMAGE.id) { + renderer.write(buf, nid, InfoProt.NPC_DAMAGE); } - - if (mask & Npc.CHANGE_TYPE) { - length += 2; + if (masks & InfoProt.NPC_CHANGE_TYPE.id) { + renderer.write(buf, nid, InfoProt.NPC_CHANGE_TYPE); } - - if (mask & Npc.SPOTANIM) { - length += 6; + if (masks & InfoProt.NPC_SPOTANIM.id) { + renderer.write(buf, nid, InfoProt.NPC_SPOTANIM); } - - if (mask & Npc.FACE_COORD) { - length += 4; + if (masks & InfoProt.NPC_FACE_COORD.id) { + renderer.write(buf, nid, InfoProt.NPC_FACE_COORD); } + } - return length; + private willFit(bytes: number, buf: Packet, bitsToAdd: number, bytesToAdd: number): boolean { + // 7 aligns to the next byte + return ((buf.bitPos + bitsToAdd + 7) >>> 3) + (bytes + bytesToAdd) <= NpcInfoEncoder.BYTES_LIMIT; } } \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoFaceCoordEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoFaceCoordEncoder.ts new file mode 100644 index 0000000000..528cb30570 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoFaceCoordEncoder.ts @@ -0,0 +1,13 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoFaceCoord from '#lostcity/network/outgoing/model/NpcInfoFaceCoord.js'; + +export default class NpcInfoFaceCoordEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.NPC_FACE_COORD; + + encode(buf: Packet, message: NpcInfoFaceCoord): void { + buf.p2(message.x); + buf.p2(message.z); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoFaceEntityEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoFaceEntityEncoder.ts new file mode 100644 index 0000000000..533522cf88 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoFaceEntityEncoder.ts @@ -0,0 +1,12 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoFaceEntity from '#lostcity/network/outgoing/model/NpcInfoFaceEntity.js'; + +export default class NpcInfoFaceEntityEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.NPC_FACE_ENTITY; + + encode(buf: Packet, message: NpcInfoFaceEntity): void { + buf.p2(message.entity); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoSayEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoSayEncoder.ts new file mode 100644 index 0000000000..ef2bfce382 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoSayEncoder.ts @@ -0,0 +1,16 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoSay from '#lostcity/network/outgoing/model/NpcInfoSay.js'; + +export default class NpcInfoSayEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.NPC_SAY; + + encode(buf: Packet, message: NpcInfoSay): void { + buf.pjstr(message.say); + } + + test(message: NpcInfoSay): number { + return 1 + message.say.length; + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/NpcInfoSpotanimEncoder.ts b/src/lostcity/network/225/outgoing/codec/NpcInfoSpotanimEncoder.ts new file mode 100644 index 0000000000..5a8840237d --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/NpcInfoSpotanimEncoder.ts @@ -0,0 +1,13 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import NpcInfoSpotanim from '#lostcity/network/outgoing/model/NpcInfoSpotanim.js'; + +export default class NpcInfoSpotanimEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.NPC_SPOTANIM; + + encode(buf: Packet, message: NpcInfoSpotanim): void { + buf.p2(message.spotanim); + buf.p4((message.height << 16) | message.delay); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/ObjAddEncoder.ts b/src/lostcity/network/225/outgoing/codec/ObjAddEncoder.ts index 93a7a88338..165def9e5f 100644 --- a/src/lostcity/network/225/outgoing/codec/ObjAddEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/ObjAddEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import ObjAdd from '#lostcity/network/outgoing/model/ObjAdd.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/ObjCountEncoder.ts b/src/lostcity/network/225/outgoing/codec/ObjCountEncoder.ts index 3a2abd23a6..672ed70fe8 100644 --- a/src/lostcity/network/225/outgoing/codec/ObjCountEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/ObjCountEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import ObjCount from '#lostcity/network/outgoing/model/ObjCount.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/ObjDelEncoder.ts b/src/lostcity/network/225/outgoing/codec/ObjDelEncoder.ts index 2a578751c6..48fd7676cf 100644 --- a/src/lostcity/network/225/outgoing/codec/ObjDelEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/ObjDelEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import ObjDel from '#lostcity/network/outgoing/model/ObjDel.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/ObjRevealEncoder.ts b/src/lostcity/network/225/outgoing/codec/ObjRevealEncoder.ts index 3262554a4c..da8470ff81 100644 --- a/src/lostcity/network/225/outgoing/codec/ObjRevealEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/ObjRevealEncoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneProt from '#lostcity/network/225/outgoing/prot/ZoneProt.js'; import ObjReveal from '#lostcity/network/outgoing/model/ObjReveal.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; diff --git a/src/lostcity/network/225/outgoing/codec/PCountDialogEncoder.ts b/src/lostcity/network/225/outgoing/codec/PCountDialogEncoder.ts index 4fa7cee6d1..f067c05e03 100644 --- a/src/lostcity/network/225/outgoing/codec/PCountDialogEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/PCountDialogEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import PCountDialog from '#lostcity/network/outgoing/model/PCountDialog.js'; diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoAnimEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoAnimEncoder.ts new file mode 100644 index 0000000000..41ffd90e2e --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoAnimEncoder.ts @@ -0,0 +1,13 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoAnim from '#lostcity/network/outgoing/model/PlayerInfoAnim.js'; + +export default class PlayerInfoAnimEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_ANIM; + + encode(buf: Packet, message: PlayerInfoAnim): void { + buf.p2(message.anim); + buf.p1(message.delay); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoAppearanceEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoAppearanceEncoder.ts new file mode 100644 index 0000000000..80503567b4 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoAppearanceEncoder.ts @@ -0,0 +1,17 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import PlayerInfoAppearance from '#lostcity/network/outgoing/model/PlayerInfoAppearance.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; + +export default class PlayerInfoAppearanceEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_APPEARANCE; + + encode(buf: Packet, message: PlayerInfoAppearance): void { + buf.p1(message.appearance.length); + buf.pdata(message.appearance, 0, message.appearance.length); + } + + test(message: PlayerInfoAppearance): number { + return 1 + message.appearance.length; + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoChatEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoChatEncoder.ts new file mode 100644 index 0000000000..8b7caeba28 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoChatEncoder.ts @@ -0,0 +1,20 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoChat from '#lostcity/network/outgoing/model/PlayerInfoChat.js'; + +export default class PlayerInfoChatEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_CHAT; + + encode(buf: Packet, message: PlayerInfoChat): void { + buf.p1(message.color); + buf.p1(message.effect); + buf.p1(message.type); + buf.p1(message.chat.length); + buf.pdata(message.chat, 0, message.chat.length); + } + + test(message: PlayerInfoChat): number { + return 1 + 1 + 1 + 1 + message.chat.length; + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoDamageEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoDamageEncoder.ts new file mode 100644 index 0000000000..cc3eb25d70 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoDamageEncoder.ts @@ -0,0 +1,15 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoDamage from '#lostcity/network/outgoing/model/PlayerInfoDamage.js'; + +export default class PlayerInfoDamageEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_DAMAGE; + + encode(buf: Packet, message: PlayerInfoDamage): void { + buf.p1(message.damage); + buf.p1(message.type); + buf.p1(message.currentHitpoints); + buf.p1(message.baseHitpoints); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoEncoder.ts index 0569888406..36be7f5a85 100644 --- a/src/lostcity/network/225/outgoing/codec/PlayerInfoEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoEncoder.ts @@ -1,16 +1,18 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import PlayerInfo from '#lostcity/network/outgoing/model/PlayerInfo.js'; -import World from '#lostcity/engine/World.js'; import { CoordGrid } from '#lostcity/engine/CoordGrid.js'; +import BuildArea from '#lostcity/entity/BuildArea.js'; +import Renderer from '#lostcity/engine/renderer/Renderer.js'; import Player from '#lostcity/entity/Player.js'; -import PlayerStat from '#lostcity/entity/PlayerStat.js'; -import BuildArea, { ExtendedInfo } from '#lostcity/entity/BuildArea.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoFaceEntity from '#lostcity/network/outgoing/model/PlayerInfoFaceEntity.js'; +import PlayerInfoFaceCoord from '#lostcity/network/outgoing/model/PlayerInfoFaceCoord.js'; +import PlayerRenderer from '#lostcity/engine/renderer/PlayerRenderer.js'; export default class PlayerInfoEncoder extends MessageEncoder { private static readonly BITS_NEW: number = 11 + 5 + 5 + 1 + 1; - private static readonly BITS_IDLE: number = 1; private static readonly BITS_RUN: number = 1 + 2 + 3 + 3 + 1; private static readonly BITS_WALK: number = 1 + 2 + 3 + 1; private static readonly BITS_EXTENDED: number = 1 + 2; @@ -19,7 +21,8 @@ export default class PlayerInfoEncoder extends MessageEncoder { prot = ServerProt.PLAYER_INFO; encode(buf: Packet, message: PlayerInfo): void { - const buildArea: BuildArea = message.buildArea; + const player = message.player; + const buildArea: BuildArea = player.buildArea; if (message.changedLevel || message.deltaX > buildArea.viewDistance || message.deltaZ > buildArea.viewDistance) { // optimization to avoid sending 3 bits * observed players when everything has to be removed anyways @@ -30,335 +33,243 @@ export default class PlayerInfoEncoder extends MessageEncoder { buildArea.resize(); } - this.writeLocalPlayer(buf, message); - this.writePlayers(buf, message); - this.writeNewPlayers(buf, message); - - const extended: Set = buildArea.extendedInfo; - if (extended.size > 0) { - for (const info of extended) { - const other: Player | null = World.getPlayerByUid(info.id); - if (!other) { - // safeguard against a potential crash point - // things WILL act weird if this happens - buf.p1(0); - continue; - } - - this.writeExtendedInfo(other, message, buf, info.id === message.uid, info.added); - } + buf.bits(); + let bytes: number = 0; + bytes = this.writeLocalPlayer(buf, message, bytes); + bytes = this.writePlayers(buf, message, bytes); + this.writeNewPlayers(buf, message, bytes); + if (buildArea.highPlayers.size > 0 || buildArea.lowPlayers.size > 0) { + buf.pBit(11, 2047); } + buf.bytes(); - buildArea.clearExtended(); + const renderer: PlayerRenderer = message.renderer; + for (const high of buildArea.highPlayers) { + this.highdefinition(buf, renderer, player, high, high.pid === player.pid); + } + for (const low of buildArea.lowPlayers) { + this.lowdefinition(buf, renderer, player, low); + } + buildArea.clearPlayerInfo(); } test(_: PlayerInfo): number { return PlayerInfoEncoder.BYTES_LIMIT; } - willFit(message: PlayerInfo, buf: Packet, bitsToAdd: number, bytesToAdd: number): boolean { - // 7 aligns to the next byte - return ((buf.bitPos + bitsToAdd + 7) >>> 3) + (message.accumulator + bytesToAdd) <= PlayerInfoEncoder.BYTES_LIMIT; - } - - private writeLocalPlayer(buf: Packet, message: PlayerInfo): void { - const { buildArea, uid, level, x, z, tele, jump, walkDir, runDir } = message; - const player: Player | null = World.getPlayerByUid(uid); - if (!player) { - return; - } - - const extendedInfoSize: number = this.calculateExtendedInfo(player, message, true, false); - const extendedInfo: boolean = extendedInfoSize > 0; - - buf.bits(); - buf.pBit(1, tele || runDir !== -1 || walkDir !== -1 || extendedInfo ? 1 : 0); + private writeLocalPlayer(buf: Packet, message: PlayerInfo, bytes: number): number { + const { buildArea, pid, tele, runDir, walkDir } = message.player; + const length: number = message.renderer.highdefinitions(pid); + const extend: boolean = length > 0; if (tele) { - buf.pBit(2, 3); - buf.pBit(2, level); - buf.pBit(7, CoordGrid.local(x, player.originX)); - buf.pBit(7, CoordGrid.local(z, player.originZ)); - buf.pBit(1, jump ? 1 : 0); - buf.pBit(1, extendedInfo ? 1 : 0); + const { x, z, level, originX, originZ, jump } = message.player; + this.teleport(buf, buildArea, message.player, CoordGrid.local(x, originX), level, CoordGrid.local(z, originZ), jump, extend); } else if (runDir !== -1) { - buf.pBit(2, 2); - buf.pBit(3, walkDir); - buf.pBit(3, runDir); - buf.pBit(1, extendedInfo ? 1 : 0); + this.run(buf, buildArea, message.player, walkDir, runDir, extend); } else if (walkDir !== -1) { - buf.pBit(2, 1); - buf.pBit(3, walkDir); - buf.pBit(1, extendedInfo ? 1 : 0); - } else if (extendedInfo) { - buf.pBit(2, 0); - } - - if (extendedInfo) { - buildArea.extendedInfo.add({ id: uid, added: false }); - message.accumulator += extendedInfoSize; + this.walk(buf, buildArea, message.player, walkDir, extend); + } else if (extend) { + this.extend(buf, buildArea, message.player); + } else { + this.idle(buf); } + return bytes + length; } - private writePlayers(buf: Packet, message: PlayerInfo): void { - const buildArea: BuildArea = message.buildArea; + private writePlayers(buf: Packet, message: PlayerInfo, bytes: number): number { + const {currentTick, renderer, player } = message; + const buildArea: BuildArea = player.buildArea; // update other players (255 max - 8 bits) buf.pBit(8, buildArea.players.size); - - for (const uid of buildArea.players) { - const other: Player | null = World.getPlayerByUid(uid); - if (!other || other.tele || other.level !== message.level || !CoordGrid.isWithinDistanceSW(message, other, buildArea.viewDistance) || !other.checkLifeCycle(World.currentTick)) { + for (const other of buildArea.players) { + const pid: number = other.pid; + if (pid === -1 || other.tele || other.level !== player.level || !CoordGrid.isWithinDistanceSW(player, other, buildArea.viewDistance) || !other.checkLifeCycle(currentTick)) { // if the player was teleported, they need to be removed and re-added - buf.pBit(1, 1); - buf.pBit(2, 3); - buildArea.players.delete(uid); + this.remove(buf, buildArea, other); continue; } - - const extendedInfoSize: number = this.calculateExtendedInfo(other, message, false, false); - let extendedInfo: boolean = extendedInfoSize > 0; - + const length: number = renderer.highdefinitions(pid); + const extend: boolean = length > 0; const { walkDir, runDir } = other; - let bits: number = PlayerInfoEncoder.BITS_IDLE; - if (runDir !== -1) { - bits = PlayerInfoEncoder.BITS_RUN; - } else if (walkDir !== -1) { - bits = PlayerInfoEncoder.BITS_WALK; - } else if (extendedInfo) { - bits = PlayerInfoEncoder.BITS_EXTENDED; - } - - if (!this.willFit(message, buf, bits, extendedInfoSize)) { - extendedInfo = false; - } - - buf.pBit(1, runDir !== -1 || walkDir !== -1 || extendedInfo ? 1 : 0); if (runDir !== -1) { - buf.pBit(2, 2); - buf.pBit(3, walkDir); - buf.pBit(3, runDir); - buf.pBit(1, extendedInfo ? 1 : 0); + this.run(buf, buildArea, other, walkDir, runDir, extend && this.willFit(bytes, buf, PlayerInfoEncoder.BITS_RUN, length)); } else if (walkDir !== -1) { - buf.pBit(2, 1); - buf.pBit(3, walkDir); - buf.pBit(1, extendedInfo ? 1 : 0); - } else if (extendedInfo) { - buf.pBit(2, 0); - } - - if (extendedInfo) { - buildArea.extendedInfo.add({ id: uid, added: false }); - message.accumulator += extendedInfoSize; + this.walk(buf, buildArea, other, walkDir, extend && this.willFit(bytes, buf, PlayerInfoEncoder.BITS_WALK, length)); + } else if (extend && this.willFit(bytes, buf, PlayerInfoEncoder.BITS_EXTENDED, length)) { + this.extend(buf, buildArea, other); + } else { + this.idle(buf); } + bytes += length; } + return bytes; } - private writeNewPlayers(buf: Packet, message: PlayerInfo): void { - const buildArea: BuildArea = message.buildArea; - for (const other of buildArea.getNearbyPlayers(message.uid, message.x, message.z, message.originX, message.originZ)) { - const extendedInfoSize: number = this.calculateExtendedInfo(other, message, false, true); - const extendedInfo: boolean = extendedInfoSize > 0; - + private writeNewPlayers(buf: Packet, message: PlayerInfo, bytes: number): void { + const renderer: Renderer = message.renderer; + const {buildArea, pid, level, x, z, originX, originZ} = message.player; + for (const other of buildArea.getNearbyPlayers(pid, level, x, z, originX, originZ)) { + const pid: number = other.pid; + const length: number = renderer.lowdefinitions(pid) + renderer.highdefinitions(pid); // bits to add player + extended info size + bits to break loop (11) - if (!this.willFit(message, buf, PlayerInfoEncoder.BITS_NEW + 11, extendedInfoSize)) { + if (!this.willFit(bytes, buf, PlayerInfoEncoder.BITS_NEW + 11, length)) { // more players get added next tick break; } - - buf.pBit(11, other.pid); - buf.pBit(5, other.x - message.x); - buf.pBit(5, other.z - message.z); - buf.pBit(1, other.jump ? 1 : 0); - buf.pBit(1, extendedInfo ? 1 : 0); - - if (extendedInfo) { - buildArea.extendedInfo.add({ id: other.uid, added: true }); - message.accumulator += extendedInfoSize; - } - - buildArea.players.add(other.uid); + this.add(buf, buildArea, other, pid, other.x - x, other.z - z, other.jump); + bytes += length; } - - if (buildArea.extendedInfo.size > 0) { - buf.pBit(11, 2047); - } - - buf.bytes(); } - private writeExtendedInfo(player: Player, message: PlayerInfo, buf: Packet, self: boolean = false, newlyObserved: boolean = false): void { - let mask: number = player.mask; - - if (newlyObserved) { - if (player.orientationX !== -1 || player.faceX !== -1) { - mask |= Player.FACE_COORD; - } + private add(buf: Packet, buildArea: BuildArea, player: Player, pid: number, x: number, z: number, jump: boolean): void { + buf.pBit(11, pid); + buf.pBit(5, x); + buf.pBit(5, z); + buf.pBit(1, jump ? 1 : 0); + buf.pBit(1, 1); // extend + buildArea.lowPlayers.add(player); + buildArea.players.add(player); + } - if (player.faceEntity !== -1) { - mask |= Player.FACE_ENTITY; - } - } + private remove(buf: Packet, buildArea: BuildArea, player: Player): void { + buf.pBit(1, 1); + buf.pBit(2, 3); + buildArea.players.delete(player); + } - if (self && (mask & Player.CHAT) != 0) { - // don't echo back local chat - mask &= ~Player.CHAT; + private teleport(buf: Packet, buildArea: BuildArea, player: Player, x: number, y: number, z: number, jump: boolean, extend: boolean): void { + buf.pBit(1, 1); + buf.pBit(2, 3); + buf.pBit(2, y); + buf.pBit(7, x); + buf.pBit(7, z); + buf.pBit(1, jump ? 1 : 0); + if (extend) { + buf.pBit(1, 1); + buildArea.highPlayers.add(player); + } else { + buf.pBit(1, 0); } + } - if (message.buildArea.hasAppearance(player.uid, player.lastAppearance) || !player.appearance) { - mask &= ~Player.APPEARANCE; + private run(buf: Packet, buildArea: BuildArea, player: Player, walkDir: number, runDir: number, extend: boolean): void { + buf.pBit(1, 1); + buf.pBit(2, 2); + buf.pBit(3, walkDir); + buf.pBit(3, runDir); + if (extend) { + buf.pBit(1, 1); + buildArea.highPlayers.add(player); } else { - mask |= Player.APPEARANCE; + buf.pBit(1, 0); } + } - if (mask > 0xff) { - mask |= Player.BIG_UPDATE; + private walk(buf: Packet, buildArea: BuildArea, player: Player, walkDir: number, extend: boolean): void { + buf.pBit(1, 1); + buf.pBit(2, 1); + buf.pBit(3, walkDir); + if (extend) { + buf.pBit(1, 1); + buildArea.highPlayers.add(player); + } else { + buf.pBit(1, 0); } + } - buf.p1(mask & 0xff); - if (mask & Player.BIG_UPDATE) { - buf.p1(mask >> 8); - } + private extend(buf: Packet, buildArea: BuildArea, player: Player): void { + buf.pBit(1, 1); + buf.pBit(2, 0); + buildArea.highPlayers.add(player); + } - if (mask & Player.APPEARANCE) { - buf.p1(player.appearance!.length); - buf.pdata(player.appearance!, 0, player.appearance!.length); - message.buildArea.saveAppearance(player.uid, player.lastAppearance); - } + private idle(buf: Packet): void { + buf.pBit(1, 0); + } - if (mask & Player.ANIM) { - buf.p2(player.animId); - buf.p1(player.animDelay); + private highdefinition(buf: Packet, renderer: PlayerRenderer, player: Player, other: Player, self: boolean): void { + let masks: number = other.masks; + if (self) { + masks &= ~InfoProt.PLAYER_CHAT.id; } + this.writeBlocks(buf, renderer, player, other, other.pid, masks, self); + } - if (mask & Player.FACE_ENTITY) { - // todo: get rid of alreadyFacedEntity - if (player.faceEntity !== -1) { - player.alreadyFacedEntity = true; - } + private lowdefinition(buf: Packet, renderer: PlayerRenderer, player: Player, other: Player): void { + const pid: number = other.pid; + let masks: number = other.masks; - buf.p2(player.faceEntity); - } - - if (mask & Player.SAY) { - buf.pjstr(player.chat ?? ''); + if (!player.buildArea.hasAppearance(pid, other.lastAppearance)) { + player.buildArea.saveAppearance(pid, other.lastAppearance); + masks |= InfoProt.PLAYER_APPEARANCE.id; + } else { + masks &= ~InfoProt.PLAYER_APPEARANCE.id; } - if (mask & Player.DAMAGE) { - buf.p1(player.damageTaken); - buf.p1(player.damageType); - buf.p1(player.levels[PlayerStat.HITPOINTS]); - buf.p1(player.baseLevels[PlayerStat.HITPOINTS]); + if (other.faceEntity !== -1 && !renderer.has(pid, InfoProt.PLAYER_FACE_ENTITY)) { + renderer.cache(pid, new PlayerInfoFaceEntity(other.faceEntity), InfoProt.PLAYER_FACE_ENTITY); + masks |= InfoProt.PLAYER_FACE_ENTITY.id; } - if (mask & Player.FACE_COORD) { - if (newlyObserved && player.orientationX !== -1) { - buf.p2(player.orientationX); - buf.p2(player.orientationZ); + if (!renderer.has(pid, InfoProt.PLAYER_FACE_COORD)) { + if (other.orientationX !== -1) { + renderer.cache(pid, new PlayerInfoFaceCoord(other.orientationX, other.orientationZ), InfoProt.PLAYER_FACE_COORD); + } else if (other.faceX !== -1) { + renderer.cache(pid, new PlayerInfoFaceCoord(other.faceX, other.faceZ), InfoProt.PLAYER_FACE_COORD); } else { - buf.p2(player.faceX); - buf.p2(player.faceZ); + renderer.cache(pid, new PlayerInfoFaceCoord(other.x * 2 + 1, (other.z - 1) * 2 + 1), InfoProt.PLAYER_FACE_COORD); } } - if (mask & Player.CHAT) { - buf.p1(player.messageColor!); - buf.p1(player.messageEffect!); - buf.p1(player.messageType!); - - buf.p1(player.message!.length); - buf.pdata(player.message!, 0, player.message!.length); - } - - if (mask & Player.SPOTANIM) { - buf.p2(player.graphicId); - buf.p2(player.graphicHeight); - buf.p2(player.graphicDelay); - } + masks |= InfoProt.PLAYER_FACE_COORD.id; - if (mask & Player.EXACT_MOVE) { - buf.p1(player.exactStartX - CoordGrid.zoneOrigin(message.originX)); - buf.p1(player.exactStartZ - CoordGrid.zoneOrigin(message.originZ)); - buf.p1(player.exactEndX - CoordGrid.zoneOrigin(message.originX)); - buf.p1(player.exactEndZ - CoordGrid.zoneOrigin(message.originZ)); - buf.p2(player.exactMoveStart); - buf.p2(player.exactMoveEnd); - buf.p1(player.exactMoveDirection); - } + this.writeBlocks(buf, renderer, player, other, pid, masks, false); } - private calculateExtendedInfo(player: Player, message: PlayerInfo, self: boolean = false, newlyObserved: boolean = false): number { - let length: number = 0; - let mask: number = player.mask; - - if (newlyObserved) { - if (player.orientationX !== -1 || player.faceX !== -1) { - mask |= Player.FACE_COORD; - } - - if (player.faceEntity !== -1) { - mask |= Player.FACE_ENTITY; - } - } - - if (self && (mask & Player.CHAT) != 0) { - // don't echo back local chat - mask &= ~Player.CHAT; + private writeBlocks(buf: Packet, renderer: PlayerRenderer, player: Player, other: Player, pid: number, masks: number, self: boolean): void { + renderer.write2(buf, masks, InfoProt.PLAYER_BIG_UPDATE.id); + if (masks & InfoProt.PLAYER_APPEARANCE.id) { + renderer.write(buf, pid, InfoProt.PLAYER_APPEARANCE); } - - if (message.buildArea.hasAppearance(player.uid, player.lastAppearance) || !player.appearance) { - mask &= ~Player.APPEARANCE; - } else { - mask |= Player.APPEARANCE; + if (masks & InfoProt.PLAYER_ANIM.id) { + renderer.write(buf, pid, InfoProt.PLAYER_ANIM); } - - if (mask > 0xff) { - mask |= Player.BIG_UPDATE; + if (masks & InfoProt.PLAYER_FACE_ENTITY.id) { + renderer.write(buf, pid, InfoProt.PLAYER_FACE_ENTITY); } - - if (mask === 0) { - return 0; + if (masks & InfoProt.PLAYER_SAY.id) { + renderer.write(buf, pid, InfoProt.PLAYER_SAY); } - - length += 1; - if (mask & Player.BIG_UPDATE) { - length += 1; + if (masks & InfoProt.PLAYER_DAMAGE.id) { + renderer.write(buf, pid, InfoProt.PLAYER_DAMAGE); } - - if (mask & Player.APPEARANCE) { - length += 1 + player.appearance!.length; + if (masks & InfoProt.PLAYER_FACE_COORD.id) { + renderer.write(buf, pid, InfoProt.PLAYER_FACE_COORD); } - - if (mask & Player.ANIM) { - length += 3; + if (!self && masks & InfoProt.PLAYER_CHAT.id) { + renderer.write(buf, pid, InfoProt.PLAYER_CHAT); } - - if (mask & Player.FACE_ENTITY) { - length += 2; + if (masks & InfoProt.PLAYER_SPOTANIM.id) { + renderer.write(buf, pid, InfoProt.PLAYER_SPOTANIM); } - - if (mask & Player.SAY) { - length += 1 + player.chat!.length; - } - - if (mask & Player.DAMAGE) { - length += 4; - } - - if (mask & Player.FACE_COORD) { - length += 4; - } - - if (mask & Player.CHAT) { - length += 4 + player.message!.length; - } - - if (mask & Player.SPOTANIM) { - length += 6; - } - - if (mask & Player.EXACT_MOVE) { - length += 9; + if (masks & InfoProt.PLAYER_EXACT_MOVE.id) { + const x: number = CoordGrid.zoneOrigin(player.originX); + const z: number = CoordGrid.zoneOrigin(player.originZ); + renderer.writeExactmove( + buf, + other.exactStartX - x, + other.exactStartZ - z, + other.exactEndX - x, + other.exactEndZ - z, + other.exactMoveStart, + other.exactMoveEnd, + other.exactMoveDirection + ); } + } - return length; + private willFit(bytes: number, buf: Packet, bitsToAdd: number, bytesToAdd: number): boolean { + // 7 aligns to the next byte + return ((buf.bitPos + bitsToAdd + 7) >>> 3) + (bytes + bytesToAdd) <= PlayerInfoEncoder.BYTES_LIMIT; } } \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoExactMoveEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoExactMoveEncoder.ts new file mode 100644 index 0000000000..2c51e2ad99 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoExactMoveEncoder.ts @@ -0,0 +1,18 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoExactMove from '#lostcity/network/outgoing/model/PlayerInfoExactMove.js'; + +export default class PlayerInfoExactMoveEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_EXACT_MOVE; + + encode(buf: Packet, message: PlayerInfoExactMove): void { + buf.p1(message.startX); + buf.p1(message.startZ); + buf.p1(message.endX); + buf.p1(message.endZ); + buf.p2(message.start); + buf.p2(message.end); + buf.p1(message.direction); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoFaceCoordEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoFaceCoordEncoder.ts new file mode 100644 index 0000000000..318d716e78 --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoFaceCoordEncoder.ts @@ -0,0 +1,13 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoFaceCoord from '#lostcity/network/outgoing/model/PlayerInfoFaceCoord.js'; + +export default class PlayerInfoFaceCoordEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_FACE_COORD; + + encode(buf: Packet, message: PlayerInfoFaceCoord): void { + buf.p2(message.x); + buf.p2(message.z); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoFaceEntityEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoFaceEntityEncoder.ts new file mode 100644 index 0000000000..507b979fee --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoFaceEntityEncoder.ts @@ -0,0 +1,12 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoFaceEntity from '#lostcity/network/outgoing/model/PlayerInfoFaceEntity.js'; + +export default class PlayerInfoFaceEntityEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_FACE_ENTITY; + + encode(buf: Packet, message: PlayerInfoFaceEntity): void { + buf.p2(message.entity); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoSayEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoSayEncoder.ts new file mode 100644 index 0000000000..6e9e38905b --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoSayEncoder.ts @@ -0,0 +1,16 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoSay from '#lostcity/network/outgoing/model/PlayerInfoSay.js'; + +export default class PlayerInfoSayEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_SAY; + + encode(buf: Packet, message: PlayerInfoSay): void { + buf.pjstr(message.say); + } + + test(message: PlayerInfoSay): number { + return 1 + message.say.length; + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/PlayerInfoSpotanimEncoder.ts b/src/lostcity/network/225/outgoing/codec/PlayerInfoSpotanimEncoder.ts new file mode 100644 index 0000000000..8581a58b7b --- /dev/null +++ b/src/lostcity/network/225/outgoing/codec/PlayerInfoSpotanimEncoder.ts @@ -0,0 +1,13 @@ +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import Packet from '#jagex/io/Packet.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; +import PlayerInfoSpotanim from '#lostcity/network/outgoing/model/PlayerInfoSpotanim.js'; + +export default class PlayerInfoSpotanimEncoder extends InfoMessageEncoder { + prot: InfoProt = InfoProt.PLAYER_SPOTANIM; + + encode(buf: Packet, message: PlayerInfoSpotanim): void { + buf.p2(message.spotanim); + buf.p4((message.height << 16) | message.delay); + } +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/codec/RebuildNormalEncoder.ts b/src/lostcity/network/225/outgoing/codec/RebuildNormalEncoder.ts index a4fe4a5309..6a38d13d50 100644 --- a/src/lostcity/network/225/outgoing/codec/RebuildNormalEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/RebuildNormalEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import RebuildNormal from '#lostcity/network/outgoing/model/RebuildNormal.js'; import {PRELOADED_CRC} from '#lostcity/server/PreloadedPacks.js'; diff --git a/src/lostcity/network/225/outgoing/codec/ResetAnimsEncoder.ts b/src/lostcity/network/225/outgoing/codec/ResetAnimsEncoder.ts index 390d045005..3727e8321f 100644 --- a/src/lostcity/network/225/outgoing/codec/ResetAnimsEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/ResetAnimsEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import ResetAnims from '#lostcity/network/outgoing/model/ResetAnims.js'; diff --git a/src/lostcity/network/225/outgoing/codec/ResetClientVarCacheEncoder.ts b/src/lostcity/network/225/outgoing/codec/ResetClientVarCacheEncoder.ts index e57d8d15fa..5dcc3b6e0c 100644 --- a/src/lostcity/network/225/outgoing/codec/ResetClientVarCacheEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/ResetClientVarCacheEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import ResetClientVarCache from '#lostcity/network/outgoing/model/ResetClientVarCache.js'; diff --git a/src/lostcity/network/225/outgoing/codec/SetMultiwayEncoder.ts b/src/lostcity/network/225/outgoing/codec/SetMultiwayEncoder.ts index 056e67582a..25e119ddd7 100644 --- a/src/lostcity/network/225/outgoing/codec/SetMultiwayEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/SetMultiwayEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import SetMultiway from '#lostcity/network/outgoing/model/SetMultiway.js'; diff --git a/src/lostcity/network/225/outgoing/codec/SynthSoundEncoder.ts b/src/lostcity/network/225/outgoing/codec/SynthSoundEncoder.ts index de41c905ed..54e7a0d7e0 100644 --- a/src/lostcity/network/225/outgoing/codec/SynthSoundEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/SynthSoundEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import SynthSound from '#lostcity/network/outgoing/model/SynthSound.js'; diff --git a/src/lostcity/network/225/outgoing/codec/TutFlashEncoder.ts b/src/lostcity/network/225/outgoing/codec/TutFlashEncoder.ts index 29f3f36040..67135e88a0 100644 --- a/src/lostcity/network/225/outgoing/codec/TutFlashEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/TutFlashEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import TutFlash from '#lostcity/network/outgoing/model/TutFlash.js'; diff --git a/src/lostcity/network/225/outgoing/codec/TutOpenEncoder.ts b/src/lostcity/network/225/outgoing/codec/TutOpenEncoder.ts index 2004d4253a..acbeceea52 100644 --- a/src/lostcity/network/225/outgoing/codec/TutOpenEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/TutOpenEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import TutOpen from '#lostcity/network/outgoing/model/TutOpen.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UnsetMapFlagEncoder.ts b/src/lostcity/network/225/outgoing/codec/UnsetMapFlagEncoder.ts index f9366e3ca9..2d4d7c779a 100644 --- a/src/lostcity/network/225/outgoing/codec/UnsetMapFlagEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UnsetMapFlagEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UnsetMapFlag from '#lostcity/network/outgoing/model/UnsetMapFlag.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateFriendListEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateFriendListEncoder.ts index 020f4b4ec8..dec103ae5f 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateFriendListEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateFriendListEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateFriendList from '#lostcity/network/outgoing/model/UpdateFriendList.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateIgnoreListEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateIgnoreListEncoder.ts index d5e55f351e..445c7d20f5 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateIgnoreListEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateIgnoreListEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateIgnoreList from '#lostcity/network/outgoing/model/UpdateIgnoreList.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateInvFullEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateInvFullEncoder.ts index 1ede04dc14..44c899a17a 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateInvFullEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateInvFullEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateInvFull from '#lostcity/network/outgoing/model/UpdateInvFull.js'; import Component from '#lostcity/cache/config/Component.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateInvPartialEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateInvPartialEncoder.ts index 9c0d716d48..ef91888fe0 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateInvPartialEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateInvPartialEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateInvPartial from '#lostcity/network/outgoing/model/UpdateInvPartial.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateInvStopTransmitEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateInvStopTransmitEncoder.ts index 0c371e5fbc..ea6390cdd2 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateInvStopTransmitEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateInvStopTransmitEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateInvStopTransmit from '#lostcity/network/outgoing/model/UpdateInvStopTransmit.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateRebootTimerEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateRebootTimerEncoder.ts index 3a408b51e3..8868f04437 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateRebootTimerEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateRebootTimerEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateRebootTimer from '#lostcity/network/outgoing/model/UpdateRebootTimer.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateRunEnergyEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateRunEnergyEncoder.ts index 69f9107ea7..d585dd1156 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateRunEnergyEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateRunEnergyEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateRunEnergy from '#lostcity/network/outgoing/model/UpdateRunEnergy.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateRunWeightEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateRunWeightEncoder.ts index 931622cc19..3eecd78df6 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateRunWeightEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateRunWeightEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateRunWeight from '#lostcity/network/outgoing/model/UpdateRunWeight.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateStatEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateStatEncoder.ts index 80e0539c80..e4c8c33a04 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateStatEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateStatEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateStat from '#lostcity/network/outgoing/model/UpdateStat.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateUid192Encoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateUid192Encoder.ts index 45e8d905f3..7a19695f9e 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateUid192Encoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateUid192Encoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateUid192 from '#lostcity/network/outgoing/model/UpdateUid192.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateZoneFullFollowsEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateZoneFullFollowsEncoder.ts index dbfbfa1310..fe08613e00 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateZoneFullFollowsEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateZoneFullFollowsEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import UpdateZoneFullFollows from '#lostcity/network/outgoing/model/UpdateZoneFullFollows.js'; import {CoordGrid} from '#lostcity/engine/CoordGrid.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateZonePartialEnclosedEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateZonePartialEnclosedEncoder.ts index d0795547ac..56ec07f90a 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateZonePartialEnclosedEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateZonePartialEnclosedEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import {CoordGrid} from '#lostcity/engine/CoordGrid.js'; import UpdateZonePartialEnclosed from '#lostcity/network/outgoing/model/UpdateZonePartialEnclosed.js'; diff --git a/src/lostcity/network/225/outgoing/codec/UpdateZonePartialFollowsEncoder.ts b/src/lostcity/network/225/outgoing/codec/UpdateZonePartialFollowsEncoder.ts index 9fb84f9c0f..bdb3767292 100644 --- a/src/lostcity/network/225/outgoing/codec/UpdateZonePartialFollowsEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/UpdateZonePartialFollowsEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import {CoordGrid} from '#lostcity/engine/CoordGrid.js'; import UpdateZonePartialFollows from '#lostcity/network/outgoing/model/UpdateZonePartialFollows.js'; diff --git a/src/lostcity/network/225/outgoing/codec/VarpLargeEncoder.ts b/src/lostcity/network/225/outgoing/codec/VarpLargeEncoder.ts index d85eeec436..e3a7cad5c0 100644 --- a/src/lostcity/network/225/outgoing/codec/VarpLargeEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/VarpLargeEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import VarpLarge from '#lostcity/network/outgoing/model/VarpLarge.js'; diff --git a/src/lostcity/network/225/outgoing/codec/VarpSmallEncoder.ts b/src/lostcity/network/225/outgoing/codec/VarpSmallEncoder.ts index 0e6f41c677..23fb492cc0 100644 --- a/src/lostcity/network/225/outgoing/codec/VarpSmallEncoder.ts +++ b/src/lostcity/network/225/outgoing/codec/VarpSmallEncoder.ts @@ -1,5 +1,5 @@ import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; import VarpSmall from '#lostcity/network/outgoing/model/VarpSmall.js'; diff --git a/src/lostcity/network/225/outgoing/prot/InfoProt.ts b/src/lostcity/network/225/outgoing/prot/InfoProt.ts new file mode 100644 index 0000000000..9e37920ee4 --- /dev/null +++ b/src/lostcity/network/225/outgoing/prot/InfoProt.ts @@ -0,0 +1,22 @@ +import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; + +export default class InfoProt extends ServerProt { + static readonly PLAYER_APPEARANCE = new InfoProt(0x1, -1); + static readonly PLAYER_ANIM = new InfoProt(0x2, 3); + static readonly PLAYER_FACE_ENTITY = new InfoProt(0x4, 2); + static readonly PLAYER_SAY = new InfoProt(0x8, -2); + static readonly PLAYER_DAMAGE = new InfoProt(0x10, 4); + static readonly PLAYER_FACE_COORD = new InfoProt(0x20, 4); + static readonly PLAYER_CHAT = new InfoProt(0x40, -2); + static readonly PLAYER_BIG_UPDATE = new InfoProt(0x80, 1); + static readonly PLAYER_SPOTANIM = new InfoProt(0x100, 6); + static readonly PLAYER_EXACT_MOVE = new InfoProt(0x200, 9); + + static readonly NPC_ANIM = new InfoProt(0x2, 3); + static readonly NPC_FACE_ENTITY = new InfoProt(0x4, 2); + static readonly NPC_SAY = new InfoProt(0x8, -2); + static readonly NPC_DAMAGE = new InfoProt(0x10, 4); + static readonly NPC_CHANGE_TYPE = new InfoProt(0x20, 2); + static readonly NPC_SPOTANIM = new InfoProt(0x40, 6); + static readonly NPC_FACE_COORD = new InfoProt(0x80, 4); +} \ No newline at end of file diff --git a/src/lostcity/network/225/outgoing/prot/ServerProt.ts b/src/lostcity/network/225/outgoing/prot/ServerProt.ts index 73ae5d0ddd..ed63962e3b 100644 --- a/src/lostcity/network/225/outgoing/prot/ServerProt.ts +++ b/src/lostcity/network/225/outgoing/prot/ServerProt.ts @@ -1,7 +1,4 @@ export default class ServerProt { - static readonly all: ServerProt[] = []; - static readonly byId: ServerProt[] = []; - // interfaces static readonly IF_OPENCHAT = new ServerProt(14, 2); static readonly IF_OPENMAIN_SIDE = new ServerProt(28, 4); @@ -89,10 +86,7 @@ export default class ServerProt { static readonly UPDATE_ZONE_FULL_FOLLOWS = new ServerProt(135, 2); // NXT naming static readonly UPDATE_ZONE_PARTIAL_ENCLOSED = new ServerProt(162, -2); // NXT naming - constructor(readonly id: number, readonly length: number) { - ServerProt.all.push(this); // no known index - ServerProt.byId[id] = this; - } + constructor(readonly id: number, readonly length: number) {} } // for type safety in CameraInfo diff --git a/src/lostcity/network/225/outgoing/prot/ServerProtRepository.ts b/src/lostcity/network/225/outgoing/prot/ServerProtRepository.ts index 5fa5f4c68d..5d6b601d77 100644 --- a/src/lostcity/network/225/outgoing/prot/ServerProtRepository.ts +++ b/src/lostcity/network/225/outgoing/prot/ServerProtRepository.ts @@ -144,6 +144,40 @@ import ZoneMessage from '#lostcity/network/outgoing/ZoneMessage.js'; import ZoneMessageEncoder from '#lostcity/network/outgoing/codec/ZoneMessageEncoder.js'; import UpdateRebootTimer from '#lostcity/network/outgoing/model/UpdateRebootTimer.js'; import UpdateRebootTimerEncoder from '#lostcity/network/225/outgoing/codec/UpdateRebootTimerEncoder.js'; +import PlayerInfoExactMove from '#lostcity/network/outgoing/model/PlayerInfoExactMove.js'; +import PlayerInfoExactMoveEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoExactMoveEncoder.js'; +import PlayerInfoAnim from '#lostcity/network/outgoing/model/PlayerInfoAnim.js'; +import PlayerInfoAnimEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoAnimEncoder.js'; +import PlayerInfoAppearance from '#lostcity/network/outgoing/model/PlayerInfoAppearance.js'; +import PlayerInfoAppearanceEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoAppearanceEncoder.js'; +import PlayerInfoChat from '#lostcity/network/outgoing/model/PlayerInfoChat.js'; +import PlayerInfoChatEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoChatEncoder.js'; +import PlayerInfoDamage from '#lostcity/network/outgoing/model/PlayerInfoDamage.js'; +import PlayerInfoDamageEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoDamageEncoder.js'; +import PlayerInfoFaceCoord from '#lostcity/network/outgoing/model/PlayerInfoFaceCoord.js'; +import PlayerInfoFaceCoordEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoFaceCoordEncoder.js'; +import PlayerInfoFaceEntity from '#lostcity/network/outgoing/model/PlayerInfoFaceEntity.js'; +import PlayerInfoFaceEntityEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoFaceEntityEncoder.js'; +import PlayerInfoSay from '#lostcity/network/outgoing/model/PlayerInfoSay.js'; +import PlayerInfoSayEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoSayEncoder.js'; +import PlayerInfoSpotanim from '#lostcity/network/outgoing/model/PlayerInfoSpotanim.js'; +import PlayerInfoSpotanimEncoder from '#lostcity/network/225/outgoing/codec/PlayerInfoSpotanimEncoder.js'; +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; +import InfoMessageEncoder from '#lostcity/network/outgoing/codec/InfoMessageEncoder.js'; +import NpcInfoAnim from '#lostcity/network/outgoing/model/NpcInfoAnim.js'; +import NpcInfoAnimEncoder from '#lostcity/network/225/outgoing/codec/NpcInfoAnimEncoder.js'; +import NpcInfoChangeType from '#lostcity/network/outgoing/model/NpcInfoChangeType.js'; +import NpcInfoChangeTypeEncoder from '#lostcity/network/225/outgoing/codec/NpcInfoChangeTypeEncoder.js'; +import NpcInfoDamage from '#lostcity/network/outgoing/model/NpcInfoDamage.js'; +import NpcInfoDamageEncoder from '#lostcity/network/225/outgoing/codec/NpcInfoDamageEncoder.js'; +import NpcInfoFaceCoord from '#lostcity/network/outgoing/model/NpcInfoFaceCoord.js'; +import NpcInfoFaceCoordEncoder from '#lostcity/network/225/outgoing/codec/NpcInfoFaceCoordEncoder.js'; +import NpcInfoFaceEntity from '#lostcity/network/outgoing/model/NpcInfoFaceEntity.js'; +import NpcInfoFaceEntityEncoder from '#lostcity/network/225/outgoing/codec/NpcInfoFaceEntityEncoder.js'; +import NpcInfoSay from '#lostcity/network/outgoing/model/NpcInfoSay.js'; +import NpcInfoSayEncoder from '#lostcity/network/225/outgoing/codec/NpcInfoSayEncoder.js'; +import NpcInfoSpotanim from '#lostcity/network/outgoing/model/NpcInfoSpotanim.js'; +import NpcInfoSpotanimEncoder from '#lostcity/network/225/outgoing/codec/NpcInfoSpotanimEncoder.js'; /* eslint-disable @typescript-eslint/no-explicit-any */ type GenericOutgoingMessage = new (...args: any[]) => T; @@ -230,6 +264,24 @@ class ServerProtRepository { this.bind(UpdateZonePartialFollows, new UpdateZonePartialFollowsEncoder()); this.bind(VarpLarge, new VarpLargeEncoder()); this.bind(VarpSmall, new VarpSmallEncoder()); + // ---- player_info + this.bind(PlayerInfoAnim, new PlayerInfoAnimEncoder()); + this.bind(PlayerInfoAppearance, new PlayerInfoAppearanceEncoder()); + this.bind(PlayerInfoChat, new PlayerInfoChatEncoder()); + this.bind(PlayerInfoDamage, new PlayerInfoDamageEncoder()); + this.bind(PlayerInfoFaceCoord, new PlayerInfoFaceCoordEncoder()); + this.bind(PlayerInfoFaceEntity, new PlayerInfoFaceEntityEncoder()); + this.bind(PlayerInfoSay, new PlayerInfoSayEncoder()); + this.bind(PlayerInfoSpotanim, new PlayerInfoSpotanimEncoder()); + this.bind(PlayerInfoExactMove, new PlayerInfoExactMoveEncoder()); + // ---- npc_info + this.bind(NpcInfoAnim, new NpcInfoAnimEncoder()); + this.bind(NpcInfoChangeType, new NpcInfoChangeTypeEncoder()); + this.bind(NpcInfoDamage, new NpcInfoDamageEncoder()); + this.bind(NpcInfoFaceCoord, new NpcInfoFaceCoordEncoder()); + this.bind(NpcInfoFaceEntity, new NpcInfoFaceEntityEncoder()); + this.bind(NpcInfoSay, new NpcInfoSayEncoder()); + this.bind(NpcInfoSpotanim, new NpcInfoSpotanimEncoder()); } getEncoder(message: T): MessageEncoder | undefined { @@ -239,6 +291,10 @@ class ServerProtRepository { getZoneEncoder(message: T): ZoneMessageEncoder | undefined { return this.encoders.get(message.constructor as GenericOutgoingMessage) as ZoneMessageEncoder | undefined; } + + getInfoEncoder(message: T): InfoMessageEncoder | undefined { + return this.encoders.get(message.constructor as GenericOutgoingMessage) as InfoMessageEncoder | undefined; + } } export default new ServerProtRepository(); diff --git a/src/lostcity/network/incoming/codec/MessageDecoder.ts b/src/lostcity/network/incoming/codec/MessageDecoder.ts index d72e90564c..3275574051 100644 --- a/src/lostcity/network/incoming/codec/MessageDecoder.ts +++ b/src/lostcity/network/incoming/codec/MessageDecoder.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import IncomingMessage from '#lostcity/network/incoming/IncomingMessage.js'; import ClientProt from '#lostcity/network/225/incoming/prot/ClientProt.js'; diff --git a/src/lostcity/network/outgoing/InfoMessage.ts b/src/lostcity/network/outgoing/InfoMessage.ts new file mode 100644 index 0000000000..1084dd59a3 --- /dev/null +++ b/src/lostcity/network/outgoing/InfoMessage.ts @@ -0,0 +1,13 @@ +import OutgoingMessage from '#lostcity/network/outgoing/OutgoingMessage.js'; +import ServerProtPriority from '#lostcity/network/outgoing/prot/ServerProtPriority.js'; + +export default abstract class InfoMessage extends OutgoingMessage { + priority = ServerProtPriority.IMMEDIATE; + protected constructor() { + super(); + } + + get persists(): boolean { + return false; + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/OutgoingMessage.ts b/src/lostcity/network/outgoing/OutgoingMessage.ts index e293a0f24e..d37de661f9 100644 --- a/src/lostcity/network/outgoing/OutgoingMessage.ts +++ b/src/lostcity/network/outgoing/OutgoingMessage.ts @@ -1,5 +1,5 @@ import ServerProtPriority from '#lostcity/network/outgoing/prot/ServerProtPriority.js'; -import DoublyLinkable from '#jagex2/datastruct/DoublyLinkable.js'; +import DoublyLinkable from '#jagex/datastruct/DoublyLinkable.js'; export default abstract class OutgoingMessage extends DoublyLinkable { readonly abstract priority: ServerProtPriority; diff --git a/src/lostcity/network/outgoing/codec/InfoMessageEncoder.ts b/src/lostcity/network/outgoing/codec/InfoMessageEncoder.ts new file mode 100644 index 0000000000..0bc8349917 --- /dev/null +++ b/src/lostcity/network/outgoing/codec/InfoMessageEncoder.ts @@ -0,0 +1,7 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; +import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; +import InfoProt from '#lostcity/network/225/outgoing/prot/InfoProt.js'; + +export default abstract class InfoMessageEncoder extends MessageEncoder { + abstract prot: InfoProt; +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/codec/MessageEncoder.ts b/src/lostcity/network/outgoing/codec/MessageEncoder.ts index 918da40f28..e2a2d55cd5 100644 --- a/src/lostcity/network/outgoing/codec/MessageEncoder.ts +++ b/src/lostcity/network/outgoing/codec/MessageEncoder.ts @@ -1,6 +1,6 @@ import OutgoingMessage from '#lostcity/network/outgoing/OutgoingMessage.js'; import ServerProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export default abstract class MessageEncoder { abstract prot: ServerProt; diff --git a/src/lostcity/network/outgoing/codec/ZoneMessageEncoder.ts b/src/lostcity/network/outgoing/codec/ZoneMessageEncoder.ts index aa72ecdeb9..21035c28b2 100644 --- a/src/lostcity/network/outgoing/codec/ZoneMessageEncoder.ts +++ b/src/lostcity/network/outgoing/codec/ZoneMessageEncoder.ts @@ -1,5 +1,5 @@ import ZoneProt from '#lostcity/network/225/outgoing/prot/ServerProt.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ZoneMessage from '#lostcity/network/outgoing/ZoneMessage.js'; import MessageEncoder from '#lostcity/network/outgoing/codec/MessageEncoder.js'; diff --git a/src/lostcity/network/outgoing/model/NpcInfo.ts b/src/lostcity/network/outgoing/model/NpcInfo.ts index 25e4473b11..b819840a91 100644 --- a/src/lostcity/network/outgoing/model/NpcInfo.ts +++ b/src/lostcity/network/outgoing/model/NpcInfo.ts @@ -1,20 +1,16 @@ import OutgoingMessage from '#lostcity/network/outgoing/OutgoingMessage.js'; import ServerProtPriority from '#lostcity/network/outgoing/prot/ServerProtPriority.js'; -import BuildArea from '#lostcity/entity/BuildArea.js'; +import Player from '#lostcity/entity/Player.js'; +import NpcRenderer from '#lostcity/engine/renderer/NpcRenderer.js'; // this is slightly unsafe. export default class NpcInfo extends OutgoingMessage { priority = ServerProtPriority.IMMEDIATE; - accumulator: number = 0; - constructor( - readonly buildArea: BuildArea, - readonly level: number, - readonly x: number, - readonly z: number, - readonly originX: number, - readonly originZ: number, + readonly currentTick: number, + readonly renderer: NpcRenderer, + readonly player: Player, readonly deltaX: number, readonly deltaZ: number, readonly changedLevel: boolean diff --git a/src/lostcity/network/outgoing/model/NpcInfoAnim.ts b/src/lostcity/network/outgoing/model/NpcInfoAnim.ts new file mode 100644 index 0000000000..32a1b86fde --- /dev/null +++ b/src/lostcity/network/outgoing/model/NpcInfoAnim.ts @@ -0,0 +1,10 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class NpcInfoAnim extends InfoMessage { + constructor( + readonly anim: number, + readonly delay: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/NpcInfoChangeType.ts b/src/lostcity/network/outgoing/model/NpcInfoChangeType.ts new file mode 100644 index 0000000000..0230cc5d6c --- /dev/null +++ b/src/lostcity/network/outgoing/model/NpcInfoChangeType.ts @@ -0,0 +1,9 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class NpcInfoChangeType extends InfoMessage { + constructor( + readonly type: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/NpcInfoDamage.ts b/src/lostcity/network/outgoing/model/NpcInfoDamage.ts new file mode 100644 index 0000000000..47fb4f2a6a --- /dev/null +++ b/src/lostcity/network/outgoing/model/NpcInfoDamage.ts @@ -0,0 +1,12 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class NpcInfoDamage extends InfoMessage { + constructor( + readonly damage: number, + readonly type: number, + readonly currentHitpoints: number, + readonly baseHitpoints: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/NpcInfoFaceCoord.ts b/src/lostcity/network/outgoing/model/NpcInfoFaceCoord.ts new file mode 100644 index 0000000000..c8c9a22562 --- /dev/null +++ b/src/lostcity/network/outgoing/model/NpcInfoFaceCoord.ts @@ -0,0 +1,10 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class NpcInfoFaceCoord extends InfoMessage { + constructor( + readonly x: number, + readonly z: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/NpcInfoFaceEntity.ts b/src/lostcity/network/outgoing/model/NpcInfoFaceEntity.ts new file mode 100644 index 0000000000..385b0f4259 --- /dev/null +++ b/src/lostcity/network/outgoing/model/NpcInfoFaceEntity.ts @@ -0,0 +1,9 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class NpcInfoFaceEntity extends InfoMessage { + constructor( + readonly entity: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/NpcInfoSay.ts b/src/lostcity/network/outgoing/model/NpcInfoSay.ts new file mode 100644 index 0000000000..3f57dd5284 --- /dev/null +++ b/src/lostcity/network/outgoing/model/NpcInfoSay.ts @@ -0,0 +1,9 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class NpcInfoSay extends InfoMessage { + constructor( + readonly say: string + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/NpcInfoSpotanim.ts b/src/lostcity/network/outgoing/model/NpcInfoSpotanim.ts new file mode 100644 index 0000000000..75f68bedb0 --- /dev/null +++ b/src/lostcity/network/outgoing/model/NpcInfoSpotanim.ts @@ -0,0 +1,11 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class NpcInfoSpotanim extends InfoMessage { + constructor( + readonly spotanim: number, + readonly height: number, + readonly delay: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfo.ts b/src/lostcity/network/outgoing/model/PlayerInfo.ts index 5cf809c54c..0e522bae9d 100644 --- a/src/lostcity/network/outgoing/model/PlayerInfo.ts +++ b/src/lostcity/network/outgoing/model/PlayerInfo.ts @@ -1,26 +1,16 @@ import OutgoingMessage from '#lostcity/network/outgoing/OutgoingMessage.js'; import ServerProtPriority from '#lostcity/network/outgoing/prot/ServerProtPriority.js'; -import BuildArea from '#lostcity/entity/BuildArea.js'; +import Player from '#lostcity/entity/Player.js'; +import PlayerRenderer from '#lostcity/engine/renderer/PlayerRenderer.js'; // this is slightly unsafe. export default class PlayerInfo extends OutgoingMessage { priority = ServerProtPriority.IMMEDIATE; - accumulator: number = 0; - constructor( - readonly buildArea: BuildArea, - readonly level: number, - readonly x: number, - readonly z: number, - readonly originX: number, - readonly originZ: number, - readonly uid: number, - readonly mask: number, - readonly tele: boolean, - readonly jump: boolean, - readonly walkDir: number, - readonly runDir: number, + readonly currentTick: number, + readonly renderer: PlayerRenderer, + readonly player: Player, readonly deltaX: number, readonly deltaZ: number, readonly changedLevel: boolean diff --git a/src/lostcity/network/outgoing/model/PlayerInfoAnim.ts b/src/lostcity/network/outgoing/model/PlayerInfoAnim.ts new file mode 100644 index 0000000000..bcc13dd051 --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoAnim.ts @@ -0,0 +1,10 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoAnim extends InfoMessage { + constructor( + readonly anim: number, + readonly delay: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoAppearance.ts b/src/lostcity/network/outgoing/model/PlayerInfoAppearance.ts new file mode 100644 index 0000000000..088cd0abff --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoAppearance.ts @@ -0,0 +1,11 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoAppearance extends InfoMessage { + constructor(readonly appearance: Uint8Array) { + super(); + } + + get persists(): boolean { + return true; + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoChat.ts b/src/lostcity/network/outgoing/model/PlayerInfoChat.ts new file mode 100644 index 0000000000..6d18d80df8 --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoChat.ts @@ -0,0 +1,12 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoChat extends InfoMessage { + constructor( + readonly color: number, + readonly effect: number, + readonly type: number, + readonly chat: Uint8Array + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoDamage.ts b/src/lostcity/network/outgoing/model/PlayerInfoDamage.ts new file mode 100644 index 0000000000..10fe2f7cbf --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoDamage.ts @@ -0,0 +1,12 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoDamage extends InfoMessage { + constructor( + readonly damage: number, + readonly type: number, + readonly currentHitpoints: number, + readonly baseHitpoints: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoExactMove.ts b/src/lostcity/network/outgoing/model/PlayerInfoExactMove.ts new file mode 100644 index 0000000000..23a8ef5c56 --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoExactMove.ts @@ -0,0 +1,15 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoExactMove extends InfoMessage { + constructor( + readonly startX: number, + readonly startZ: number, + readonly endX: number, + readonly endZ: number, + readonly start: number, + readonly end: number, + readonly direction: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoFaceCoord.ts b/src/lostcity/network/outgoing/model/PlayerInfoFaceCoord.ts new file mode 100644 index 0000000000..55e774c98f --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoFaceCoord.ts @@ -0,0 +1,10 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoFaceCoord extends InfoMessage { + constructor( + readonly x: number, + readonly z: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoFaceEntity.ts b/src/lostcity/network/outgoing/model/PlayerInfoFaceEntity.ts new file mode 100644 index 0000000000..dac020d7ad --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoFaceEntity.ts @@ -0,0 +1,9 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoFaceEntity extends InfoMessage { + constructor( + readonly entity: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoSay.ts b/src/lostcity/network/outgoing/model/PlayerInfoSay.ts new file mode 100644 index 0000000000..9fc69c3f84 --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoSay.ts @@ -0,0 +1,9 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoSay extends InfoMessage { + constructor( + readonly say: string + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/network/outgoing/model/PlayerInfoSpotanim.ts b/src/lostcity/network/outgoing/model/PlayerInfoSpotanim.ts new file mode 100644 index 0000000000..746a7e3474 --- /dev/null +++ b/src/lostcity/network/outgoing/model/PlayerInfoSpotanim.ts @@ -0,0 +1,11 @@ +import InfoMessage from '#lostcity/network/outgoing/InfoMessage.js'; + +export default class PlayerInfoSpotanim extends InfoMessage { + constructor( + readonly spotanim: number, + readonly height: number, + readonly delay: number + ) { + super(); + } +} \ No newline at end of file diff --git a/src/lostcity/cache/packchat/pack.ts b/src/lostcity/pack/chat/pack.ts similarity index 97% rename from src/lostcity/cache/packchat/pack.ts rename to src/lostcity/pack/chat/pack.ts index fbb286c5b0..95872a0e67 100644 --- a/src/lostcity/cache/packchat/pack.ts +++ b/src/lostcity/pack/chat/pack.ts @@ -1,7 +1,7 @@ import fs from 'fs'; -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; import { shouldBuildFileAny } from '#lostcity/util/PackFile.js'; export function packClientWordenc() { diff --git a/src/lostcity/cache/packconfig/DbRowConfig.ts b/src/lostcity/pack/config/DbRowConfig.ts similarity index 92% rename from src/lostcity/cache/packconfig/DbRowConfig.ts rename to src/lostcity/pack/config/DbRowConfig.ts index 5df9a0ae4f..7daf97214f 100644 --- a/src/lostcity/cache/packconfig/DbRowConfig.ts +++ b/src/lostcity/pack/config/DbRowConfig.ts @@ -1,8 +1,8 @@ import DbTableType from '#lostcity/cache/config/DbTableType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ConfigValue, ConfigLine, packStepError, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; -import { lookupParamValue } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { ConfigValue, ConfigLine, packStepError, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; +import { lookupParamValue } from '#lostcity/pack/config/ParamConfig.js'; import { DbRowPack, DbTablePack } from '#lostcity/util/PackFile.js'; function parseCsv(str: string): string[] { @@ -116,20 +116,20 @@ export function packDbRowConfigs(configs: Map): { client: throw packStepError(debugname, 'No table defined in dbrow config'); } - if (data.length) { + if (data.length && table) { server.p1(3); - server.p1(table!.types.length); - for (let i = 0; i < table!.types.length; i++) { + server.p1(table.types.length); + for (let i = 0; i < table.types.length; i++) { server.p1(i); - const types = table!.types[i]; + const types = table.types[i]; server.p1(types.length); for (let j = 0; j < types.length; j++) { server.p1(types[j]); } - const columnName = table!.columnNames[i]; + const columnName = table.columnNames[i]; const fields = data.filter(d => d.column === columnName); server.p1(fields.length); diff --git a/src/lostcity/cache/packconfig/DbTableConfig.ts b/src/lostcity/pack/config/DbTableConfig.ts similarity index 97% rename from src/lostcity/cache/packconfig/DbTableConfig.ts rename to src/lostcity/pack/config/DbTableConfig.ts index 68f45bd2fc..c6a874032f 100644 --- a/src/lostcity/cache/packconfig/DbTableConfig.ts +++ b/src/lostcity/pack/config/DbTableConfig.ts @@ -1,7 +1,7 @@ import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; -import { lookupParamValue } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; +import { lookupParamValue } from '#lostcity/pack/config/ParamConfig.js'; import { DbTablePack } from '#lostcity/util/PackFile.js'; function parseCsv(str: string): string[] { diff --git a/src/lostcity/cache/packconfig/EnumConfig.ts b/src/lostcity/pack/config/EnumConfig.ts similarity index 96% rename from src/lostcity/cache/packconfig/EnumConfig.ts rename to src/lostcity/pack/config/EnumConfig.ts index f88baa2b6c..f8285bec64 100644 --- a/src/lostcity/cache/packconfig/EnumConfig.ts +++ b/src/lostcity/pack/config/EnumConfig.ts @@ -1,7 +1,7 @@ import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean, packStepError } from '#lostcity/cache/packconfig/PackShared.js'; -import { lookupParamValue } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean, packStepError } from '#lostcity/pack/config/PackShared.js'; +import { lookupParamValue } from '#lostcity/pack/config/ParamConfig.js'; import { EnumPack } from '#lostcity/util/PackFile.js'; export function parseEnumConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packconfig/FloConfig.ts b/src/lostcity/pack/config/FloConfig.ts similarity index 97% rename from src/lostcity/cache/packconfig/FloConfig.ts rename to src/lostcity/pack/config/FloConfig.ts index 695f9c7c3d..7835198146 100644 --- a/src/lostcity/cache/packconfig/FloConfig.ts +++ b/src/lostcity/pack/config/FloConfig.ts @@ -1,4 +1,4 @@ -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { FloPack, TexturePack } from '#lostcity/util/PackFile.js'; export function parseFloConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packconfig/HuntConfig.ts b/src/lostcity/pack/config/HuntConfig.ts similarity index 87% rename from src/lostcity/cache/packconfig/HuntConfig.ts rename to src/lostcity/pack/config/HuntConfig.ts index 3cb01b52fb..cf470a55ea 100644 --- a/src/lostcity/cache/packconfig/HuntConfig.ts +++ b/src/lostcity/pack/config/HuntConfig.ts @@ -4,10 +4,9 @@ import { PackedData, isConfigBoolean, getConfigBoolean, - HuntCheckInv, HuntCheckInvParam -} from '#lostcity/cache/packconfig/PackShared.js'; - -import {Inventory} from '#lostcity/engine/Inventory.js'; + HuntCheckInv, HuntCheckInvParam, + HuntCheckVar +} from '#lostcity/pack/config/PackShared.js'; import HuntModeType from '#lostcity/entity/hunt/HuntModeType.js'; import HuntVis from '#lostcity/entity/hunt/HuntVis.js'; @@ -325,42 +324,31 @@ export function parseHuntConfig(key: string, value: string): ConfigValue | null } else if (key === 'check_inv') { // check_inv=inv,obj,min,max const parts: string[] = value.split(','); - if (parts.length !== 4) { + if (parts.length !== 3) { return null; } - const inv = InvPack.getByName(parts[0]); if (inv === -1) { return null; } - const obj = ObjPack.getByName(parts[1]); if (obj === -1) { return null; } - - if (!/^-?[0-9]+$/.test(parts[2])) { - return null; - } - const min = parseInt(parts[2]); - - if (!/^-?[0-9]+$/.test(parts[3])) { - return null; - } - const max = parseInt(parts[3]); - - if (min < 0 || min > Inventory.STACK_LIMIT || min > max) { + const conditionWithVal = parts[2]; + const condition = conditionWithVal.charAt(0); + if (!['=', '>', '<', '!'].includes(condition)) { return null; } - - if (max < 0 || max > Inventory.STACK_LIMIT || max < min) { + const val = parseInt(conditionWithVal.slice(1)); + if (isNaN(val)) { return null; } - return {inv, obj, min, max}; + return {inv, obj, condition, val}; } else if (key === 'check_invparam') { // check_inv=inv,param,min,max const parts: string[] = value.split(','); - if (parts.length !== 4) { + if (parts.length !== 3) { return null; } @@ -373,25 +361,40 @@ export function parseHuntConfig(key: string, value: string): ConfigValue | null if (param === -1) { return null; } - - if (!/^-?[0-9]+$/.test(parts[2])) { + const conditionWithVal = parts[2]; + const condition = conditionWithVal.charAt(0); + if (!['=', '>', '<', '!'].includes(condition)) { return null; } - const min = parseInt(parts[2]); - - if (!/^-?[0-9]+$/.test(parts[3])) { + const val = parseInt(conditionWithVal.slice(1)); + if (isNaN(val)) { return null; } - const max = parseInt(parts[3]); - - if (min < 0 || min > Inventory.STACK_LIMIT || min > max) { + return {inv, param, condition, val}; + } else if (key === 'extracheck_var') { + const parts: string[] = value.split(','); + + if (parts.length !== 2) { return null; } - - if (max < 0 || max > Inventory.STACK_LIMIT || max < min) { + + if (!parts[0].startsWith('%')) { + return null; + } + const conditionWithVal = parts[1]; + const condition = conditionWithVal.charAt(0); + if (!['=', '>', '<', '!'].includes(condition)) { return null; } - return {inv, param, min, max}; + const varp = VarpPack.getByName(parts[0].slice(1)); + if (varp === -1) { + return null; + } + const val = parseInt(conditionWithVal.slice(1)); + if (isNaN(val)) { + return null; + } + return {varp, condition, val}; } else { return undefined; } @@ -404,7 +407,7 @@ export function packHuntConfigs(configs: Map): { client: P for (let i = 0; i < HuntPack.size; i++) { const debugname = HuntPack.getById(i); const config = configs.get(debugname)!; - + let extracheckVarsCount = 0; for (let j = 0; j < config.length; j++) { const { key, value } = config[j]; @@ -494,8 +497,8 @@ export function packHuntConfigs(configs: Map): { client: P server.p1(16); server.p2(checkInv.inv); server.p2(checkInv.obj); - server.p4(checkInv.min); - server.p4(checkInv.max); + server.pjstr(checkInv.condition); + server.p4(checkInv.val); } else { throw new Error(`Hunt config: [${debugname}] unable to pack line!!!.\nInvalid property value: ${key}=${value}`); } @@ -505,12 +508,25 @@ export function packHuntConfigs(configs: Map): { client: P server.p1(17); server.p2(checkInv.inv); server.p2(checkInv.param); - server.p4(checkInv.min); - server.p4(checkInv.max); + server.pjstr(checkInv.condition); + server.p4(checkInv.val); } else { throw new Error(`Hunt config: [${debugname}] unable to pack line!!!.\nInvalid property value: ${key}=${value}`); } - } + } else if (key === 'extracheck_var') { // 18-20 + if (extracheckVarsCount > 2) { + throw new Error(`Hunt config: [${debugname}] unable to pack line!!!.\nLimit of 3 extracheck_var properties exceeded.`); + } else if (value !== null && config.filter(x => x.key === 'type' && (x.value === HuntModeType.PLAYER)).length > 0) { + const checkVar: HuntCheckVar = value as HuntCheckVar; + server.p1(18 + extracheckVarsCount); + server.p2(checkVar.varp); + server.pjstr(checkVar.condition); + server.p4(checkVar.val); + extracheckVarsCount += 1; + } else { + throw new Error(`Hunt config: [${debugname}] unable to pack line!!!.\nInvalid property value: ${key}=${value}`); + } + } } server.p1(250); diff --git a/src/lostcity/cache/packconfig/IdkConfig.ts b/src/lostcity/pack/config/IdkConfig.ts similarity index 98% rename from src/lostcity/cache/packconfig/IdkConfig.ts rename to src/lostcity/pack/config/IdkConfig.ts index 7c24a51eb6..ec5152b8e5 100644 --- a/src/lostcity/cache/packconfig/IdkConfig.ts +++ b/src/lostcity/pack/config/IdkConfig.ts @@ -1,4 +1,4 @@ -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import ColorConversion from '#lostcity/util/ColorConversion.js'; import { IdkPack, ModelPack } from '#lostcity/util/PackFile.js'; diff --git a/src/lostcity/cache/packconfig/InvConfig.ts b/src/lostcity/pack/config/InvConfig.ts similarity index 98% rename from src/lostcity/cache/packconfig/InvConfig.ts rename to src/lostcity/pack/config/InvConfig.ts index f980d6ae50..0415f10ee2 100644 --- a/src/lostcity/cache/packconfig/InvConfig.ts +++ b/src/lostcity/pack/config/InvConfig.ts @@ -1,6 +1,6 @@ import InvType from '#lostcity/cache/config/InvType.js'; -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { InvPack, ObjPack } from '#lostcity/util/PackFile.js'; export function parseInvConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packconfig/LocConfig.ts b/src/lostcity/pack/config/LocConfig.ts similarity index 98% rename from src/lostcity/cache/packconfig/LocConfig.ts rename to src/lostcity/pack/config/LocConfig.ts index 5e71ae103a..37d7b33432 100644 --- a/src/lostcity/cache/packconfig/LocConfig.ts +++ b/src/lostcity/pack/config/LocConfig.ts @@ -1,8 +1,8 @@ import ParamType from '#lostcity/cache/config/ParamType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { LocModelShape, ConfigValue, ConfigLine, ParamValue, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; -import { lookupParamValue } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { LocModelShape, ConfigValue, ConfigLine, ParamValue, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; +import { lookupParamValue } from '#lostcity/pack/config/ParamConfig.js'; import ColorConversion from '#lostcity/util/ColorConversion.js'; import { CategoryPack, LocPack, ModelPack, SeqPack, TexturePack } from '#lostcity/util/PackFile.js'; @@ -303,6 +303,9 @@ export function packLocConfigs(configs: Map): { client: Pa } else if (key === 'mapfunction') { client.p1(60); client.p2(value as number); + } else if (key === 'category') { + server.p1(61); + server.p2(value as number); } else if (key === 'mirror') { if (value === true) { client.p1(62); @@ -339,9 +342,6 @@ export function packLocConfigs(configs: Map): { client: Pa if (value === true) { client.p1(73); } - } else if (key === 'category') { - server.p1(200); - server.p2(value as number); } } @@ -400,7 +400,7 @@ export function packLocConfigs(configs: Map): { client: Pa server.p1(params.length); for (let k = 0; k < params.length; k++) { - const paramData = params[k] as ParamValue; + const paramData = params[k]; server.p3(paramData.id); server.pbool(paramData.type === ScriptVarType.STRING); diff --git a/src/lostcity/cache/packconfig/MesAnimConfig.ts b/src/lostcity/pack/config/MesAnimConfig.ts similarity index 97% rename from src/lostcity/cache/packconfig/MesAnimConfig.ts rename to src/lostcity/pack/config/MesAnimConfig.ts index fd57c27bda..249758b628 100644 --- a/src/lostcity/cache/packconfig/MesAnimConfig.ts +++ b/src/lostcity/pack/config/MesAnimConfig.ts @@ -1,4 +1,4 @@ -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { MesAnimPack, SeqPack } from '#lostcity/util/PackFile.js'; export function parseMesAnimConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packconfig/NpcConfig.ts b/src/lostcity/pack/config/NpcConfig.ts similarity index 99% rename from src/lostcity/cache/packconfig/NpcConfig.ts rename to src/lostcity/pack/config/NpcConfig.ts index 15eacc5097..d38bac7297 100644 --- a/src/lostcity/cache/packconfig/NpcConfig.ts +++ b/src/lostcity/pack/config/NpcConfig.ts @@ -4,8 +4,8 @@ import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; import MoveRestrict from '#lostcity/entity/MoveRestrict.js'; import NpcMode from '#lostcity/entity/NpcMode.js'; -import { ParamValue, ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; -import { lookupParamValue } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { ParamValue, ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; +import { lookupParamValue } from '#lostcity/pack/config/ParamConfig.js'; import BlockWalk from '#lostcity/entity/BlockWalk.js'; import { CategoryPack, HuntPack, ModelPack, NpcPack, SeqPack } from '#lostcity/util/PackFile.js'; import ColorConversion from '#lostcity/util/ColorConversion.js'; diff --git a/src/lostcity/cache/packconfig/ObjConfig.ts b/src/lostcity/pack/config/ObjConfig.ts similarity index 96% rename from src/lostcity/cache/packconfig/ObjConfig.ts rename to src/lostcity/pack/config/ObjConfig.ts index 6ea77ba65a..fe0fa60f27 100644 --- a/src/lostcity/cache/packconfig/ObjConfig.ts +++ b/src/lostcity/pack/config/ObjConfig.ts @@ -2,8 +2,8 @@ import ObjType from '#lostcity/cache/config/ObjType.js'; import ParamType from '#lostcity/cache/config/ParamType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ParamValue, ConfigValue, ConfigLine, packStepError, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; -import { lookupParamValue } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { ParamValue, ConfigValue, ConfigLine, packStepError, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; +import { lookupParamValue } from '#lostcity/pack/config/ParamConfig.js'; import ColorConversion from '#lostcity/util/ColorConversion.js'; import { printWarning } from '#lostcity/util/Logger.js'; import { CategoryPack, ModelPack, ObjPack, SeqPack } from '#lostcity/util/PackFile.js'; @@ -221,14 +221,18 @@ export function packObjConfigs(configs: Map): { client: Pa // if no name we fill with the debug name let hasName = false; + let hasModel = false; for (let j = 0; j < config.length; j++) { - if (config[j].key === 'name') { + const key = config[j].key; + + if (key === 'name') { hasName = true; - break; + } else if (key === 'model') { + hasModel = true; } } - if (!hasName && config.length > 0) { + if (!hasName && hasModel) { const name = debugname.charAt(0).toUpperCase() + debugname.slice(1).replace(/_/g, ' '); config.push({ key: 'name', value: name }); } @@ -295,6 +299,10 @@ export function packObjConfigs(configs: Map): { client: Pa } else if (key === 'wearpos2') { server.p1(14); server.p1(value as number); + } else if (key === 'tradeable') { + if (value === false) { + server.p1(15); + } } else if (key === 'members') { if (value === true) { client.p1(16); @@ -369,10 +377,6 @@ export function packObjConfigs(configs: Map): { client: Pa client.p1(100 + index); client.p2(values[0]); client.p2(values[1]); - } else if (key === 'tradeable') { - if (value === true) { - server.p1(200); - } } else if (key === 'respawnrate') { server.p1(201); server.p2(value as number); @@ -406,7 +410,7 @@ export function packObjConfigs(configs: Map): { client: Pa server.p1(params.length); for (let k = 0; k < params.length; k++) { - const paramData = params[k] as ParamValue; + const paramData = params[k]; server.p3(paramData.id); server.pbool(paramData.type === ScriptVarType.STRING); diff --git a/src/lostcity/cache/packconfig/PackShared.ts b/src/lostcity/pack/config/PackShared.ts similarity index 74% rename from src/lostcity/cache/packconfig/PackShared.ts rename to src/lostcity/pack/config/PackShared.ts index ddd4f0f13d..74c1c39d7d 100644 --- a/src/lostcity/cache/packconfig/PackShared.ts +++ b/src/lostcity/pack/config/PackShared.ts @@ -1,38 +1,39 @@ import fs from 'fs'; +import readline from 'readline'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { VarnPack, VarpPack, VarsPack, shouldBuild } from '#lostcity/util/PackFile.js'; import ParamType from '#lostcity/cache/config/ParamType.js'; -import { packParamConfigs, parseParamConfig } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { packParamConfigs, parseParamConfig } from '#lostcity/pack/config/ParamConfig.js'; import { loadDir } from '#lostcity/util/NameMap.js'; -import { packFloConfigs, parseFloConfig } from '#lostcity/cache/packconfig/FloConfig.js'; -import { packIdkConfigs, parseIdkConfig } from '#lostcity/cache/packconfig/IdkConfig.js'; -import { packLocConfigs, parseLocConfig } from '#lostcity/cache/packconfig/LocConfig.js'; -import { packNpcConfigs, parseNpcConfig } from '#lostcity/cache/packconfig/NpcConfig.js'; -import { packObjConfigs, parseObjConfig } from '#lostcity/cache/packconfig/ObjConfig.js'; -import { packSeqConfigs, parseSeqConfig } from '#lostcity/cache/packconfig/SeqConfig.js'; -import { packSpotAnimConfigs, parseSpotAnimConfig } from '#lostcity/cache/packconfig/SpotAnimConfig.js'; -import { packVarpConfigs, parseVarpConfig } from '#lostcity/cache/packconfig/VarpConfig.js'; +import { packFloConfigs, parseFloConfig } from '#lostcity/pack/config/FloConfig.js'; +import { packIdkConfigs, parseIdkConfig } from '#lostcity/pack/config/IdkConfig.js'; +import { packLocConfigs, parseLocConfig } from '#lostcity/pack/config/LocConfig.js'; +import { packNpcConfigs, parseNpcConfig } from '#lostcity/pack/config/NpcConfig.js'; +import { packObjConfigs, parseObjConfig } from '#lostcity/pack/config/ObjConfig.js'; +import { packSeqConfigs, parseSeqConfig } from '#lostcity/pack/config/SeqConfig.js'; +import { packSpotAnimConfigs, parseSpotAnimConfig } from '#lostcity/pack/config/SpotAnimConfig.js'; +import { packVarpConfigs, parseVarpConfig } from '#lostcity/pack/config/VarpConfig.js'; import { AnimPack, CategoryPack, shouldBuildFile } from '#lostcity/util/PackFile.js'; import { listFilesExt } from '#lostcity/util/Parse.js'; import DbTableType from '#lostcity/cache/config/DbTableType.js'; -import { packDbRowConfigs, parseDbRowConfig } from '#lostcity/cache/packconfig/DbRowConfig.js'; -import { packDbTableConfigs, parseDbTableConfig } from '#lostcity/cache/packconfig/DbTableConfig.js'; -import { packEnumConfigs, parseEnumConfig } from '#lostcity/cache/packconfig/EnumConfig.js'; -import { packInvConfigs, parseInvConfig } from '#lostcity/cache/packconfig/InvConfig.js'; -import { packMesAnimConfigs, parseMesAnimConfig } from '#lostcity/cache/packconfig/MesAnimConfig.js'; -import { packStructConfigs, parseStructConfig } from '#lostcity/cache/packconfig/StructConfig.js'; -import { packHuntConfigs, parseHuntConfig } from '#lostcity/cache/packconfig/HuntConfig.js'; -import { packVarnConfigs, parseVarnConfig } from '#lostcity/cache/packconfig/VarnConfig.js'; -import { packVarsConfigs, parseVarsConfig } from '#lostcity/cache/packconfig/VarsConfig.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import { packDbRowConfigs, parseDbRowConfig } from '#lostcity/pack/config/DbRowConfig.js'; +import { packDbTableConfigs, parseDbTableConfig } from '#lostcity/pack/config/DbTableConfig.js'; +import { packEnumConfigs, parseEnumConfig } from '#lostcity/pack/config/EnumConfig.js'; +import { packInvConfigs, parseInvConfig } from '#lostcity/pack/config/InvConfig.js'; +import { packMesAnimConfigs, parseMesAnimConfig } from '#lostcity/pack/config/MesAnimConfig.js'; +import { packStructConfigs, parseStructConfig } from '#lostcity/pack/config/StructConfig.js'; +import { packHuntConfigs, parseHuntConfig } from '#lostcity/pack/config/HuntConfig.js'; +import { packVarnConfigs, parseVarnConfig } from '#lostcity/pack/config/VarnConfig.js'; +import { packVarsConfigs, parseVarsConfig } from '#lostcity/pack/config/VarsConfig.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import Environment from '#lostcity/util/Environment.js'; export function isConfigBoolean(input: string): boolean { @@ -91,74 +92,29 @@ export class PackedData { } export const CONSTANTS = new Map(); -loadDir('data/src/scripts', '.constant', src => { - for (let i = 0; i < src.length; i++) { - if (!src[i] || src[i].startsWith('//')) { - continue; - } - - const parts = src[i].split('='); - let name = parts[0].trim(); - const value = parts[1].trim(); - - if (name.startsWith('^')) { - name = name.substring(1); - } - - if (CONSTANTS.has(name)) { - throw new Error(`Duplicate constant found: ${name}`); - } - - CONSTANTS.set(name, value); - } -}); - -// var domains are global, so we need to check for conflicts - -for (let id = 0; id < VarpPack.size; id++) { - const name = VarpPack.getById(id); - - if (VarnPack.getByName(name) !== -1) { - throw new Error(`Varp and varn name conflict: ${name}\nPick a different name for one of them!`); - } - - if (VarsPack.getByName(name) !== -1) { - throw new Error(`Varp and vars name conflict: ${name}\nPick a different name for one of them!`); - } -} -for (let id = 0; id < VarnPack.size; id++) { - const name = VarnPack.getById(id); - - if (VarsPack.getByName(name) !== -1) { - throw new Error(`Varn and vars name conflict: ${name}\nPick a different name for one of them!`); - } -} - -export function findFiles(path: string, extension: string, results: string[] = []): string[] { +export function readDirTree(dirTree: Set, path: string) { const files = fs.readdirSync(path); - for (let i = 0; i < files.length; i++) { - if (fs.statSync(path + '/' + files[i]).isDirectory()) { - findFiles(path + '/' + files[i], extension, results); + for (const file of files) { + if (fs.statSync(path + '/' + file).isDirectory()) { + readDirTree(dirTree, path + '/' + file); } else { - if (files[i].endsWith(extension)) { - results.push(path + '/' + files[i]); - } + dirTree.add(path + '/' + file); } } - - return results; } -export function readFiles(files: string[]): Map { - const contents = new Map(); // key: file, value: content +export function findFiles(dirTree: Set, extension: string) { + const results = new Set(); - for (let i = 0; i < files.length; i++) { - contents.set(files[i], fs.readFileSync(files[i], 'utf8').replace(/\r/g, '')); + for (const entry of dirTree) { + if (entry.endsWith(extension)) { + results.add(entry); + } } - return contents; + return results; } export function parseStepError(file: string, lineNumber: number, message: string) { @@ -175,9 +131,10 @@ export type ParamValue = { value: string | number | boolean; }; export type LocModelShape = { model: number; shape: number }; -export type HuntCheckInv = { inv: number; obj: number; min: number; max: number; }; -export type HuntCheckInvParam = { inv: number; param: number; min: number; max: number; }; -export type ConfigValue = string | number | boolean | number[] | LocModelShape[] | ParamValue | HuntCheckInv | HuntCheckInvParam; +export type HuntCheckInv = { inv: number; obj: number; condition: string; val: number; }; +export type HuntCheckInvParam = { inv: number; param: number; condition: string; val: number; }; +export type HuntCheckVar = { varp: number; condition: string; val: number; } +export type ConfigValue = string | number | boolean | number[] | LocModelShape[] | ParamValue | HuntCheckInv | HuntCheckInvParam | HuntCheckVar; export type ConfigLine = { key: string; value: ConfigValue }; // we're using null for invalid values, undefined for invalid keys @@ -186,18 +143,22 @@ export type ConfigDatIdx = { client: PackedData, server: PackedData }; export type ConfigPackCallback = (configs: Map) => ConfigDatIdx; export type ConfigSaveCallback = (dat: Packet, idx: Packet) => void; -export function readConfigs(extension: string, requiredProperties: string[], parse: ConfigParseCallback, pack: ConfigPackCallback, saveClient: ConfigSaveCallback, saveServer: ConfigSaveCallback, srcDir: string = 'data/src/scripts') { - const files = readFiles(findFiles(srcDir, extension)); +export async function readConfigs(dirTree: Set, extension: string, requiredProperties: string[], parse: ConfigParseCallback, pack: ConfigPackCallback, saveClient: ConfigSaveCallback, saveServer: ConfigSaveCallback) { + const files = findFiles(dirTree, extension); const configs = new Map(); - files.forEach((value, file) => { - const lines = value.split('\n'); + for (const file of files) { + const reader = readline.createInterface({ + input: fs.createReadStream(file) + }); let debugname: string | null = null; let config: ConfigLine[] = []; - for (let lineNumber = 0; lineNumber < lines.length; lineNumber++) { - const line = lines[lineNumber]; + let lineNumber = 0; + for await (const line of reader) { + lineNumber++; + if (line.length === 0 || line.startsWith('//')) { continue; } @@ -288,29 +249,78 @@ export function readConfigs(extension: string, requiredProperties: string[], par configs.set(debugname, config); } - }); + } const { client, server } = pack(configs); saveClient(client.dat, client.idx); saveServer(server.dat, server.idx); } -// We have to pack params for other configs to parse correctly -if (shouldBuild('data/src/scripts', '.param', 'data/pack/server/param.dat')) { - readConfigs('.param', ['type'], parseParamConfig, packParamConfigs, () => {}, (dat: Packet, idx: Packet) => { - dat.save('data/pack/server/param.dat'); - idx.save('data/pack/server/param.idx'); - dat.release(); - idx.release(); +function noOp() { } + +export async function packConfigs() { + CONSTANTS.clear(); + + loadDir('data/src/scripts', '.constant', src => { + for (let i = 0; i < src.length; i++) { + if (!src[i] || src[i].startsWith('//')) { + continue; + } + + const parts = src[i].split('='); + let name = parts[0].trim(); + const value = parts[1].trim(); + + if (name.startsWith('^')) { + name = name.substring(1); + } + + if (CONSTANTS.has(name)) { + throw new Error(`Duplicate constant found: ${name}`); + } + + CONSTANTS.set(name, value); + } }); -} -// Now that they're up to date, load them for us to use elsewhere during this process -ParamType.load('data/pack'); + // var domains are global, so we need to check for conflicts + + for (let id = 0; id < VarpPack.size; id++) { + const name = VarpPack.getById(id); + + if (VarnPack.getByName(name) !== -1) { + throw new Error(`Varp and varn name conflict: ${name}\nPick a different name for one of them!`); + } + + if (VarsPack.getByName(name) !== -1) { + throw new Error(`Varp and vars name conflict: ${name}\nPick a different name for one of them!`); + } + } + + for (let id = 0; id < VarnPack.size; id++) { + const name = VarnPack.getById(id); + + if (VarsPack.getByName(name) !== -1) { + throw new Error(`Varn and vars name conflict: ${name}\nPick a different name for one of them!`); + } + } + + const dirTree = new Set(); + readDirTree(dirTree, 'data/src/scripts'); + + // We have to pack params for other configs to parse correctly + if (shouldBuild('data/src/scripts', '.param', 'data/pack/server/param.dat')) { + await readConfigs(dirTree, '.param', ['type'], parseParamConfig, packParamConfigs, () => { }, (dat: Packet, idx: Packet) => { + dat.save('data/pack/server/param.dat'); + idx.save('data/pack/server/param.idx'); + dat.release(); + idx.release(); + }); + } -function noOp() {} + // Now that they're up to date, load them for us to use elsewhere during this process + ParamType.load('data/pack'); -export function packConfigs() { const jag = new Jagfile(); /* client order: @@ -397,7 +407,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.dbtable', 'data/pack/server/dbtable.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/dbtable.dat') ) { - readConfigs('.dbtable', [], parseDbTableConfig, packDbTableConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.dbtable', [], parseDbTableConfig, packDbTableConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/dbtable.dat'); idx.save('data/pack/server/dbtable.idx'); dat.release(); @@ -414,7 +424,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.dbtable', 'data/pack/server/dbtable.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/dbtable.dat') ) { - readConfigs('.dbrow', [], parseDbRowConfig, packDbRowConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.dbrow', [], parseDbRowConfig, packDbRowConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/dbrow.dat'); idx.save('data/pack/server/dbrow.idx'); dat.release(); @@ -426,7 +436,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.enum', 'data/pack/server/enum.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/enum.dat') ) { - readConfigs('.enum', [], parseEnumConfig, packEnumConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.enum', [], parseEnumConfig, packEnumConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/enum.dat'); idx.save('data/pack/server/enum.idx'); dat.release(); @@ -438,7 +448,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.inv', 'data/pack/server/inv.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/inv.dat') ) { - readConfigs('.inv', [], parseInvConfig, packInvConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.inv', [], parseInvConfig, packInvConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/inv.dat'); idx.save('data/pack/server/inv.idx'); dat.release(); @@ -450,7 +460,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.mesanim', 'data/pack/server/mesanim.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/mesanim.dat') ) { - readConfigs('.mesanim', [], parseMesAnimConfig, packMesAnimConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.mesanim', [], parseMesAnimConfig, packMesAnimConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/mesanim.dat'); idx.save('data/pack/server/mesanim.idx'); dat.release(); @@ -462,7 +472,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.struct', 'data/pack/server/struct.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/struct.dat') ) { - readConfigs('.struct', [], parseStructConfig, packStructConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.struct', [], parseStructConfig, packStructConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/struct.dat'); idx.save('data/pack/server/struct.idx'); dat.release(); @@ -476,7 +486,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.seq', 'data/pack/server/seq.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/seq.dat') ) { - readConfigs('.seq', [], parseSeqConfig, packSeqConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.seq', [], parseSeqConfig, packSeqConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, 1638136604) || !Packet.checkcrc(idx.data, 0, idx.pos, 969051566))) { throw new Error('.seq CRC check failed! Custom data detected.'); } @@ -495,7 +505,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.loc', 'data/pack/server/loc.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/loc.dat') ) { - readConfigs('.loc', [], parseLocConfig, packLocConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.loc', [], parseLocConfig, packLocConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, 891497087) || !Packet.checkcrc(idx.data, 0, idx.pos, -941401128))) { throw new Error('.loc CRC check failed! Custom data detected.'); } @@ -514,7 +524,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.flo', 'data/pack/server/flo.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/flo.dat') ) { - readConfigs('.flo', [], parseFloConfig, packFloConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.flo', [], parseFloConfig, packFloConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, 1976597026) || !Packet.checkcrc(idx.data, 0, idx.pos, 561308705))) { throw new Error('.flo CRC check failed! Custom data detected.'); } @@ -533,7 +543,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.spotanim', 'data/pack/server/spotanim.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/spotanim.dat') ) { - readConfigs('.spotanim', [], parseSpotAnimConfig, packSpotAnimConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.spotanim', [], parseSpotAnimConfig, packSpotAnimConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, -1279835623) || !Packet.checkcrc(idx.data, 0, idx.pos, -1696140322))) { throw new Error('.spotanim CRC check failed! Custom data detected.'); } @@ -552,7 +562,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.npc', 'data/pack/server/npc.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/npc.dat') ) { - readConfigs('.npc', [], parseNpcConfig, packNpcConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.npc', [], parseNpcConfig, packNpcConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, -2140681882) || !Packet.checkcrc(idx.data, 0, idx.pos, -1986014643))) { throw new Error('.npc CRC check failed! Custom data detected.'); } @@ -571,7 +581,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.obj', 'data/pack/server/obj.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/obj.dat') ) { - readConfigs('.obj', [], parseObjConfig, packObjConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.obj', [], parseObjConfig, packObjConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, -840233510) || !Packet.checkcrc(idx.data, 0, idx.pos, 669212954))) { throw new Error('.obj CRC check failed! Custom data detected.'); } @@ -590,7 +600,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.idk', 'data/pack/server/idk.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/idk.dat') ) { - readConfigs('.idk', [], parseIdkConfig, packIdkConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.idk', [], parseIdkConfig, packIdkConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, -359342366) || !Packet.checkcrc(idx.data, 0, idx.pos, 667216411))) { throw new Error('.idk CRC check failed! Custom data detected.'); } @@ -609,7 +619,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.varp', 'data/pack/server/varp.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/varp.dat') ) { - readConfigs('.varp', [], parseVarpConfig, packVarpConfigs, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.varp', [], parseVarpConfig, packVarpConfigs, (dat: Packet, idx: Packet) => { if (Environment.BUILD_VERIFY && (!Packet.checkcrc(dat.data, 0, dat.pos, 705633567) || !Packet.checkcrc(idx.data, 0, idx.pos, -1843167599))) { throw new Error('.varp CRC check failed! Custom data detected.'); } @@ -628,7 +638,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.hunt', 'data/pack/server/hunt.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/hunt.dat') ) { - readConfigs('.hunt', [], parseHuntConfig, packHuntConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.hunt', [], parseHuntConfig, packHuntConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/hunt.dat'); idx.save('data/pack/server/hunt.idx'); dat.release(); @@ -640,7 +650,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.varn', 'data/pack/server/varn.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/varn.dat') ) { - readConfigs('.varn', [], parseVarnConfig, packVarnConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.varn', [], parseVarnConfig, packVarnConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/varn.dat'); idx.save('data/pack/server/varn.idx'); dat.release(); @@ -652,7 +662,7 @@ export function packConfigs() { shouldBuild('data/src/scripts', '.vars', 'data/pack/server/vars.dat') || shouldBuild('src/lostcity/cache/packconfig', '.ts', 'data/pack/server/vars.dat') ) { - readConfigs('.vars', [], parseVarsConfig, packVarsConfigs, noOp, (dat: Packet, idx: Packet) => { + await readConfigs(dirTree, '.vars', [], parseVarsConfig, packVarsConfigs, noOp, (dat: Packet, idx: Packet) => { dat.save('data/pack/server/vars.dat'); idx.save('data/pack/server/vars.idx'); dat.release(); diff --git a/src/lostcity/cache/packconfig/ParamConfig.ts b/src/lostcity/pack/config/ParamConfig.ts similarity index 98% rename from src/lostcity/cache/packconfig/ParamConfig.ts rename to src/lostcity/pack/config/ParamConfig.ts index 5a27e8fed7..02462ed183 100644 --- a/src/lostcity/cache/packconfig/ParamConfig.ts +++ b/src/lostcity/pack/config/ParamConfig.ts @@ -1,6 +1,6 @@ import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ConfigValue, ConfigLine, packStepError, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, packStepError, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { CategoryPack, EnumPack, InterfacePack, InvPack, LocPack, NpcPack, ObjPack, ParamPack, SeqPack, SoundPack, SpotAnimPack, StructPack, VarpPack } from '#lostcity/util/PackFile.js'; const stats: (string | null)[] = [ diff --git a/src/lostcity/cache/packconfig/SeqConfig.ts b/src/lostcity/pack/config/SeqConfig.ts similarity index 98% rename from src/lostcity/cache/packconfig/SeqConfig.ts rename to src/lostcity/pack/config/SeqConfig.ts index 0c47df3f31..6bd4e34351 100644 --- a/src/lostcity/cache/packconfig/SeqConfig.ts +++ b/src/lostcity/pack/config/SeqConfig.ts @@ -1,4 +1,4 @@ -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { AnimPack, ObjPack, SeqPack } from '#lostcity/util/PackFile.js'; export function parseSeqConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packconfig/SpotAnimConfig.ts b/src/lostcity/pack/config/SpotAnimConfig.ts similarity index 98% rename from src/lostcity/cache/packconfig/SpotAnimConfig.ts rename to src/lostcity/pack/config/SpotAnimConfig.ts index fe8a32531d..c3590ae93d 100644 --- a/src/lostcity/cache/packconfig/SpotAnimConfig.ts +++ b/src/lostcity/pack/config/SpotAnimConfig.ts @@ -1,4 +1,4 @@ -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import ColorConversion from '#lostcity/util/ColorConversion.js'; import { ModelPack, SeqPack, SpotAnimPack } from '#lostcity/util/PackFile.js'; diff --git a/src/lostcity/cache/packconfig/StructConfig.ts b/src/lostcity/pack/config/StructConfig.ts similarity index 93% rename from src/lostcity/cache/packconfig/StructConfig.ts rename to src/lostcity/pack/config/StructConfig.ts index c99ce3a35d..903d0db82f 100644 --- a/src/lostcity/cache/packconfig/StructConfig.ts +++ b/src/lostcity/pack/config/StructConfig.ts @@ -1,8 +1,8 @@ import ParamType from '#lostcity/cache/config/ParamType.js'; import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ConfigValue, ConfigLine, ParamValue, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; -import { lookupParamValue } from '#lostcity/cache/packconfig/ParamConfig.js'; +import { ConfigValue, ConfigLine, ParamValue, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; +import { lookupParamValue } from '#lostcity/pack/config/ParamConfig.js'; import { StructPack } from '#lostcity/util/PackFile.js'; export function parseStructConfig(key: string, value: string): ConfigValue | null | undefined { @@ -91,7 +91,7 @@ export function packStructConfigs(configs: Map): { client: server.p1(params.length); for (let k = 0; k < params.length; k++) { - const paramData = params[k] as ParamValue; + const paramData = params[k]; server.p3(paramData.id); server.pbool(paramData.type === ScriptVarType.STRING); diff --git a/src/lostcity/cache/packconfig/VarnConfig.ts b/src/lostcity/pack/config/VarnConfig.ts similarity index 97% rename from src/lostcity/cache/packconfig/VarnConfig.ts rename to src/lostcity/pack/config/VarnConfig.ts index e12488057b..1cd68f28dd 100644 --- a/src/lostcity/cache/packconfig/VarnConfig.ts +++ b/src/lostcity/pack/config/VarnConfig.ts @@ -1,6 +1,6 @@ import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { VarnPack } from '#lostcity/util/PackFile.js'; export function parseVarnConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packconfig/VarpConfig.ts b/src/lostcity/pack/config/VarpConfig.ts similarity index 97% rename from src/lostcity/cache/packconfig/VarpConfig.ts rename to src/lostcity/pack/config/VarpConfig.ts index fb20c7082f..b76dc00a81 100644 --- a/src/lostcity/cache/packconfig/VarpConfig.ts +++ b/src/lostcity/pack/config/VarpConfig.ts @@ -1,7 +1,7 @@ import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; import VarPlayerType from '#lostcity/cache/config/VarPlayerType.js'; -import { PackedData, ConfigValue, ConfigLine, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { PackedData, ConfigValue, ConfigLine, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { VarpPack } from '#lostcity/util/PackFile.js'; export function parseVarpConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packconfig/VarsConfig.ts b/src/lostcity/pack/config/VarsConfig.ts similarity index 97% rename from src/lostcity/cache/packconfig/VarsConfig.ts rename to src/lostcity/pack/config/VarsConfig.ts index 2ff177db93..0866ca2eea 100644 --- a/src/lostcity/cache/packconfig/VarsConfig.ts +++ b/src/lostcity/pack/config/VarsConfig.ts @@ -1,6 +1,6 @@ import ScriptVarType from '#lostcity/cache/config/ScriptVarType.js'; -import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/cache/packconfig/PackShared.js'; +import { ConfigValue, ConfigLine, PackedData, isConfigBoolean, getConfigBoolean } from '#lostcity/pack/config/PackShared.js'; import { VarsPack } from '#lostcity/util/PackFile.js'; export function parseVarsConfig(key: string, value: string): ConfigValue | null | undefined { diff --git a/src/lostcity/cache/packgraphics/pack.ts b/src/lostcity/pack/graphics/pack.ts similarity index 98% rename from src/lostcity/cache/packgraphics/pack.ts rename to src/lostcity/pack/graphics/pack.ts index 16c99df67e..1b666559ba 100644 --- a/src/lostcity/cache/packgraphics/pack.ts +++ b/src/lostcity/pack/graphics/pack.ts @@ -1,12 +1,12 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { loadOrder, listFiles } from '#lostcity/util/NameMap.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import { AnimPack, BasePack, ModelPack, shouldBuildFile, shouldBuildFileAny } from '#lostcity/util/PackFile.js'; import path from 'path'; import { printError } from '#lostcity/util/Logger.js'; export function packClientModel() { - if (!shouldBuildFile('src/lostcity/cache/packgraphics/pack.ts', 'data/pack/client/models') && + if (!shouldBuildFile('src/lostcity/pack/graphics/pack.ts', 'data/pack/client/models') && !shouldBuildFileAny('data/src/models', 'data/pack/client/models') ) { return; diff --git a/src/lostcity/cache/packconfig/recolor.ts b/src/lostcity/pack/graphics/recolor.ts similarity index 99% rename from src/lostcity/cache/packconfig/recolor.ts rename to src/lostcity/pack/graphics/recolor.ts index 7ac97f58e4..d68e99970a 100644 --- a/src/lostcity/cache/packconfig/recolor.ts +++ b/src/lostcity/pack/graphics/recolor.ts @@ -2,7 +2,7 @@ import fs from 'fs'; import ColorConversion from '#lostcity/util/ColorConversion.js'; import { loadDirExact, loadPack } from '#lostcity/util/NameMap.js'; import Model from '#lostcity/cache/graphics/Model.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; Model.unpack(Jagfile.load('data/pack/client/models')); diff --git a/src/lostcity/cache/packgraphics/reorg.ts b/src/lostcity/pack/graphics/reorg.ts similarity index 100% rename from src/lostcity/cache/packgraphics/reorg.ts rename to src/lostcity/pack/graphics/reorg.ts diff --git a/src/lostcity/cache/packgraphics/unpack.ts b/src/lostcity/pack/graphics/unpack.ts similarity index 98% rename from src/lostcity/cache/packgraphics/unpack.ts rename to src/lostcity/pack/graphics/unpack.ts index adfd035fbc..610a7c56a7 100644 --- a/src/lostcity/cache/packgraphics/unpack.ts +++ b/src/lostcity/pack/graphics/unpack.ts @@ -1,7 +1,7 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import Model from '#lostcity/cache/graphics/Model.js'; import { printWarning } from '#lostcity/util/Logger.js'; diff --git a/src/lostcity/cache/packinterface/PackClient.ts b/src/lostcity/pack/interface/PackClient.ts similarity index 94% rename from src/lostcity/cache/packinterface/PackClient.ts rename to src/lostcity/pack/interface/PackClient.ts index 137c4d1cab..0a38a431de 100644 --- a/src/lostcity/cache/packinterface/PackClient.ts +++ b/src/lostcity/pack/interface/PackClient.ts @@ -1,4 +1,4 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import { shouldBuild } from '#lostcity/util/PackFile.js'; import { packInterface } from './PackShared.js'; diff --git a/src/lostcity/cache/packinterface/PackServer.ts b/src/lostcity/pack/interface/PackServer.ts similarity index 100% rename from src/lostcity/cache/packinterface/PackServer.ts rename to src/lostcity/pack/interface/PackServer.ts diff --git a/src/lostcity/cache/packinterface/PackShared.ts b/src/lostcity/pack/interface/PackShared.ts similarity index 99% rename from src/lostcity/cache/packinterface/PackShared.ts rename to src/lostcity/pack/interface/PackShared.ts index 271cdb2e5e..1263fb0c68 100644 --- a/src/lostcity/cache/packinterface/PackShared.ts +++ b/src/lostcity/pack/interface/PackShared.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import { printError } from '#lostcity/util/Logger.js'; import { loadDir, loadOrder } from '#lostcity/util/NameMap.js'; import { InterfacePack, ModelPack, ObjPack, SeqPack, VarpPack } from '#lostcity/util/PackFile.js'; @@ -192,7 +192,7 @@ export function packInterface(server: boolean) { comName = line.substring(1, line.length - 1); comId = InterfacePack.getByName(`${ifName}:${comName}`); if (comId === -1 || typeof component[comId] === 'undefined') { - throw new Error(`Missing component ID ${ifName}:${comName} in data/src/pack/interface.pack`); + throw new Error(`Missing component ID ${ifName}:${comName} in data/src/pack/interface.order`); } component[comId].root = ifName; diff --git a/src/lostcity/cache/packinterface/Unpack.ts b/src/lostcity/pack/interface/Unpack.ts similarity index 99% rename from src/lostcity/cache/packinterface/Unpack.ts rename to src/lostcity/pack/interface/Unpack.ts index e0ad695f03..fd4a107964 100644 --- a/src/lostcity/cache/packinterface/Unpack.ts +++ b/src/lostcity/pack/interface/Unpack.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import { loadPack } from '#lostcity/util/NameMap.js'; import { printWarning } from '#lostcity/util/Logger.js'; diff --git a/src/lostcity/cache/packmap/PackClient.js b/src/lostcity/pack/map/PackClient.js similarity index 99% rename from src/lostcity/cache/packmap/PackClient.js rename to src/lostcity/pack/map/PackClient.js index eaa61841ed..7ffebc7dc4 100644 --- a/src/lostcity/cache/packmap/PackClient.js +++ b/src/lostcity/pack/map/PackClient.js @@ -1,7 +1,7 @@ import fs from 'fs'; -import BZip2 from '#jagex2/io/BZip2.js'; -import Packet2 from '#jagex2/io/Packet.ts'; +import BZip2 from '#jagex/io/BZip2.js'; +import Packet2 from '#jagex/io/Packet.js'; import { shouldBuildFile } from '#lostcity/util/PackFile.js'; function readMap(map) { diff --git a/src/lostcity/cache/packmap/PackServer.js b/src/lostcity/pack/map/PackServer.js similarity index 99% rename from src/lostcity/cache/packmap/PackServer.js rename to src/lostcity/pack/map/PackServer.js index 2a3c5b67a2..918cbe5481 100644 --- a/src/lostcity/cache/packmap/PackServer.js +++ b/src/lostcity/pack/map/PackServer.js @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet2 from '#jagex2/io/Packet.ts'; +import Packet2 from '#jagex/io/Packet.js'; import { shouldBuild, shouldBuildFile } from '#lostcity/util/PackFile.js'; function readMap(map) { diff --git a/src/lostcity/cache/packmap/Unpack.ts b/src/lostcity/pack/map/Unpack.ts similarity index 98% rename from src/lostcity/cache/packmap/Unpack.ts rename to src/lostcity/pack/map/Unpack.ts index 869bfd2e6d..600ab6a3cd 100644 --- a/src/lostcity/cache/packmap/Unpack.ts +++ b/src/lostcity/pack/map/Unpack.ts @@ -1,7 +1,7 @@ import fs from 'fs'; -import BZip2 from '#jagex2/io/BZip2.js'; -import Packet from '#jagex2/io/Packet.js'; +import BZip2 from '#jagex/io/BZip2.js'; +import Packet from '#jagex/io/Packet.js'; import { printInfo } from '#lostcity/util/Logger.js'; const maps = fs.readdirSync('dump/maps'); diff --git a/src/lostcity/cache/packmap/Worldmap.ts b/src/lostcity/pack/map/Worldmap.ts similarity index 98% rename from src/lostcity/cache/packmap/Worldmap.ts rename to src/lostcity/pack/map/Worldmap.ts index 26ad1b94f6..1888b216a7 100644 --- a/src/lostcity/cache/packmap/Worldmap.ts +++ b/src/lostcity/pack/map/Worldmap.ts @@ -1,7 +1,7 @@ import fs from 'fs'; -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; import FloType from '#lostcity/cache/config/FloType.js'; import LocType from '#lostcity/cache/config/LocType.js'; @@ -34,7 +34,7 @@ export async function packWorldmap() { if ( !shouldBuildFileAny('data/pack/server/maps', 'data/pack/mapview/worldmap.jag') && - !shouldBuildFile('src/lostcity/cache/packmap/Worldmap.ts', 'data/pack/mapview/worldmap.jag') + !shouldBuildFile('src/lostcity/pack/map/Worldmap.ts', 'data/pack/mapview/worldmap.jag') ) { return; } @@ -662,16 +662,16 @@ export async function packWorldmap() { const index = Packet.alloc(1); const mapscene = await convertImage(index, 'data/src/sprites', 'mapscene'); - jag.write('mapscene.dat', mapscene!); + jag.write('mapscene.dat', mapscene); const mapfunction = await convertImage(index, 'data/src/sprites', 'mapfunction'); - jag.write('mapfunction.dat', mapfunction!); + jag.write('mapfunction.dat', mapfunction); const b12 = await convertImage(index, 'data/src/fonts', 'b12'); - jag.write('b12.dat', b12!); + jag.write('b12.dat', b12); const mapdots = await convertImage(index, 'data/src/sprites', 'mapdots'); - jag.write('mapdots.dat', mapdots!); + jag.write('mapdots.dat', mapdots); jag.write('index.dat', index); diff --git a/src/lostcity/cache/packmidi/pack.ts b/src/lostcity/pack/midi/pack.ts similarity index 96% rename from src/lostcity/cache/packmidi/pack.ts rename to src/lostcity/pack/midi/pack.ts index 9c126a1cc2..86c25eff4c 100644 --- a/src/lostcity/cache/packmidi/pack.ts +++ b/src/lostcity/pack/midi/pack.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import BZip2 from '#jagex2/io/BZip2.js'; +import BZip2 from '#jagex/io/BZip2.js'; import { shouldBuild } from '#lostcity/util/PackFile.js'; export function packClientMusic() { diff --git a/src/lostcity/pack/packall.ts b/src/lostcity/pack/packall.ts new file mode 100644 index 0000000000..0356f06ad5 --- /dev/null +++ b/src/lostcity/pack/packall.ts @@ -0,0 +1,96 @@ +import fs from 'fs'; +import child_process from 'child_process'; +import { parentPort } from 'worker_threads'; + +import { packServerInterface } from '#lostcity/pack/interface/PackServer.js'; +import { packServerMap } from '#lostcity/pack/map/PackServer.js'; +import { generateServerSymbols } from '#lostcity/pack/symbols.js'; +import { packConfigs } from '#lostcity/pack/config/PackShared.js'; +import { packWorldmap } from '#lostcity/pack/map/Worldmap.js'; +import Environment from '#lostcity/util/Environment.js'; +import { revalidatePack } from '#lostcity/util/PackFile.js'; + +import { packClientInterface } from '#lostcity/pack/interface/PackClient.js'; +import { packClientMap } from '#lostcity/pack/map/PackClient.js'; +import { packClientModel } from '#lostcity/pack/graphics/pack.js'; +import { packClientMusic } from '#lostcity/pack/midi/pack.js'; +import { packClientSound } from '#lostcity/pack/sound/pack.js'; +import { packClientWordenc } from '#lostcity/pack/chat/pack.js'; +import { packClientTitle } from '#lostcity/pack/sprite/title.js'; +import { packClientTexture } from '#lostcity/pack/sprite/textures.js'; +import { packClientMedia } from '#lostcity/pack/sprite/media.js'; +import { CrcBuffer } from '#lostcity/server/CrcTable.js'; + +export async function packServer() { + if (!fs.existsSync('RuneScriptCompiler.jar')) { + throw new Error('The RuneScript compiler is missing and the build process cannot continue.'); + } + + if (parentPort) { + parentPort.postMessage({ + type: 'dev_progress', + broadcast: 'Packing server cache (1/2)' + }); + } + + revalidatePack(); + await packConfigs(); + packServerInterface(); + + packServerMap(); + await packWorldmap(); + + generateServerSymbols(); + + if (parentPort) { + parentPort.postMessage({ + type: 'dev_progress', + text: 'Compiling server scripts' + }); + } + + try { + child_process.execSync(`"${Environment.BUILD_JAVA_PATH}" -jar RuneScriptCompiler.jar`, { stdio: 'inherit' }); + } catch (err) { + throw new Error('Failed to compile scripts.'); + } + + if (parentPort) { + parentPort.postMessage({ + type: 'dev_progress', + text: 'Packed server cache (1/2)' + }); + } + + fs.writeFileSync('data/pack/server/lastbuild.pack', ''); +} + +export async function packClient() { + if (parentPort) { + parentPort.postMessage({ + type: 'dev_progress', + broadcast: 'Packing client cache (2/2)' + }); + } + + await packClientTitle(); + packClientInterface(); + await packClientMedia(); + packClientModel(); + await packClientTexture(); + packClientWordenc(); + packClientSound(); + + packClientMap(); + packClientMusic(); + + if (parentPort) { + parentPort.postMessage({ + type: 'dev_progress', + text: 'Packed client cache (2/2)' + }); + } + + fs.writeFileSync('data/pack/client/crc', CrcBuffer.data); + fs.writeFileSync('data/pack/client/lastbuild.pack', ''); +} diff --git a/src/lostcity/cache/packsound/pack.ts b/src/lostcity/pack/sound/pack.ts similarity index 90% rename from src/lostcity/cache/packsound/pack.ts rename to src/lostcity/pack/sound/pack.ts index 7708272ce9..f483a438b6 100644 --- a/src/lostcity/cache/packsound/pack.ts +++ b/src/lostcity/pack/sound/pack.ts @@ -1,7 +1,7 @@ import fs from 'fs'; -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; import { loadOrder } from '#lostcity/util/NameMap.js'; import { SoundPack, shouldBuildFileAny } from '#lostcity/util/PackFile.js'; diff --git a/src/lostcity/cache/packsound/reorg.ts b/src/lostcity/pack/sound/reorg.ts similarity index 100% rename from src/lostcity/cache/packsound/reorg.ts rename to src/lostcity/pack/sound/reorg.ts diff --git a/src/lostcity/cache/packsound/unpack.ts b/src/lostcity/pack/sound/unpack.ts similarity index 97% rename from src/lostcity/cache/packsound/unpack.ts rename to src/lostcity/pack/sound/unpack.ts index f493645b1a..575ff5f6f2 100644 --- a/src/lostcity/cache/packsound/unpack.ts +++ b/src/lostcity/pack/sound/unpack.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; if (!fs.existsSync('data/src/sounds')) { fs.mkdirSync('data/src/sounds', { recursive: true }); diff --git a/src/lostcity/cache/packsprite/media/pack.ts b/src/lostcity/pack/sprite/media.ts similarity index 97% rename from src/lostcity/cache/packsprite/media/pack.ts rename to src/lostcity/pack/sprite/media.ts index 8be732534c..cbc931bbb4 100644 --- a/src/lostcity/cache/packsprite/media/pack.ts +++ b/src/lostcity/pack/sprite/media.ts @@ -1,5 +1,5 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; import { shouldBuildFileAny } from '#lostcity/util/PackFile.js'; import { convertImage } from '#lostcity/util/PixPack.js'; diff --git a/src/lostcity/cache/packsprite/textures/pack.ts b/src/lostcity/pack/sprite/textures.ts similarity index 96% rename from src/lostcity/cache/packsprite/textures/pack.ts rename to src/lostcity/pack/sprite/textures.ts index dc9fc8539e..fb2e29a4c8 100644 --- a/src/lostcity/cache/packsprite/textures/pack.ts +++ b/src/lostcity/pack/sprite/textures.ts @@ -1,10 +1,10 @@ import fs from 'fs'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; import { convertImage } from '#lostcity/util/PixPack.js'; import { shouldBuildFileAny } from '#lostcity/util/PackFile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export async function packClientTexture() { if (!shouldBuildFileAny('data/src/textures', 'data/pack/client/textures')) { diff --git a/src/lostcity/cache/packsprite/title/pack.ts b/src/lostcity/pack/sprite/title.ts similarity index 95% rename from src/lostcity/cache/packsprite/title/pack.ts rename to src/lostcity/pack/sprite/title.ts index 88ed75c912..97e2ecd17c 100644 --- a/src/lostcity/cache/packsprite/title/pack.ts +++ b/src/lostcity/pack/sprite/title.ts @@ -1,5 +1,5 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; import { shouldBuildFileAny } from '#lostcity/util/PackFile.js'; import { convertImage } from '#lostcity/util/PixPack.js'; diff --git a/src/lostcity/cache/symbols.ts b/src/lostcity/pack/symbols.ts similarity index 98% rename from src/lostcity/cache/symbols.ts rename to src/lostcity/pack/symbols.ts index 686428f77b..4742858bd2 100644 --- a/src/lostcity/cache/symbols.ts +++ b/src/lostcity/pack/symbols.ts @@ -22,13 +22,17 @@ export function generateServerSymbols() { } const parts = src[i].split('='); - let name = parts[0].trim(); - const value = parts[1].trim(); + let name = parts[0].trim(); if (name.startsWith('^')) { name = name.substring(1); } + let value = parts[1].trim(); + if (value.startsWith('"') && value.endsWith('"')) { + value = value.substring(1, value.length - 1); + } + constants[name] = value; } }); diff --git a/src/lostcity/prometheus.ts b/src/lostcity/prometheus.ts new file mode 100644 index 0000000000..3497d09851 --- /dev/null +++ b/src/lostcity/prometheus.ts @@ -0,0 +1,68 @@ +import { Counter, Gauge, Histogram } from 'prom-client'; + +export const trackPlayerCount = new Gauge({ name: 'lostcity_active_players', help: 'Active player count.' }); +export const trackNpcCount = new Gauge({ name: 'lostcity_active_npcs', help: 'Active NPC count.' }); + +export const trackCycleTime = new Histogram({ + name: 'lostcity_cycle_ms', + help: 'Overall processing duration in milliseconds.', + buckets: [10, 20, 30, 50, 80, 100, 150, 200, 250, 300, 400, 450, 550, 600, 800, 1000] +}); + +export const trackCycleWorldTime = new Histogram({ + name: 'lostcity_cycle_world_ms', + help: 'World (not overall) processing duration in milliseconds.', + buckets: [10, 20, 30, 40, 50, 100] +}); + +export const trackCycleClientInTime = new Histogram({ + name: 'lostcity_cycle_client_in_ms', + help: 'Client In processing duration in milliseconds.', + buckets: [10, 30, 50, 100, 200, 300, 400] +}); + +export const trackCycleClientOutTime = new Histogram({ + name: 'lostcity_cycle_client_out_ms', + help: 'Client Out processing duration in milliseconds.', + buckets: [10, 30, 50, 100, 200, 300, 400] +}); + +export const trackCycleNpcTime = new Histogram({ + name: 'lostcity_cycle_npc_ms', + help: 'NPC processing duration in milliseconds.', + buckets: [10, 20, 30, 40, 50, 100] +}); + +export const trackCyclePlayerTime = new Histogram({ + name: 'lostcity_cycle_player_ms', + help: 'Player processing duration in milliseconds.', + buckets: [10, 20, 30, 40, 50, 100] +}); + +export const trackCycleZoneTime = new Histogram({ + name: 'lostcity_cycle_zone_ms', + help: 'Zone processing duration in milliseconds.', + buckets: [10, 20, 30, 40, 50, 100] +}); + +export const trackCycleLoginTime = new Histogram({ + name: 'lostcity_cycle_login_ms', + help: 'Login processing duration in milliseconds.', + buckets: [10, 30, 50, 100] +}); + +export const trackCycleLogoutTime = new Histogram({ + name: 'lostcity_cycle_logout_ms', + help: 'Logout processing duration in milliseconds.', + buckets: [10, 30, 50, 100] +}); + +export const trackCycleBandwidthInBytes = new Counter({ + name: 'lostcity_cycle_bandwidth_in_bytes', + help: 'Total incoming bandwidth in bytes.' +}); + +export const trackCycleBandwidthOutBytes = new Counter({ + name: 'lostcity_cycle_bandwidth_out_bytes', + help: 'Total outgoing bandwidth in bytes.' +}); diff --git a/src/lostcity/tools/cache/cacheRename.ts b/src/lostcity/scripts/cache/cacheRename.ts similarity index 90% rename from src/lostcity/tools/cache/cacheRename.ts rename to src/lostcity/scripts/cache/cacheRename.ts index bad58d5418..db29376eb0 100644 --- a/src/lostcity/tools/cache/cacheRename.ts +++ b/src/lostcity/scripts/cache/cacheRename.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import { fromBase37 } from '#jagex2/jstring/JString.js'; +import { fromBase37 } from '#jagex/jstring/JString.js'; import { printFatalError } from '#lostcity/util/Logger.js'; const args = process.argv.slice(2); diff --git a/src/lostcity/tools/cache/cleanClient.ts b/src/lostcity/scripts/cache/cleanClient.ts similarity index 100% rename from src/lostcity/tools/cache/cleanClient.ts rename to src/lostcity/scripts/cache/cleanClient.ts diff --git a/src/lostcity/tools/cache/cleanServer.ts b/src/lostcity/scripts/cache/cleanServer.ts similarity index 100% rename from src/lostcity/tools/cache/cleanServer.ts rename to src/lostcity/scripts/cache/cleanServer.ts diff --git a/src/lostcity/scripts/cache/findMismatch.ts b/src/lostcity/scripts/cache/findMismatch.ts new file mode 100644 index 0000000000..fffc976cb5 --- /dev/null +++ b/src/lostcity/scripts/cache/findMismatch.ts @@ -0,0 +1,23 @@ +import Packet from '#jagex/io/Packet.js'; +import { printFatalError } from '#lostcity/util/Logger.js'; + +const oldIdx = Packet.load('dump/unpack/config.raw/obj.idx'); +const newIdx = Packet.load('dump/new.idx'); + +const oldCount = oldIdx.g2(); +const newCount = newIdx.g2(); + +if (oldCount !== newCount) { + printFatalError('configs are different sizes'); +} + +for (let i = 0; i < newCount; i++) { + const oldLen = oldIdx.g2(); + const newLen = newIdx.g2(); + + console.log(i, oldLen, newLen); + + if (oldLen !== newLen) { + break; + } +} diff --git a/src/lostcity/tools/cache/jagCompare.ts b/src/lostcity/scripts/cache/jagCompare.ts similarity index 96% rename from src/lostcity/tools/cache/jagCompare.ts rename to src/lostcity/scripts/cache/jagCompare.ts index d01a0eaa10..91c150e087 100644 --- a/src/lostcity/tools/cache/jagCompare.ts +++ b/src/lostcity/scripts/cache/jagCompare.ts @@ -1,5 +1,5 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; +import Jagfile from '#jagex/io/Jagfile.js'; +import Packet from '#jagex/io/Packet.js'; const args = process.argv.slice(2); diff --git a/src/lostcity/tools/cache/jagUnpack.ts b/src/lostcity/scripts/cache/jagUnpack.ts similarity index 91% rename from src/lostcity/tools/cache/jagUnpack.ts rename to src/lostcity/scripts/cache/jagUnpack.ts index d8ebc84eed..c51b342c40 100644 --- a/src/lostcity/tools/cache/jagUnpack.ts +++ b/src/lostcity/scripts/cache/jagUnpack.ts @@ -1,6 +1,6 @@ import path from 'path'; -import Jagfile from '#jagex2/io/Jagfile.js'; +import Jagfile from '#jagex/io/Jagfile.js'; const args = process.argv.slice(2); diff --git a/src/lostcity/scripts/cache/organizeMaps.ts b/src/lostcity/scripts/cache/organizeMaps.ts new file mode 100644 index 0000000000..d51d5d4663 --- /dev/null +++ b/src/lostcity/scripts/cache/organizeMaps.ts @@ -0,0 +1,148 @@ +import fs from 'fs'; +import path from 'path'; + +import Packet from '#jagex/io/Packet.js'; + +import { fromBase37 } from '#jagex/jstring/JString.js'; + +const args = process.argv.splice(2); + +if (!args.length) { + process.exit(1); +} + +const searchDir = args[0]; + +type MapEntry = { + filePath: string, + name: string, + ctime: number, + size: number, + checksum: number +}; + +const dirs = fs.readdirSync(searchDir); +const allFiles: MapEntry[] = []; +const betaFiles: MapEntry[] = []; + +for (const dir of dirs) { + const dirPath = path.join(searchDir, dir); + if (!fs.statSync(dirPath).isDirectory()) { + continue; + } + + const files = fs.readdirSync(dirPath); + + for (const file of files) { + const name = fromBase37(BigInt(file)); + + if (name === 'invalid_name') { + // console.log('unknown file:', file); + continue; + } + + const filePath = path.join(searchDir, dir, file); + + if (name.match(/[lm]\d+_\d+/)) { + // lX_Z and mX_Z maps + const stats = fs.statSync(filePath); + const data = Packet.load(filePath); + + // users might have uploaded corrupted files + let bad = false; + for (let i = 0; i < 8; i++) { + // "bad_ntfs_decompr" - 6261645F6E7466735F6465636F6D7072 + const sig = data.g4(); + data.pos -= 3; + if (sig === 0x5F6E7466) { + // "_ntf" spotted in the first 12 bytes + bad = true; + } else if (sig === 0x08080808) { + // repeating 08 spotted + bad = true; + } + } + if (bad) { + continue; + } + + const checksum = Packet.getcrc(data.data, 0, data.length); + + if (fs.statSync(filePath).birthtime >= new Date('2004-02-01T00:00:00')) { + allFiles.push({ + filePath, + name, + ctime: stats.birthtimeMs, + size: stats.size, + checksum + }); + } else { + // these beta files use a different set of IDs so they're "incompatible" as-is, or in some cases, only existed for a short while + betaFiles.push({ + filePath, + name, + ctime: stats.birthtimeMs, + size: stats.size, + checksum + }); + } + } + } +} + +function sortFiles(files: MapEntry[], outPath: string) { + files.sort((a, b) => a.name.localeCompare(b.name)); + fs.mkdirSync(outPath, { recursive: true }); + + const processed = new Set(); + for (const map of files) { + if (processed.has(map.name)) { + continue; + } + + // only run once on this name + processed.add(map.name); + + // get all of the map entries that match this one + let revisions = files.filter(x => x.name === map.name); + + // order by date + revisions.sort((a, b) => a.ctime - b.ctime); + + // remove duplicates + revisions = revisions.filter((value, index, self) => + index === self.findIndex((t) => ( + t.name === value.name && t.checksum === value.checksum + )) + ); + + // copy to dump folder + if (revisions.length <= 1) { + for (const revision of revisions) { + fs.copyFileSync(revision.filePath, path.join(outPath, revision.name)); + fs.utimesSync(path.join(outPath, revision.name), revision.ctime / 1000, revision.ctime / 1000); + } + } else { + for (let i = 0; i < revisions.length; i++) { + const revision = revisions[i]; + + if (i === revisions.length - 1) { + fs.copyFileSync(revision.filePath, path.join(outPath, revision.name)); + fs.utimesSync(path.join(outPath, revision.name), revision.ctime / 1000, revision.ctime / 1000); + continue; + } + + const outFolder = path.join(outPath, 'v' + (i + 1)); + if (!fs.existsSync(outFolder)) { + fs.mkdirSync(outFolder, { recursive: true }); + } + + fs.copyFileSync(revision.filePath, path.join(outFolder, revision.name)); + fs.utimesSync(path.join(outFolder, revision.name), revision.ctime / 1000, revision.ctime / 1000); + } + } + } +} + +sortFiles(allFiles, path.join('dump', 'maps')); +// sortFiles(betaFiles, path.join('dump', 'maps', 'beta')); diff --git a/src/lostcity/tools/cache/pack.ts b/src/lostcity/scripts/cache/pack.ts similarity index 84% rename from src/lostcity/tools/cache/pack.ts rename to src/lostcity/scripts/cache/pack.ts index eb3a6978a4..d468b22205 100644 --- a/src/lostcity/tools/cache/pack.ts +++ b/src/lostcity/scripts/cache/pack.ts @@ -1,4 +1,4 @@ -import { packClient, packServer } from '#lostcity/cache/packall.js'; +import { packClient, packServer } from '#lostcity/pack/packall.js'; import Environment from '#lostcity/util/Environment.js'; import { updateCompiler } from '#lostcity/util/RuneScriptCompiler.js'; diff --git a/src/lostcity/tools/common/hsl.ts b/src/lostcity/scripts/common/hsl.ts similarity index 100% rename from src/lostcity/tools/common/hsl.ts rename to src/lostcity/scripts/common/hsl.ts diff --git a/src/lostcity/tools/map/ImportNpcCsv.ts b/src/lostcity/scripts/map/ImportNpcCsv.ts similarity index 100% rename from src/lostcity/tools/map/ImportNpcCsv.ts rename to src/lostcity/scripts/map/ImportNpcCsv.ts diff --git a/src/lostcity/tools/map/ImportObjCsv.ts b/src/lostcity/scripts/map/ImportObjCsv.ts similarity index 100% rename from src/lostcity/tools/map/ImportObjCsv.ts rename to src/lostcity/scripts/map/ImportObjCsv.ts diff --git a/src/lostcity/tools/server/saves.ts b/src/lostcity/scripts/server/saves.ts similarity index 100% rename from src/lostcity/tools/server/saves.ts rename to src/lostcity/scripts/server/saves.ts diff --git a/src/lostcity/server/ClientSocket.ts b/src/lostcity/server/ClientSocket.ts index 58998e3a1d..d233c1ec2b 100644 --- a/src/lostcity/server/ClientSocket.ts +++ b/src/lostcity/server/ClientSocket.ts @@ -2,8 +2,8 @@ import { randomUUID } from 'crypto'; import { Socket } from 'net'; import { WebSocket } from 'ws'; -import Isaac from '#jagex2/io/Isaac.js'; -import Packet from '#jagex2/io/Packet.js'; +import Isaac from '#jagex/io/Isaac.js'; +import Packet from '#jagex/io/Packet.js'; import { NetworkPlayer } from '#lostcity/entity/NetworkPlayer.js'; diff --git a/src/lostcity/server/CrcTable.ts b/src/lostcity/server/CrcTable.ts index 8909251b18..4462fd9d98 100644 --- a/src/lostcity/server/CrcTable.ts +++ b/src/lostcity/server/CrcTable.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import Environment from '#lostcity/util/Environment.js'; export const CrcBuffer: Packet = new Packet(new Uint8Array(4 * 9)); diff --git a/src/lostcity/server/DevThread.ts b/src/lostcity/server/DevThread.ts index eebe5ef51f..2021058031 100644 --- a/src/lostcity/server/DevThread.ts +++ b/src/lostcity/server/DevThread.ts @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; import { parentPort } from 'worker_threads'; -import { packClient, packServer } from '#lostcity/cache/packall.js'; +import { packClient, packServer } from '#lostcity/pack/packall.js'; // todo: this file queue is so the rebuild/reload process can utilize the additional context let processNextQueue: Set = new Set(); @@ -12,8 +12,6 @@ let processNextTimeout: Timer | null = null; let active = false; async function processChangedFiles() { - console.log('DevThread: Packing cache'); - active = true; // in case another event happens during build we can queue it up for the next change event @@ -50,8 +48,6 @@ async function processChangedFiles() { } function trackFileChange(filename: string) { - console.log('DevThread:', path.basename(filename), 'changed'); - processNextQueue.add(filename); if (active) { diff --git a/src/lostcity/server/FriendServer.ts b/src/lostcity/server/FriendServer.ts index 96bdfdb1db..dd26f1a02d 100644 --- a/src/lostcity/server/FriendServer.ts +++ b/src/lostcity/server/FriendServer.ts @@ -1,7 +1,7 @@ import { WebSocket, WebSocketServer } from 'ws'; import WsSyncReq from '#3rdparty/ws-sync/ws-sync.js'; -import { fromBase37, toBase37 } from '#jagex2/jstring/JString.js'; +import { fromBase37, toBase37 } from '#jagex/jstring/JString.js'; import { FriendServerRepository } from '#lostcity/server/FriendServerRepository.js'; diff --git a/src/lostcity/server/FriendServerRepository.ts b/src/lostcity/server/FriendServerRepository.ts index 5db8b0e7f7..701b078f21 100644 --- a/src/lostcity/server/FriendServerRepository.ts +++ b/src/lostcity/server/FriendServerRepository.ts @@ -1,4 +1,4 @@ -import { fromBase37, toBase37 } from '#jagex2/jstring/JString.js'; +import { fromBase37, toBase37 } from '#jagex/jstring/JString.js'; import { db } from '#lostcity/db/query.js'; import { ChatModePrivate } from '#lostcity/util/ChatModes.js'; diff --git a/src/lostcity/server/LoginClient.ts b/src/lostcity/server/LoginClient.ts index 4796c452e2..c36e2cb9bd 100644 --- a/src/lostcity/server/LoginClient.ts +++ b/src/lostcity/server/LoginClient.ts @@ -1,7 +1,7 @@ import { WebSocket } from 'ws'; import WsSyncReq from '#3rdparty/ws-sync/ws-sync.js'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import Environment from '#lostcity/util/Environment.js'; @@ -85,21 +85,15 @@ export default class LoginClient { await this.connect(); if (!this.ws || !this.wsr || !this.wsr.checkIfWsLive()) { - return -1; + return; } - const message = await this.wsr.fetchSync({ + await this.wsr.fetchSync({ type: 2, world: Environment.NODE_ID, username37: username37.toString(), save: Buffer.from(save).toString('base64') }); - - if (message.error) { - return -1; - } - - return 0; } async reset() { diff --git a/src/lostcity/server/LoginServer.ts b/src/lostcity/server/LoginServer.ts index bb914b645e..53b9a5222e 100644 --- a/src/lostcity/server/LoginServer.ts +++ b/src/lostcity/server/LoginServer.ts @@ -4,7 +4,7 @@ import fsp from 'fs/promises'; import bcrypt from 'bcrypt'; import { WebSocket, WebSocketServer } from 'ws'; -import { fromBase37 } from '#jagex2/jstring/JString.js'; +import { fromBase37 } from '#jagex/jstring/JString.js'; import { db } from '#lostcity/db/query.js'; diff --git a/src/lostcity/server/LoginThread.ts b/src/lostcity/server/LoginThread.ts index b24e2c064c..f73845a3cd 100644 --- a/src/lostcity/server/LoginThread.ts +++ b/src/lostcity/server/LoginThread.ts @@ -3,9 +3,9 @@ import fsp from 'fs/promises'; import forge from 'node-forge'; import { parentPort } from 'worker_threads'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; -import { toBase37, toSafeName } from '#jagex2/jstring/JString.js'; +import { toBase37, toSafeName } from '#jagex/jstring/JString.js'; import LoginClient from '#lostcity/server/LoginClient.js'; import LoginResponse from '#lostcity/server/LoginResponse.js'; @@ -189,7 +189,7 @@ async function handleRequests(parentPort: any, msg: any, priv: forge.pki.rsa.Pri } } else { if (fs.existsSync(`data/players/${safeName}.sav`)) { - save = await fsp.readFile(`data/players/${safeName}.sav`); + save = Uint8Array.from(await fsp.readFile(`data/players/${safeName}.sav`)); } } @@ -206,25 +206,14 @@ async function handleRequests(parentPort: any, msg: any, priv: forge.pki.rsa.Pri break; } case 'logout': { - const { username, save } = msg; + if (!Environment.LOGIN_KEY) { + return; + } - if (Environment.LOGIN_KEY) { - const reply = await login.save(toBase37(username), save); + const { username, save } = msg; - if (reply === 0) { - parentPort.postMessage({ - type: 'logoutreply', - username - }); - } - } else { - parentPort.postMessage({ - type: 'logoutreply', - username - }); - } - break; - } + await login.save(toBase37(username), save); + } break; case 'autosave': { if (!Environment.LOGIN_KEY) { return; diff --git a/src/lostcity/server/NetworkStream.ts b/src/lostcity/server/NetworkStream.ts index 51fc0994cc..ad961cd505 100644 --- a/src/lostcity/server/NetworkStream.ts +++ b/src/lostcity/server/NetworkStream.ts @@ -1,6 +1,6 @@ import net from 'net'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export default class NetworkStream { private queue: Uint8Array[] = []; // queue of data events diff --git a/src/lostcity/server/PreloadedPacks.ts b/src/lostcity/server/PreloadedPacks.ts index 24f38479e0..dfbbb96d25 100644 --- a/src/lostcity/server/PreloadedPacks.ts +++ b/src/lostcity/server/PreloadedPacks.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export const PRELOADED = new Map(); export const PRELOADED_CRC = new Map(); diff --git a/src/lostcity/server/TcpMaintenanceServer.ts b/src/lostcity/server/TcpMaintenanceServer.ts index 6a08fad098..2464511aae 100644 --- a/src/lostcity/server/TcpMaintenanceServer.ts +++ b/src/lostcity/server/TcpMaintenanceServer.ts @@ -1,6 +1,6 @@ import net, { Server } from 'net'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ClientSocket from '#lostcity/server/ClientSocket.js'; @@ -49,7 +49,7 @@ export default class TcpServer { }); }); - this.tcp.listen(Environment.NODE_PORT as number, '0.0.0.0', () => { + this.tcp.listen(Environment.NODE_PORT, '0.0.0.0', () => { }); } } diff --git a/src/lostcity/server/TcpServer.ts b/src/lostcity/server/TcpServer.ts index 5f870d1b4e..5667c8cafa 100644 --- a/src/lostcity/server/TcpServer.ts +++ b/src/lostcity/server/TcpServer.ts @@ -1,6 +1,6 @@ import net, { Server } from 'net'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ClientSocket from '#lostcity/server/ClientSocket.js'; @@ -30,14 +30,14 @@ export default class TcpServer { seed.p4(Math.floor(Math.random() * 0xffffffff)); socket.send(seed.data); - s.on('data', async (data: Buffer) => { + s.on('data', (data: Buffer) => { const packet = new Packet(new Uint8Array(data)); try { if (socket.state === 1) { - await World.readIn(socket, packet); + World.readIn(socket, packet); } else { - await Login.readIn(socket, packet); + Login.readIn(socket, packet); } } catch (err) { socket.close(); @@ -63,7 +63,7 @@ export default class TcpServer { }); }); - this.tcp.listen(Environment.NODE_PORT as number, '0.0.0.0', () => { + this.tcp.listen(Environment.NODE_PORT, '0.0.0.0', () => { }); } } diff --git a/src/lostcity/server/WSMaintenanceServer.ts b/src/lostcity/server/WSMaintenanceServer.ts index 7b8649e97f..9e69a02900 100644 --- a/src/lostcity/server/WSMaintenanceServer.ts +++ b/src/lostcity/server/WSMaintenanceServer.ts @@ -1,7 +1,7 @@ import { WebSocketServer } from 'ws'; import { IncomingMessage } from 'http'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ClientSocket from '#lostcity/server/ClientSocket.js'; diff --git a/src/lostcity/server/WSServer.ts b/src/lostcity/server/WSServer.ts index 402b2b6686..9488cb1676 100644 --- a/src/lostcity/server/WSServer.ts +++ b/src/lostcity/server/WSServer.ts @@ -1,7 +1,7 @@ import { WebSocketServer, WebSocket } from 'ws'; import { IncomingMessage } from 'http'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import Login from '#lostcity/engine/Login.js'; import World from '#lostcity/engine/World.js'; @@ -29,7 +29,7 @@ export default class WSServer { wss: WebSocketServer | null = null; start() { - const port = (Environment.NODE_PORT as number) + 1; + const port = Environment.NODE_PORT + 1; this.wss = new WebSocketServer({ port, host: '0.0.0.0' }, () => { }); @@ -44,14 +44,14 @@ export default class WSServer { seed.p4(Math.floor(Math.random() * 0xffffffff)); socket.send(seed.data); - ws.on('message', async (data: Buffer) => { + ws.on('message', (data: Buffer) => { const packet = new Packet(new Uint8Array(data)); try { if (socket.state === 1) { - await World.readIn(socket, packet); + World.readIn(socket, packet); } else { - await Login.readIn(socket, packet); + Login.readIn(socket, packet); } } catch (err) { socket.close(); diff --git a/src/lostcity/server/WorkerServer.ts b/src/lostcity/server/WorkerServer.ts index f5156f4459..ae3f57537d 100644 --- a/src/lostcity/server/WorkerServer.ts +++ b/src/lostcity/server/WorkerServer.ts @@ -1,4 +1,4 @@ -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; import ClientSocket from '#lostcity/server/ClientSocket.js'; @@ -11,7 +11,7 @@ export default class WorkerServer { constructor() {} start() { - self.onmessage = async (e: MessageEvent) => { + self.onmessage = (e: MessageEvent) => { const packet = new Packet(new Uint8Array(e.data.data)); const socket = this.sockets.get(e.data.id); @@ -30,9 +30,9 @@ export default class WorkerServer { if (socket) { try { if (socket.state === 1) { - await World.readIn(socket, packet); + World.readIn(socket, packet); } else { - await Login.readIn(socket, packet); + Login.readIn(socket, packet); } } catch (err) { console.log('error', err); diff --git a/src/lostcity/tools/cache/dump-store.ts b/src/lostcity/tools/cache/dump-store.ts deleted file mode 100644 index b3dbc90a9a..0000000000 --- a/src/lostcity/tools/cache/dump-store.ts +++ /dev/null @@ -1,38 +0,0 @@ -import fs from 'fs'; -import zlib from 'zlib'; - -import FileStream from '#jagex2/io/FileStream.js'; - -const args = process.argv.slice(2); -if (args.length < 2) { - throw new Error('Usage: node dump-store.js '); -} - -const inputDir = args[0]; -const outputDir = args[1]; - -const names = [['', 'title', 'config', 'interface', 'media', 'versionlist', 'textures', 'wordenc', 'sounds'], [], [], [], []]; -const extensions = ['jag', 'dat', 'dat', 'mid', 'dat']; - -const store = new FileStream(inputDir); -for (let index = 0; index <= 4; index++) { - fs.mkdirSync(`${outputDir}/${index}`, { recursive: true }); - - const count = store.count(index); - for (let file = 0; file < count; file++) { - let data = store.read(index, file); - if (!data) { - continue; - } - - const name = names[index][file]; - - if (index > 0) { - const version = (((data[data.length - 2] << 8) | data[data.length - 1]) >>> 0) - 1; - data = zlib.gunzipSync(data); - fs.writeFileSync(`${outputDir}/${index}/${name?.length > 0 ? name.replaceAll(' ', '_') : file}.${version}.${extensions[index]}`, data); - } else { - fs.writeFileSync(`${outputDir}/${index}/${name?.length > 0 ? name.replaceAll(' ', '_') : file}.${extensions[index]}`, data); - } - } -} diff --git a/src/lostcity/tools/cache/jagList.ts b/src/lostcity/tools/cache/jagList.ts deleted file mode 100644 index 7af7af9249..0000000000 --- a/src/lostcity/tools/cache/jagList.ts +++ /dev/null @@ -1,24 +0,0 @@ -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; - -const args = process.argv.slice(2); - -if (args.length < 1) { - console.log('Usage: ts-loader jagList.ts '); - process.exit(1); -} - -const jag = Jagfile.load(args[0]); - -for (let i = 0; i < jag.fileCount; i++) { - const name = jag.fileName[i] ?? jag.fileHash[i]; - - const data = jag.get(i); - if (data === null) { - console.log('Failed to read', name); - continue; - } - - const checksum = Packet.getcrc(data.data, 0, data.data.length); - console.log(name, checksum); -} diff --git a/src/lostcity/tools/cache/organizeMaps.ts b/src/lostcity/tools/cache/organizeMaps.ts deleted file mode 100644 index adb83ea9d1..0000000000 --- a/src/lostcity/tools/cache/organizeMaps.ts +++ /dev/null @@ -1,118 +0,0 @@ -import Packet from '#jagex2/io/Packet.js'; -import { fromBase37 } from '#jagex2/jstring/JString.js'; -import fs from 'fs'; -import path from 'path'; - -const args = process.argv.splice(2); - -if (!args.length) { - process.exit(1); -} - -const searchDir = args[0]; -const outDir = path.join('dump', 'maps'); - -if (!fs.existsSync(outDir)) { - fs.mkdirSync(outDir, { recursive: true }); -} - -class MapEntry { - constructor(readonly filePath: string, readonly name: string, readonly ctime: number, readonly size: number, readonly checksum: number) { - } -} - -const dirs = fs.readdirSync(searchDir); -const allFiles: MapEntry[] = []; - -for (const dir of dirs) { - const files = fs.readdirSync(path.join(searchDir, dir)); - - for (const file of files) { - const name = fromBase37(BigInt(file)); - - if (name === 'invalid_name') { - // console.log('unknown file:', file); - continue; - } - - const filePath = path.join(searchDir, dir, file); - - if (name.match(/[lm]\d+_\d+/)) { - // lX_Z and mX_Z maps - const stats = fs.statSync(filePath); - const data = Packet.load(filePath); - - // users might have uploaded corrupted files - let bad = false; - for (let i = 0; i < 8; i++) { - // "bad_ntfs_decompr" - 6261645F6E7466735F6465636F6D7072 - const sig = data.g4(); - data.pos -= 3; - if (sig === 0x5F6E7466) { - // "_ntf" spotted in the first 12 bytes - bad = true; - } else if (sig === 0x08080808) { - // repeating 08 spotted - bad = true; - } - } - if (bad) { - continue; - } - - const checksum = Packet.getcrc(data.data, 0, data.length); - allFiles.push(new MapEntry(filePath, name, stats.birthtimeMs, stats.size, checksum)); - } - } -} - -allFiles.sort((a, b) => a.name.localeCompare(b.name)); -const processed = new Set(); - -for (const map of allFiles) { - if (processed.has(map.name)) { - continue; - } - - // only run once on this name - processed.add(map.name); - - // get all of the map entries that match this one - let revisions = allFiles.filter(x => x.name === map.name); - - // order by date - revisions.sort((a, b) => a.ctime - b.ctime); - - // remove duplicates - revisions = revisions.filter((value, index, self) => - index === self.findIndex((t) => ( - t.name === value.name && t.checksum === value.checksum - )) - ); - - // copy to dump folder - if (revisions.length <= 1) { - for (const revision of revisions) { - fs.copyFileSync(revision.filePath, path.join('dump', 'maps', revision.name)); - fs.utimesSync(path.join(outDir, revision.name), revision.ctime / 1000, revision.ctime / 1000); - } - } else { - for (let i = 0; i < revisions.length; i++) { - const revision = revisions[i]; - - if (i === revisions.length - 1) { - fs.copyFileSync(revision.filePath, path.join('dump', 'maps', revision.name)); - fs.utimesSync(path.join(outDir, revision.name), revision.ctime / 1000, revision.ctime / 1000); - continue; - } - - const outFolder = path.join('dump', 'maps', 'v' + (i + 1)); - if (!fs.existsSync(outFolder)) { - fs.mkdirSync(outFolder); - } - - fs.copyFileSync(revision.filePath, path.join(outFolder, revision.name)); - fs.utimesSync(path.join(outFolder, revision.name), revision.ctime / 1000, revision.ctime / 1000); - } - } -} diff --git a/src/lostcity/tools/cache/pack-store.ts b/src/lostcity/tools/cache/pack-store.ts deleted file mode 100644 index c8f9f5a7c2..0000000000 --- a/src/lostcity/tools/cache/pack-store.ts +++ /dev/null @@ -1,25 +0,0 @@ -import fs from 'fs'; - -import FileStream from '#jagex2/io/FileStream.js'; - -const args = process.argv.slice(2); -if (args.length < 2) { - throw new Error('Usage: node pack-store.js '); -} - -const inputDir = args[0]; -const outputDir = args[1]; - -const store = new FileStream(outputDir, true); - -for (let i = 0; i <= 4; i++) { - const files = fs.readdirSync(`${inputDir}/` + i); - files.sort((a, b) => parseInt(a) - parseInt(b)); - - for (let j = 0; j < files.length; j++) { - const file = files[j]; - const data = fs.readFileSync(`${inputDir}/` + i + '/' + file); - - store.write(i, parseInt(file), data); - } -} diff --git a/src/lostcity/tools/cache/unpack.ts b/src/lostcity/tools/cache/unpack.ts deleted file mode 100644 index abf6337f80..0000000000 --- a/src/lostcity/tools/cache/unpack.ts +++ /dev/null @@ -1,137 +0,0 @@ -import fs from 'fs'; -import zlib from 'zlib'; - -import FileStream from '#jagex2/io/FileStream.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; - -import { - decodeFlo, decodeIdk, decodeLoc, decodeNpc, - decodeObj, decodeSeq, decodeSpotAnim, decodeVarbit, decodeVarp, - readJag, unpackConfig, unpackMedia, unpackTextures, unpackTitle, - unpackWordenc -} from '#lostcity/util/CacheUnpack.js'; -// import Packet from '#jagex2/io/Packet.js'; -import AnimFrame from '#lostcity/cache/graphics/AnimFrame.js'; -// import AnimBase from '#lostcity/cache/graphics/AnimBase.js'; - -let title: Jagfile | null = null; -let config: Jagfile | null = null; -// let interfaces: Jagfile | null = null; -let media: Jagfile | null = null; -let textures: Jagfile | null = null; -let wordenc: Jagfile | null = null; -let sounds: Jagfile | null = null; - -if (fs.existsSync('dump/main_file_cache.dat')) { - const cache = new FileStream('dump'); - - title = readJag(cache, 1); - config = readJag(cache, 2); - // interfaces = readJag(cache, 3); // todo - media = readJag(cache, 4); - textures = readJag(cache, 6); - wordenc = readJag(cache, 7); - sounds = readJag(cache, 8); // todo - - // const versionlist = readJag(cache, 5); // todo - - if (!fs.existsSync('data/src/pack')) { - fs.mkdirSync('data/src/pack', { recursive: true }); - } - - if (!fs.existsSync('data/src/models/_unpack')) { - fs.mkdirSync('data/src/models/_unpack', { recursive: true }); - } - - fs.writeFileSync('data/src/pack/model.pack', ''); - const modelCount = 0; // cache.count(1); - for (let i = 0; i < modelCount; i++) { - fs.appendFileSync('data/src/pack/model.pack', `${i}=model_${i}\n`); - - if (fs.existsSync('data/src/models/_unpack/model_' + i + '.ob2')) { - continue; - } - - const data = cache.read(1, i); - if (!data) { - continue; - } - - const decompressed = zlib.gunzipSync(data); - fs.writeFileSync('data/src/models/_unpack/model_' + i + '.ob2', decompressed); - } - - if (!fs.existsSync('data/src/models/_unpack/base')) { - fs.mkdirSync('data/src/models/_unpack/base', { recursive: true }); - } - - if (!fs.existsSync('data/src/models/_unpack/frame')) { - fs.mkdirSync('data/src/models/_unpack/frame', { recursive: true }); - } - - const animCount = cache.count(2); - for (let i = 0; i < animCount; i++) { - const compressed = cache.read(2, i); - if (!compressed) { - continue; - } - - const src = new Uint8Array(zlib.gunzipSync(compressed)); - AnimFrame.unpack377(src); - } - - // todo: save frames/bases to files - - if (!fs.existsSync('data/src/songs')) { - fs.mkdirSync('data/src/songs', { recursive: true }); - } - - const midiCount = 0; // cache.count(3); - for (let i = 0; i < midiCount; i++) { - const data = cache.read(3, i); - if (!data) { - continue; - } - - const decompressed = zlib.gunzipSync(data); - fs.writeFileSync('data/src/songs/' + i + '.mid', decompressed); - } - - // we need versionlist working to be able to dump maps - const mapCount = cache.count(4); - for (let i = 0; i < mapCount; i++) { - // todo - } -} else { - title = Jagfile.load('dump/title'); - config = Jagfile.load('dump/config'); - // interfaces = Jagfile.load('dump/interface'); - media = Jagfile.load('dump/media'); - textures = Jagfile.load('dump/textures'); - wordenc = Jagfile.load('dump/wordenc'); - sounds = Jagfile.load('dump/sounds'); // not in 194 - - const models = Jagfile.load('dump/models'); - // todo: save to files -} - -unpackTitle(title); -unpackMedia(media); -unpackTextures(textures); -unpackWordenc(wordenc); - -unpackConfig(config, 'loc', decodeLoc); -unpackConfig(config, 'npc', decodeNpc); -unpackConfig(config, 'obj', decodeObj); -unpackConfig(config, 'seq', decodeSeq); -unpackConfig(config, 'varp', decodeVarp); -unpackConfig(config, 'spotanim', decodeSpotAnim); -unpackConfig(config, 'idk', decodeIdk); -unpackConfig(config, 'flo', decodeFlo); -unpackConfig(config, 'varbit', decodeVarbit); - -// server-side: -// unpackConfig(config, 'mesanim', decodeNoOp); -// unpackConfig(config, 'mes', decodeNoOp); -// unpackConfig(config, 'param', decodeNoOp); -// unpackConfig(config, 'hunt', decodeNoOp); diff --git a/src/lostcity/tools/packet/npcInfo.ts b/src/lostcity/tools/packet/npcInfo.ts deleted file mode 100644 index 0b9d764420..0000000000 --- a/src/lostcity/tools/packet/npcInfo.ts +++ /dev/null @@ -1,154 +0,0 @@ -import fs from 'fs'; - -import Packet from '#jagex2/io/Packet.js'; - -const npcIds: number[] = []; -let npcCount = 0; - -const entityRemovalIds: number[] = []; -let entityRemovalCount = 0; - -const entityUpdateIds: number[] = []; -let entityUpdateCount = 0; - -fs.readdirSync('dump') - .sort((a, b) => parseInt(a.slice(0, a.length - '.npc.bin'.length)) - parseInt(b.slice(0, b.length - '.npc.bin'.length))) - .filter(f => f.endsWith('.npc.bin')) - .forEach(f => { - const buf = Packet.load(`dump/${f}`); - console.log('----'); - console.log(f); - - entityRemovalCount = 0; - entityUpdateCount = 0; - - // readNpcs - buf.bits(); - - const total = buf.gBit(8); - if (total < npcCount) { - for (let i = total; i < npcCount; i++) { - entityRemovalIds[entityRemovalCount++] = npcIds[i]; - } - } - - if (total > npcCount) { - console.error('Too many npcs', total, npcCount); - process.exit(1); - } - - npcCount = 0; - for (let i = 0; i < total; i++) { - const id = npcIds[i]; - const update = buf.gBit(1); - - if (update === 0) { - console.log('refresh', id); - npcIds[npcCount++] = id; - } else if (update === 1) { - const type = buf.gBit(2); - - if (type === 0) { - npcIds[npcCount++] = id; - console.log('refresh + mask', id); - entityUpdateIds[entityUpdateCount++] = id; - } else if (type === 1) { - npcIds[npcCount++] = id; - const walkDir = buf.gBit(3); - const maskUpdate = buf.gBit(1); - console.log('refresh + walk', id, walkDir, maskUpdate); - - if (maskUpdate === 1) { - entityUpdateIds[entityUpdateCount++] = id; - } - } else if (type === 2) { - npcIds[npcCount++] = id; - const runDir = buf.gBit(3); - const walkDir = buf.gBit(3); - const maskUpdate = buf.gBit(1); - console.log('refresh + run', id, runDir, walkDir, maskUpdate); - - if (maskUpdate === 1) { - entityUpdateIds[entityUpdateCount++] = id; - } - } else if (type === 3) { - console.log('remove', id); - entityRemovalIds[entityRemovalCount++] = id; - } - } - } - - // readNewNpcs - while (buf.bitPos + 21 < buf.data.length * 8) { - const id = buf.gBit(13); - if (id === 8191) { - break; - } - - npcIds[npcCount++] = id; - const type = buf.gBit(11); - const x = buf.gBit(5); - const z = buf.gBit(5); - const maskUpdate = buf.gBit(1); - console.log('add', id, type, x, z, maskUpdate); - - if (maskUpdate === 1) { - entityUpdateIds[entityUpdateCount++] = id; - } - } - - buf.bytes(); - - // readNpcUpdates - for (let i = 0; i < entityUpdateCount; i++) { - const id = entityUpdateIds[i]; - const mask = buf.g1(); - console.log('mask', id, mask.toString(16)); - - if ((mask & 0x2) === 0x2) { - const animId = buf.g2(); - const animDelay = buf.g1(); - } - - if ((mask & 0x4) === 0x4) { - const faceEntity = buf.g2(); - } - - if ((mask & 0x8) === 0x8) { - const say = buf.gjstr(); - } - - if ((mask & 0x10) === 0x10) { - const hitDamage = buf.g2(); - const hitType = buf.g1(); - const health = buf.g1(); - const maxHealth = buf.g2(); - } - - if ((mask & 0x20) === 0x20) { - const newType = buf.g2(); - } - - if ((mask & 0x40) === 0x40) { - const graphicId = buf.g2(); - const graphicHeight = buf.g2(); - const graphicDelay = buf.g1(); - } - - if ((mask & 0x80) === 0x80) { - const faceX = buf.g2(); - const faceZ = buf.g2(); - } - } - - for (let i = 0; i < entityRemovalCount; i++) { - const id = entityRemovalIds[i]; - } - - if (buf.pos !== buf.data.length) { - console.error('size mismatch in getnpc', buf.pos, buf.data.length); - process.exit(1); - } - - console.log(npcCount, 'npcs'); - }); diff --git a/src/lostcity/tools/packet/playerInfo.ts b/src/lostcity/tools/packet/playerInfo.ts deleted file mode 100644 index 3d320e94c2..0000000000 --- a/src/lostcity/tools/packet/playerInfo.ts +++ /dev/null @@ -1,308 +0,0 @@ -import fs from 'fs'; - -import Packet from '#jagex2/io/Packet.js'; -import { fromBase37 } from '#jagex2/jstring/JString.js'; - -const playerIds: number[] = []; -let playerCount = 0; - -const entityRemovalIds: number[] = []; -let entityRemovalCount = 0; - -const entityUpdateIds: number[] = []; -let entityUpdateCount = 0; - -const files = fs.readdirSync('dump'); -const players = new Map(); -for (let i = 0; i < files.length; i++) { - const file = files[i]; - - if (file.endsWith('.player.bin')) { - const parts = file.split('.'); - const tick = parseInt(parts[0]); - const username = parts[1]; - - if (!players.has(username)) { - players.set(username, []); - } - - players.get(username)!.push(tick); - } -} - -for (const [username, ticks] of players) { - // if (username !== 'pazaz') { - // continue; - // } - - ticks.sort((a, b) => a - b); - - for (let i = 0; i < ticks.length; i++) { - console.log('----'); - console.log(username, 'tick', ticks[i]); - const buf = Packet.load(`dump/${ticks[i]}.${username}.player.bin`); - - entityRemovalCount = 0; - entityUpdateCount = 0; - - // readLocalPlayer - buf.bits(); - - const update = buf.gBit(1); - - if (update === 1) { - const type = buf.gBit(2); - - if (type === 0) { - console.log('local mask'); - entityUpdateIds[entityUpdateCount++] = 0; - } else if (type === 1) { - const walkDir = buf.gBit(3); - const maskUpdate = buf.gBit(1); - console.log('local walk', walkDir, maskUpdate); - - if (maskUpdate === 1) { - entityUpdateIds[entityUpdateCount++] = 0; - } - } else if (type === 2) { - const runDir = buf.gBit(3); - const walkDir = buf.gBit(3); - const maskUpdate = buf.gBit(1); - console.log('local run', runDir, walkDir, maskUpdate); - - if (maskUpdate === 1) { - entityUpdateIds[entityUpdateCount++] = 0; - } - } else if (type === 3) { - const level = buf.gBit(2); - const x = buf.gBit(7); - const z = buf.gBit(7); - const jump = buf.gBit(1); - const maskUpdate = buf.gBit(1); - console.log('local teleport', level, x, z, jump, maskUpdate); - - if (maskUpdate === 1) { - entityUpdateIds[entityUpdateCount++] = 0; - } - } - } - - // readPlayers - const total = buf.gBit(8); - if (total < playerCount) { - for (let i = total; i < playerCount; i++) { - entityRemovalIds[entityRemovalCount++] = playerIds[i]; - } - } - - if (total > playerCount) { - console.error('Too many players', total, playerCount); - process.exit(1); - } - - playerCount = 0; - for (let i = 0; i < total; i++) { - const id = playerIds[i]; - const update = buf.gBit(1) ? true : false; - - if (!update) { - console.log('refresh', id); - playerIds[playerCount++] = id; - } else { - const type = buf.gBit(2); - - if (type === 0) { - playerIds[playerCount++] = id; - console.log('refresh + mask', id); - entityUpdateIds[entityUpdateCount++] = id; - } else if (type === 1) { - playerIds[playerCount++] = id; - const walkDir = buf.gBit(3); - const maskUpdate = buf.gBit(1) ? true : false; - console.log('refresh + walk', id, walkDir, maskUpdate); - - if (maskUpdate) { - entityUpdateIds[entityUpdateCount++] = id; - } - } else if (type === 2) { - playerIds[playerCount++] = id; - const runDir = buf.gBit(3); - const walkDir = buf.gBit(3); - const maskUpdate = buf.gBit(1) ? true : false; - console.log('refresh + run', id, runDir, walkDir, maskUpdate); - - if (maskUpdate) { - entityUpdateIds[entityUpdateCount++] = id; - } - } else if (type === 3) { - console.log('remove', id); - entityRemovalIds[entityRemovalCount++] = id; - } - } - } - - // readNewPlayers - while (buf.bitPos + 10 < buf.data.length * 8) { - const id = buf.gBit(11); - if (id === 2047) { - break; - } - - playerIds[playerCount++] = id; - let x = buf.gBit(5); - if (x > 15) { - x -= 32; - } - let z = buf.gBit(5); - if (z > 15) { - z -= 32; - } - const jump = buf.gBit(1) ? true : false; - const maskUpdate = buf.gBit(1) ? true : false; - console.log('add', id, x, z, jump, maskUpdate); - - if (maskUpdate) { - entityUpdateIds[entityUpdateCount++] = id; - } - } - - buf.bytes(); - - // readPlayerUpdates - for (let i = 0; i < entityUpdateCount; i++) { - const id = entityUpdateIds[i]; - - if (!buf.available) { - console.error('not enough data in getplayer', id, entityUpdateCount, i); - process.exit(1); - } - - let mask = buf.g1(); - if ((mask & 0x80) === 0x80) { - mask += buf.g1() << 8; - } - - console.log('mask', id, mask.toString(16)); - - if ((mask & 0x1) === 0x1) { - const length = buf.g1(); - const gender = buf.g1(); - const headicons = buf.g1(); - - for (let i = 0; i < 12; i++) { - let type = buf.g1(); - - if (type === 0) { - // - } else { - type = (type << 8) + buf.g1(); - } - } - - for (let i = 0; i < 5; i++) { - const color = buf.g1(); - } - - let basReadyAnim = buf.g2(); - if (basReadyAnim === 65535) { - basReadyAnim = -1; - } - - let basTurnOnSpot = buf.g2(); - if (basTurnOnSpot === 65535) { - basTurnOnSpot = -1; - } - - let basWalkForward = buf.g2(); - if (basWalkForward === 65535) { - basWalkForward = -1; - } - - let basWalkBackward = buf.g2(); - if (basWalkBackward === 65535) { - basWalkBackward = -1; - } - - let basWalkLeft = buf.g2(); - if (basWalkLeft === 65535) { - basWalkLeft = -1; - } - - let basWalkRight = buf.g2(); - if (basWalkRight === 65535) { - basWalkRight = -1; - } - - let basRunning = buf.g2(); - if (basRunning === 65535) { - basRunning = -1; - } - - const name = fromBase37(buf.g8()); - const combatLevel = buf.g1(); - } - - if ((mask & 0x2) === 0x2) { - const animId = buf.g2(); - const animDelay = buf.g1(); - } - - if ((mask & 0x4) === 0x4) { - const faceEntity = buf.g2(); - } - - if ((mask & 0x8) === 0x8) { - const chat = buf.gjstr(); - } - - if ((mask & 0x10) === 0x10) { - const hitDamage = buf.g2(); - const hitType = buf.g1(); - const health = buf.g1(); - const maxHealth = buf.g2(); - } - - if ((mask & 0x20) === 0x20) { - const faceX = buf.g2(); - const faceZ = buf.g2(); - } - - if ((mask & 0x40) === 0x40) { - const messageColor = buf.g1(); - const messageEffect = buf.g1(); - const messageType = buf.g1(); - - const length = buf.g1(); - const message = new Uint8Array(length); - buf.gdata(message, 0, message.length); - } - - if ((mask & 0x100) === 0x100) { - const graphicId = buf.g2(); - const graphicHeight = buf.g2(); - const graphicDelay = buf.g2(); - } - - if ((mask & 0x200) === 0x200) { - const exactStartX = buf.g1(); - const exactStartZ = buf.g1(); - const exactEndX = buf.g1(); - const exactEndZ = buf.g1(); - const exactMoveStart = buf.g2(); - const exactMoveEnd = buf.g2(); - const exactMoveDirection = buf.g1(); - } - } - - for (let i = 0; i < entityRemovalCount; i++) { - const id = entityRemovalIds[i]; - } - - if (buf.pos !== buf.data.length) { - console.error('size mismatch in getplayer', buf.pos, buf.data.length); - process.exit(1); - } - - console.log(playerCount, 'players'); - } -} diff --git a/src/lostcity/util/CacheUnpack.ts b/src/lostcity/util/CacheUnpack.ts deleted file mode 100644 index c7a9f5036f..0000000000 --- a/src/lostcity/util/CacheUnpack.ts +++ /dev/null @@ -1,1209 +0,0 @@ -import fs from 'fs'; -import Jimp from 'jimp'; - -import FileStream from '#jagex2/io/FileStream.js'; -import Jagfile from '#jagex2/io/Jagfile.js'; -import Packet from '#jagex2/io/Packet.js'; - -import { countPix, pixSize, unpackPix } from '#lostcity/util/PixUnpack.js'; -import { printError, printInfo } from './Logger.js'; - -export function readJag(cache: FileStream, id: number): Jagfile | null { - const raw = cache.read(0, id); - if (!raw) { - return null; - } - - return new Jagfile(new Packet(raw)); -} - -function unpackImage(dat: Packet | null, idx: Packet | null, id: number = 0) { - if (!dat || !idx) { - return; - } - - return unpackPix(dat, idx, id); -} - -function saveImage(img: Jimp | undefined, file: string) { - if (!img || !file) { - return; - } - - img.write(file + '.png'); -} - -function unpackAndSaveImage(jag: Jagfile, idx: Packet | null, file: string, outDir: string) { - if (!idx) { - return; - } - - const dat = jag.read(file + '.dat'); - if (!dat) { - return; - } - - const unpacked = unpackImage(dat, idx); - if (unpacked) { - saveImage(unpacked.img, 'data/src/' + outDir + '/' + file); - - // ---- - - if (!fs.existsSync('data/src/' + outDir + '/meta')) { - fs.mkdirSync('data/src/' + outDir + '/meta', { recursive: true }); - } - - const meta = `${unpacked.cropX},${unpacked.cropY},${unpacked.width},${unpacked.height},${unpacked.pixelOrder ? 'row' : 'column'}\n`; - fs.writeFileSync('data/src/' + outDir + '/meta/' + file + '.opt', meta); - - // ---- - - const pal = new Jimp(16, 16, 0xff00ffff).colorType(2); - - for (let j = 1; j < unpacked.palette.length; j++) { - const x = j % 16; - const y = Math.floor(j / 16); - - const color = unpacked.palette[j]; - - const pos = (x + y * 16) * 4; - pal.bitmap.data[pos] = (color >> 16) & 0xff; - pal.bitmap.data[pos + 1] = (color >> 8) & 0xff; - pal.bitmap.data[pos + 2] = color & 0xff; - } - - saveImage(pal, 'data/src/' + outDir + '/meta/' + file + '.pal'); - } -} - -function unpackAndSaveSheet(jag: Jagfile, idx: Packet | null, file: string, outDir: string) { - if (!idx) { - return; - } - - const dat = jag.read(file + '.dat'); - if (!dat) { - return; - } - - const size = pixSize(dat, idx); - const count = countPix(dat, idx); - - const sprites = []; - for (let i = 0; i < count; i++) { - sprites[i] = unpackPix(dat, idx, i); - } - - let width = Math.ceil(Math.sqrt(count)); - let height = Math.ceil(count / width); - - if (width * height > count) { - let widthTries = 0; - - // wrong aspect ratio, try subtracting from width and adding to height - while (width * height > count && widthTries < 10) { - width--; - height++; - widthTries++; - } - } - - const sheet = new Jimp(width * size.width, height * size.height, 0xff00ffff).colorType(2); - - for (let j = 0; j < count; j++) { - const x = j % width; - const y = Math.floor(j / width); - - sheet.blit(sprites[j].img, x * size.width, y * size.height, 0, 0, size.width, size.height); - } - - saveImage(sheet, 'data/src/' + outDir + '/' + file); - - // ---- - - if (!fs.existsSync('data/src/' + outDir + '/meta')) { - fs.mkdirSync('data/src/' + outDir + '/meta', { recursive: true }); - } - - let meta = `${size.width}x${size.height}\n`; - - for (let j = 0; j < count; j++) { - const sprite = sprites[j]; - meta += `${sprite.cropX},${sprite.cropY},${sprite.width},${sprite.height},${sprite.pixelOrder ? 'row' : 'column'}\n`; - } - - fs.writeFileSync('data/src/' + outDir + '/meta/' + file + '.opt', meta); - - // ---- - - const pal = new Jimp(16, 16, 0xff00ffff).colorType(2); - - for (let j = 1; j < sprites[0].palette.length; j++) { - const x = j % 16; - const y = Math.floor(j / 16); - - const color = sprites[0].palette[j]; - - const pos = (x + y * 16) * 4; - pal.bitmap.data[pos] = (color >> 16) & 0xff; - pal.bitmap.data[pos + 1] = (color >> 8) & 0xff; - pal.bitmap.data[pos + 2] = color & 0xff; - } - - saveImage(pal, 'data/src/' + outDir + '/meta/' + file + '.pal'); -} - -export function unpackAndSave(jag: Jagfile, idx: Packet | null, file: string, outDir: string) { - if (!idx) { - return; - } - - const dat = jag.read(file + '.dat'); - if (!dat) { - return; - } - - const count = countPix(dat, idx); - if (count === 1) { - unpackAndSaveImage(jag, idx, file, outDir); - } else { - unpackAndSaveSheet(jag, idx, file, outDir); - } -} - -export function unpackTitle(title: Jagfile | null) { - if (!title) { - return; - } - - const titleJpg = title.read('title.dat'); - if (titleJpg) { - titleJpg.save('data/src/binary/title.jpg', titleJpg.length); - } - - const index = title.read('index.dat'); - - unpackAndSave(title, index, 'logo', 'title'); - unpackAndSave(title, index, 'titlebox', 'title'); - unpackAndSave(title, index, 'titlebutton', 'title'); - unpackAndSave(title, index, 'runes', 'title'); - unpackAndSave(title, index, 'p11', 'fonts'); - unpackAndSave(title, index, 'p12', 'fonts'); - unpackAndSave(title, index, 'b12', 'fonts'); - unpackAndSave(title, index, 'q8', 'fonts'); - unpackAndSave(title, index, 'p11_full', 'fonts'); - unpackAndSave(title, index, 'p12_full', 'fonts'); - unpackAndSave(title, index, 'b12_full', 'fonts'); - unpackAndSave(title, index, 'q8_full', 'fonts'); -} - -export function unpackMedia(media: Jagfile | null) { - if (!media) { - return; - } - - const index = media.read('index.dat'); - - unpackAndSave(media, index, 'backbase1', 'sprites'); - unpackAndSave(media, index, 'backbase2', 'sprites'); - unpackAndSave(media, index, 'backhmid1', 'sprites'); - unpackAndSave(media, index, 'backhmid2', 'sprites'); - unpackAndSave(media, index, 'backleft1', 'sprites'); - unpackAndSave(media, index, 'backleft2', 'sprites'); - unpackAndSave(media, index, 'backright1', 'sprites'); - unpackAndSave(media, index, 'backright2', 'sprites'); - unpackAndSave(media, index, 'backtop1', 'sprites'); - unpackAndSave(media, index, 'backtop2', 'sprites'); - unpackAndSave(media, index, 'backvmid1', 'sprites'); - unpackAndSave(media, index, 'backvmid2', 'sprites'); - unpackAndSave(media, index, 'backvmid3', 'sprites'); - unpackAndSave(media, index, 'mapback', 'sprites'); - unpackAndSave(media, index, 'chatback', 'sprites'); - unpackAndSave(media, index, 'invback', 'sprites'); - unpackAndSave(media, index, 'magicon', 'sprites'); - unpackAndSave(media, index, 'magicoff', 'sprites'); - unpackAndSave(media, index, 'prayeron', 'sprites'); - unpackAndSave(media, index, 'prayeroff', 'sprites'); - unpackAndSave(media, index, 'prayerglow', 'sprites'); - unpackAndSave(media, index, 'wornicons', 'sprites'); - unpackAndSave(media, index, 'sideicons', 'sprites'); - unpackAndSave(media, index, 'compass', 'sprites'); - unpackAndSave(media, index, 'miscgraphics', 'sprites'); - unpackAndSave(media, index, 'miscgraphics2', 'sprites'); - unpackAndSave(media, index, 'miscgraphics3', 'sprites'); - unpackAndSave(media, index, 'staticons', 'sprites'); - unpackAndSave(media, index, 'staticons2', 'sprites'); - unpackAndSave(media, index, 'combaticons', 'sprites'); - unpackAndSave(media, index, 'combaticons2', 'sprites'); - unpackAndSave(media, index, 'combaticons3', 'sprites'); - unpackAndSave(media, index, 'combatboxes', 'sprites'); - unpackAndSave(media, index, 'tradebacking', 'sprites'); - unpackAndSave(media, index, 'hitmarks', 'sprites'); - unpackAndSave(media, index, 'cross', 'sprites'); - unpackAndSave(media, index, 'mapdots', 'sprites'); - unpackAndSave(media, index, 'sworddecor', 'sprites'); - unpackAndSave(media, index, 'redstone1', 'sprites'); - unpackAndSave(media, index, 'redstone2', 'sprites'); - unpackAndSave(media, index, 'redstone3', 'sprites'); - unpackAndSave(media, index, 'leftarrow', 'sprites'); - unpackAndSave(media, index, 'rightarrow', 'sprites'); - unpackAndSave(media, index, 'steelborder', 'sprites'); - unpackAndSave(media, index, 'steelborder2', 'sprites'); - unpackAndSave(media, index, 'scrollbar', 'sprites'); - unpackAndSave(media, index, 'mapscene', 'sprites'); - unpackAndSave(media, index, 'mapfunction', 'sprites'); - unpackAndSave(media, index, 'magicon2', 'sprites'); - unpackAndSave(media, index, 'magicoff2', 'sprites'); - unpackAndSave(media, index, 'gnomeball_buttons', 'sprites'); - unpackAndSave(media, index, 'mapflag', 'sprites'); - unpackAndSave(media, index, 'mapmarker', 'sprites'); - unpackAndSave(media, index, 'mod_icons', 'sprites'); - unpackAndSave(media, index, 'mapedge', 'sprites'); - unpackAndSave(media, index, 'leftarrow_small', 'sprites'); - unpackAndSave(media, index, 'rightarrow_small', 'sprites'); - unpackAndSave(media, index, 'blackmark', 'sprites'); - unpackAndSave(media, index, 'button_brown', 'sprites'); - unpackAndSave(media, index, 'button_red', 'sprites'); - unpackAndSave(media, index, 'chest', 'sprites'); - unpackAndSave(media, index, 'coins', 'sprites'); - unpackAndSave(media, index, 'key', 'sprites'); - unpackAndSave(media, index, 'keys', 'sprites'); - unpackAndSave(media, index, 'pen', 'sprites'); - unpackAndSave(media, index, 'startgame', 'sprites'); - unpackAndSave(media, index, 'titlescroll', 'sprites'); - unpackAndSave(media, index, 'letter', 'sprites'); - unpackAndSave(media, index, 'button_brown_big', 'sprites'); - unpackAndSave(media, index, 'headicons', 'sprites'); - unpackAndSave(media, index, 'headicons_pk', 'sprites'); - unpackAndSave(media, index, 'headicons_prayer', 'sprites'); - unpackAndSave(media, index, 'headicons_hint', 'sprites'); - unpackAndSave(media, index, 'overlay_multiway', 'sprites'); - unpackAndSave(media, index, 'overlay_duel', 'sprites'); - unpackAndSave(media, index, 'tex_brown', 'sprites'); - unpackAndSave(media, index, 'tex_red', 'sprites'); - unpackAndSave(media, index, 'number_button', 'sprites'); -} - -export function unpackTextures(textures: Jagfile | null) { - if (!textures) { - return null; - } - - const packOut = 'data/src/pack/texture.pack'; - fs.mkdirSync('data/src/pack', { recursive: true }); - fs.writeFileSync(packOut, ''); - - const index = textures.read('index.dat'); - - for (let i = 0; i < 50; i++) { - fs.appendFileSync(packOut, i + '=' + i + '\n'); - unpackAndSave(textures, index, i.toString(), 'textures'); - } -} - -export function unpackConfig(jag: Jagfile | null, name: string, decoder: (dat: Packet, code: number) => string | string[] | null) { - if (!jag) { - return; - } - - const dat = jag.read(name + '.dat'); - if (!dat) { - return; - } - - const packOut = 'data/src/pack/' + name + '.pack'; - fs.mkdirSync('data/src/pack', { recursive: true }); - fs.writeFileSync(packOut, ''); - - const srcOut = 'data/src/scripts/_unpack/all.' + name; - fs.mkdirSync('data/src/scripts/_unpack', { recursive: true }); - fs.writeFileSync(srcOut, ''); - - const count: number = dat.g2(); - for (let id = 0; id < count; id++) { - if (id > 0) { - fs.appendFileSync(srcOut, '\n'); - } - - fs.appendFileSync(packOut, id + '=' + name + '_' + id + '\n'); - - const src: string[] = []; - src.push('[' + name + '_' + id + ']'); - - while (true) { - const code = dat.g1(); - if (code === 0) { - break; - } - - const out = decoder(dat, code); - if (out === null) { - printError('Unrecognized ' + name + ' config code: ' + code); - process.exit(1); - } - - if (Array.isArray(out)) { - src.push(...out); - } else if (out.length > 0) { - src.push(out); - } - } - - fs.appendFileSync(srcOut, src.join('\n') + '\n'); - } - - printInfo(count + ' ' + name + ' configs unpacked'); -} - - -enum LocShape { - wall_straight, - wall_diagonalcorner, - wall_l, - wall_squarecorner, - walldecor_straight_nooffset, - walldecor_straight_offset, - walldecor_diagonal_nooffset, - walldecor_diagonal_offset, - walldecor_diagonal_both, - wall_diagonal, - centrepiece_straight, - centrepiece_diagonal, - roof_straight, - roof_diagonal_with_roofedge, - roof_diagonal, - roof_l_concave, - roof_l_convex, - roof_flat, - roofedge_straight, - roofedge_diagonalcorner, - roofedge_l, - roofedge_squarecorner, - grounddecor, -} - -export function decodeLoc(dat: Packet, code: number) { - if (code === 1 || code === 5) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const id = dat.g2(); - let shape = 10; - - if (code === 1) { - shape = dat.g1(); - } - - out.push('model' + (i + 1) + '=model_' + id + ',' + shape); // LocShape[shape]); - } - - return out; - } else if (code === 2) { - const value = dat.gjstr(); - return 'name=' + value; - } else if (code === 3) { - const value = dat.gjstr(); - return 'desc=' + value; - } else if (code === 14) { - const value = dat.g1(); - return 'width=' + value; - } else if (code === 15) { - const value = dat.g1(); - return 'length=' + value; - } else if (code === 17) { - return 'blockwalk=no'; - } else if (code === 18) { - return 'blockrange=no'; - } else if (code === 19) { - const value = dat.gbool(); - return 'active=' + (value ? 'yes' : 'no'); - } else if (code === 21) { - return 'hillskew=yes'; - } else if (code === 22) { - return 'sharelight=yes'; - } else if (code === 23) { - return 'occlude=yes'; - } else if (code === 24) { - const id = dat.g2(); - return 'anim=seq_' + id; - } else if (code === 25) { - return 'hasalpha=yes'; - } else if (code === 28) { - const value = dat.g1(); - return 'wallwidth=' + value; - } else if (code === 29) { - const value = dat.g1b(); - return 'ambient=' + value; - } else if (code === 39) { - const value = dat.g1b(); - return 'contrast=' + value; - } else if (code >= 30 && code < 39) { - const value = dat.gjstr(); - - const index = code - 30; - return 'op' + (index + 1) + '=' + value; - } else if (code === 40) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const src = dat.g2(); - const dst = dat.g2(); - - out.push('recol' + (i + 1) + 's=' + src); - out.push('recol' + (i + 1) + 'd=' + dst); - } - - return out; - } else if (code === 41) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const src = dat.g2(); - const dst = dat.g2(); - - out.push('//unsupported: retex' + (i + 1) + 's=' + src); - out.push('//unsupported: retex' + (i + 1) + 'd=' + dst); - } - - return out; - } else if (code === 60 || code === 82) { - const value = dat.g2(); - return 'mapfunction=' + value; - } else if (code === 62) { - return 'mirror=yes'; - } else if (code === 64) { - return 'shadow=no'; - } else if (code === 65) { - const value = dat.g2(); - return 'resizex=' + value; - } else if (code === 66) { - const value = dat.g2(); - return 'resizey=' + value; - } else if (code === 67) { - const value = dat.g2(); - return 'resizez=' + value; - } else if (code === 68) { - const value = dat.g2(); - return 'mapscene=' + value; - } else if (code === 69) { - const flags = dat.g1(); - - if ((flags & 0x1) === 0) { - return 'forceapproach=north'; - } else if ((flags & 0x2) === 0) { - return 'forceapproach=east'; - } else if ((flags & 0x4) === 0) { - return 'forceapproach=south'; - } else if ((flags & 0x8) === 0) { - return 'forceapproach=west'; - } - } else if (code === 70) { - const value = dat.g2s(); - return 'offsetx=' + value; - } else if (code === 71) { - const value = dat.g2s(); - return 'offsety=' + value; - } else if (code === 72) { - const value = dat.g2s(); - return 'offsetz=' + value; - } else if (code === 73) { - return 'forcedecor=yes'; - } else if (code === 74) { - return '//unsupported: breakroutefinding=yes'; - } else if (code === 75) { - const value = dat.gbool(); - return '//unsupported: raiseobject=' + (value ? 'yes' : 'no'); - } else if (code === 77 || code === 92) { - const out: string[] = []; - - let multiLocVarbit = dat.g2(); - if (multiLocVarbit === 65535) { - multiLocVarbit = -1; - } - - if (multiLocVarbit !== -1) { - out.push('//unsupported: multivar=varbit_' + multiLocVarbit); - } - - let multiLocVarp = dat.g2(); - if (multiLocVarp === 65535) { - multiLocVarp = -1; - } - - if (multiLocVarp !== -1) { - out.push('//unsupported: multivar=varp_' + multiLocVarp); - } - - let defaultMultiLoc: number = -1; - if (code === 92) { - defaultMultiLoc = dat.g2(); - - if (defaultMultiLoc === 65535) { - defaultMultiLoc = -1; - } - } - - const count: number = dat.g1(); - const multiLocs = new Int32Array(count + 1); - - for (let i: number = 0; i <= count; i++) { - multiLocs[i] = dat.g2(); - - if (multiLocs[i] === 65535) { - multiLocs[i] = -1; - } - } - - multiLocs[count + 1] = defaultMultiLoc; - - if (defaultMultiLoc !== -1) { - out.push('//unsupported: defaultloc=loc_' + defaultMultiLoc); - } - - for (let i: number = 0; i <= count; i++) { - if (multiLocs[i] !== -1) { - out.push('//unsupported: multiloc=' + i + ',loc_' + multiLocs[i]); - } - } - - return out; - } else if (code === 78) { - const id = dat.g2(); - const value2 = dat.g1(); - return '//unsupported: bgsound=sound_' + id + ',' + value2; - } else if (code === 79) { - const out: string[] = []; - out.push('//unsupported: randomsound=' + dat.g2() + ',' + dat.g2() + ',' + dat.g1()); - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const id = dat.g2(); - out.push('//unsupported: randomsound' + (i + 1) + '=sound_' + id); - } - - out.push('//unsupported: bgsound=sound_' + dat.g2() + ',' + dat.g1()); - return out; - } else if (code === 81) { - const value = dat.g1(); - return '//unsupported: treeskew=' + value; - } - - return null; -} - -export function decodeNpc(dat: Packet, code: number) { - if (code === 1) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const id = dat.g2(); - out.push('model' + (i + 1) + '=model_' + id); - } - - return out; - } else if (code === 2) { - const value = dat.gjstr(); - return 'name=' + value; - } else if (code === 3) { - const value = dat.gjstr(); - return 'desc=' + value; - } else if (code === 12) { - const value = dat.g1(); - return 'size=' + value; - } else if (code === 13) { - const id = dat.g2(); - return 'readyanim=seq_' + id; - } else if (code === 14) { - const id = dat.g2(); - return 'walkanim=seq_' + id; - } else if (code === 16) { - return 'hasalpha=yes'; - } else if (code === 17) { - const front = dat.g2(); - const back = dat.g2(); - const right = dat.g2(); - const left = dat.g2(); - - return 'walkanim=seq_' + front + ',seq_' + back + ',seq_' + right + ',seq_' + left; - } else if (code >= 30 && code < 40) { - const value = dat.gjstr(); - - const index = code - 30; - return 'op' + (index + 1) + '=' + value; - } else if (code === 40) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const src = dat.g2(); - const dst = dat.g2(); - - out.push('recol' + (i + 1) + 's=' + src); - out.push('recol' + (i + 1) + 'd=' + dst); - } - - return out; - } else if (code === 60) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const id = dat.g2(); - out.push('head' + (i + 1) + '=model_' + id); - } - - return out; - } else if (code === 90) { - const value = dat.g2(); - return 'code90=' + value; - } else if (code === 91) { - const value = dat.g2(); - return 'code91=' + value; - } else if (code === 92) { - const value = dat.g2(); - return 'code92=' + value; - } else if (code === 93) { - return 'minimap=no'; - } else if (code === 95) { - const value = dat.g2(); - - if (value === 0) { - return 'vislevel=hide'; - } - - return 'vislevel=' + value; - } else if (code === 97) { - const value = dat.g2(); - return 'resizeh=' + value; - } else if (code === 98) { - const value = dat.g2(); - return 'resizev=' + value; - } else if (code === 99) { - return '//unsupported: alwaysontop=yes'; - } else if (code === 100) { - const value = dat.g1b(); - return '//unsupported: ambient=' + value; - } else if (code === 101) { - const value = dat.g1b(); - return '//unsupported: contrast=' + value; - } else if (code === 102) { - const value = dat.g2(); - return '//unsupported: headicon=' + value; - } else if (code === 103) { - const value = dat.g2(); - return '//unsupported: turnspeed=' + value; - } else if (code === 106) { - const out: string[] = []; - - let multiNpcVarbit = dat.g2(); - if (multiNpcVarbit === 65535) { - multiNpcVarbit = -1; - } - - if (multiNpcVarbit !== -1) { - out.push('//unsupported: multivar=varbit_' + multiNpcVarbit); - } - - let multiNpcVarp = dat.g2(); - if (multiNpcVarp === 65535) { - multiNpcVarp = -1; - } - - if (multiNpcVarp !== -1) { - out.push('//unsupported: multivar=varp_' + multiNpcVarp); - } - - const count: number = dat.g1(); - const multiNpcs = new Int32Array(count + 1); - - for (let i: number = 0; i <= count; i++) { - multiNpcs[i] = dat.g2(); - if (multiNpcs[i] === 65535) { - multiNpcs[i] = -1; - } - } - - for (let i: number = 0; i <= count; i++) { - if (multiNpcs[i] !== -1) { - out.push('//unsupported: multinpc' + (i + 1) + '=npc_' + multiNpcs[i]); - } - } - - return out; - } else if (code === 107) { - return '//unsupported: active=no'; - } - - return null; -} - -export function decodeObj(dat: Packet, code: number) { - if (code === 1) { - const id = dat.g2(); - return 'model=model_' + id; - } else if (code === 2) { - const value = dat.gjstr(); - return 'name=' + value; - } else if (code === 3) { - const value = dat.gjstr(); - return 'desc=' + value; - } else if (code === 4) { - const value = dat.g2s(); - return '2dzoom=' + value; - } else if (code === 5) { - const value = dat.g2s(); - return '2dxan=' + value; - } else if (code === 6) { - const value = dat.g2s(); - return '2dyan=' + value; - } else if (code === 7) { - const value = dat.g2s(); - return '2dxof=' + value; - } else if (code === 8) { - const value = dat.g2s(); - return '2dyof=' + value; - } else if (code === 9) { - return 'code9=yes'; - } else if (code === 10) { - const id = dat.g2(); - return 'code10=seq_' + id; - } else if (code === 11) { - return 'stackable=yes'; - } else if (code === 12) { - const value = dat.g4(); - return 'cost=' + value; - } else if (code === 16) { - return 'members=yes'; - } else if (code === 23) { - const id = dat.g2(); - const offset = dat.g1(); - return 'manwear=model_' + id + ',' + offset; - } else if (code === 24) { - const id = dat.g2(); - return 'manwear2=model_' + id; - } else if (code === 25) { - const id = dat.g2(); - const offset = dat.g1(); - return 'womanwear=model_' + id + ',' + offset; - } else if (code === 26) { - const id = dat.g2(); - return 'womanwear2=model_' + id; - } else if (code >= 30 && code < 35) { - const value = dat.gjstr(); - - const index = code - 30; - return 'op' + (index + 1) + '=' + value; - } else if (code >= 35 && code < 40) { - const value = dat.gjstr(); - - const index = code - 35; - return 'iop' + (index + 1) + '=' + value; - } else if (code === 40) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const src = dat.g2(); - const dst = dat.g2(); - - out.push('recol' + (i + 1) + 's=' + src); - out.push('recol' + (i + 1) + 'd=' + dst); - } - - return out; - } else if (code === 78) { - const id = dat.g2(); - return 'manwear3=model_' + id; - } else if (code === 79) { - const id = dat.g2(); - return 'womanwear3=model_' + id; - } else if (code === 90) { - const id = dat.g2(); - return 'manhead=model_' + id; - } else if (code === 91) { - const id = dat.g2(); - return 'womanhead=model_' + id; - } else if (code === 92) { - const id = dat.g2(); - return 'manhead2=model_' + id; - } else if (code === 93) { - const id = dat.g2(); - return 'womanhead2=model_' + id; - } else if (code === 95) { - const value = dat.g2s(); - return '2dzan=' + value; - } else if (code === 97) { - const id = dat.g2(); - return 'certlink=obj_' + id; - } else if (code === 98) { - const id = dat.g2(); - return 'certtemplate=obj_' + id; - } else if (code >= 100 && code < 110) { - const id = dat.g2(); - const count = dat.g2(); - - const index = code - 100; - return 'count' + (index + 1) + '=obj_' + id + ',' + count; - } else if (code === 110) { - const value = dat.g2(); - return '//unsupported: resizex=' + value; - } else if (code === 111) { - const value = dat.g2(); - return '//unsupported: resizey=' + value; - } else if (code === 112) { - const value = dat.g2(); - return '//unsupported: resizez=' + value; - } else if (code === 113) { - const value = dat.g1b(); - return '//unsupported: ambient=' + value; - } else if (code === 114) { - const value = dat.g1b(); - return '//unsupported: contrast=' + value; - } else if (code === 115) { - const value = dat.g1(); - return '//unsupported: team=' + value; - } - - return null; -} - -export function decodeSeq(dat: Packet, code: number) { - if (code === 1) { - const frame = []; - const iframe = []; - const delay = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - frame[i] = dat.g2(); - - iframe[i] = dat.g2(); - if (iframe[i] === 65535) { - iframe[i] = -1; - } - - delay[i] = dat.g2(); - } - - const out: string[] = []; - - for (let i = 0; i < count; i++) { - out.push('frame' + (i + 1) + '=anim_' + frame[i]); - - if (delay[i] !== 0) { - out.push('delay' + (i + 1) + '=' + delay[i]); - } - } - - for (let i = 0; i < count; i++) { - if (iframe[i] === -1) { - continue; - } - - out.push('iframe' + (i + 1) + '=anim_' + iframe[i]); - } - - return out; - } else if (code === 2) { - const value = dat.g2(); - return 'replayoff=' + value; - } else if (code === 3) { - const count = dat.g1(); - - const labels = []; - for (let i = 0; i < count; i++) { - labels[i] = dat.g1(); - } - - return 'walkmerge=' + labels.map(l => 'label_' + l).join(','); - } else if (code === 4) { - // dat.g2(); // 194 - return 'stretches=yes'; - } else if (code === 5) { - const value = dat.g1(); - return 'priority=' + value; - } else if (code === 6) { - const id = dat.g2(); - - if (id === 0) { - return 'righthand=hide'; - } else { - return 'righthand=obj_' + (id - 512); - } - } else if (code === 7) { - const id = dat.g2(); - - if (id === 0) { - return 'lefthand=hide'; - } else { - return 'lefthand=obj_' + (id - 512); - } - } else if (code === 8) { - const value = dat.g1(); - return 'replaycount=' + value; - } else if (code === 9) { - const value = dat.g1(); - return '//unsupported: code9=' + value; - } else if (code === 10) { - const value = dat.g1(); - return '//unsupported: code10=' + value; - } else if (code === 11) { - const value = dat.g1(); - return '//unsupported: code11=' + value; - } else if (code === 12) { - const value = dat.g4(); - return '//unsupported: code12=' + value; - } - - return null; -} - -export function decodeVarp(dat: Packet, code: number) { - if (code === 5) { - const value = dat.g2(); - return 'clientcode=' + value; - } - - return null; -} - -export function decodeSpotAnim(dat: Packet, code: number) { - if (code === 1) { - const id = dat.g2(); - return 'model=model_' + id; - } else if (code === 2) { - const id = dat.g2(); - return 'anim=seq_' + id; - } else if (code === 3) { - return 'hasalpha=yes'; - } else if (code === 4) { - const size = dat.g2(); - return 'resizeh=' + size; - } else if (code === 5) { - const size = dat.g2(); - return 'resizev=' + size; - } else if (code === 6) { - const angle = dat.g2(); - return 'orientation=' + angle; - } else if (code === 7) { - const value = dat.g1b(); - return 'ambient=' + value; - } else if (code === 8) { - const value = dat.g1b(); - return 'contrast=' + value; - } else if (code >= 40 && code < 50) { - const hsl16 = dat.g2(); - - const index = code - 40; - return 'recol' + (index + 1) + 's=' + hsl16; - } else if (code >= 50 && code < 60) { - const hsl16 = dat.g2(); - - const index = code - 50; - return 'recol' + (index + 1) + 'd=' + hsl16; - } - - return null; -} - -enum IdkBodyPart { - man_hair, - man_jaw, - man_torso, - man_arms, - man_hands, - man_legs, - man_feet, - woman_hair, - woman_jaw, - woman_torso, - woman_arms, - woman_hands, - woman_legs, - woman_feet -} - -export function decodeIdk(dat: Packet, code: number) { - if (code === 1) { - const type = dat.g1(); - return 'type=' + IdkBodyPart[type]; - } else if (code === 2) { - const out: string[] = []; - - const count = dat.g1(); - for (let i = 0; i < count; i++) { - const id = dat.g2(); - out.push(`model${i + 1}=model_${id}`); - } - - return out; - } else if (code === 3) { - return 'disable=yes'; - } else if (code >= 40 && code < 50) { - const hsl16 = dat.g2(); - - const index = code - 40; - return 'recol' + (index + 1) + 's=' + hsl16; - } else if (code >= 50 && code < 60) { - const hsl16 = dat.g2(); - - const index = code - 50; - return 'recol' + (index + 1) + 'd=' + hsl16; - } else if (code >= 60 && code < 70) { - const id = dat.g2(); - - const index = code - 60; - return `head${index + 1}=model_${id}`; - } - - return null; -} - -export function decodeFlo(dat: Packet, code: number) { - if (code === 1) { - const colour = dat.g3(); - return 'rgb=0x' + colour.toString(16).toUpperCase().padStart(6, '0'); - } else if (code === 2) { - const texture = dat.g1(); - return 'texture=' + texture; - } else if (code === 3) { - return 'overlay=yes'; - } else if (code === 5) { - return 'occlude=no'; - } else if (code === 6) { - const name = dat.gjstr(); - return '//implicit: editname=' + name; - } else if (code === 7) { - const average = dat.g3(); - return '//unsupported: maprgb=0x' + average.toString(16).toUpperCase().padStart(6, '0'); - } - - return null; -} - -export function decodeVarbit(dat: Packet, code: number) { - if (code === 1) { - const basevar = dat.g2(); - const startbit = dat.g1(); - const endbit = dat.g1(); - - const out: string[] = []; - out.push('//unsupported: basevar=varp_' + basevar); - out.push('//unsupported: startbit=' + startbit); - out.push('//unsupported: endbit=' + endbit); - return out; - } - - return null; -} - -export function decodeNoOp(dat: Packet, code: number) { - return null; -} - -export function unpackWordenc(jag: Jagfile | null) { - if (!jag) { - return; - } - - const badenc = jag.read('badenc.txt'); - const domainenc = jag.read('domainenc.txt'); - const fragmentsenc = jag.read('fragmentsenc.txt'); - const tldlist = jag.read('tldlist.txt'); - - if (!badenc) { - return; - } - - if (!domainenc) { - return; - } - - if (!fragmentsenc) { - return; - } - - if (!tldlist) { - return; - } - - fs.mkdirSync('data/src/wordenc', { recursive: true }); - - // ---- - - { - fs.writeFileSync('data/src/wordenc/badenc.txt', ''); - - const total = badenc.g4(); - for (let i = 0; i < total; i++) { - let badword = ''; - const count = badenc.g1(); - for (let j = 0; j < count; j++) { - badword += String.fromCharCode(badenc.g1()); - } - fs.appendFileSync('data/src/wordenc/badenc.txt', badword); - - const combinations = badenc.g1(); - for (let j = 0; j < combinations; j++) { - const a = badenc.g1(); - const b = badenc.g1(); - - fs.appendFileSync('data/src/wordenc/badenc.txt', ` ${a}:${b}`); - } - - fs.appendFileSync('data/src/wordenc/badenc.txt', '\n'); - } - } - - // ---- - - { - fs.writeFileSync('data/src/wordenc/domainenc.txt', ''); - - const total = domainenc.g4(); - for (let i = 0; i < total; i++) { - let domain = ''; - const count = domainenc.g1(); - for (let j = 0; j < count; j++) { - domain += String.fromCharCode(domainenc.g1()); - } - - fs.appendFileSync('data/src/wordenc/domainenc.txt', domain + '\n'); - } - } - - // ---- - - { - fs.writeFileSync('data/src/wordenc/fragmentsenc.txt', ''); - - const total = fragmentsenc.g4(); - for (let i = 0; i < total; i++) { - const fragment = fragmentsenc.g2(); - fs.appendFileSync('data/src/wordenc/fragmentsenc.txt', fragment + '\n'); - } - } - - // ---- - - { - fs.writeFileSync('data/src/wordenc/tldlist.txt', ''); - - const total = tldlist.g4(); - for (let i = 0; i < total; i++) { - const type = tldlist.g1(); - - let tld = ''; - const count = tldlist.g1(); - for (let j = 0; j < count; j++) { - tld += String.fromCharCode(tldlist.g1()); - } - - fs.appendFileSync('data/src/wordenc/tldlist.txt', `${tld} ${type}\n`); - } - } -} diff --git a/src/lostcity/util/Environment.ts b/src/lostcity/util/Environment.ts index da8b040863..1054c45dc9 100644 --- a/src/lostcity/util/Environment.ts +++ b/src/lostcity/util/Environment.ts @@ -9,6 +9,9 @@ export default { WEB_PORT: tryParseInt(process.env.WEB_PORT, process.platform === 'win32' ? 80 : 8888), WEB_CORS: tryParseBoolean(process.env.WEB_CORS, true), + // management server + WEB_MANAGEMENT_PORT: tryParseInt(process.env.WEB_MANAGEMENT_PORT, 8898), + /// game server // world id - offset by 9, so 1 = 10, 2 = 11, etc NODE_ID: tryParseInt(process.env.NODE_ID, 10), @@ -25,7 +28,7 @@ export default { // extra debug info e.g. missing triggers NODE_DEBUG: tryParseBoolean(process.env.NODE_DEBUG, true), // measuring script execution - NODE_DEBUG_PROFILER: tryParseBoolean(process.env.NODE_DEBUG_PROFILE, false), + NODE_DEBUG_PROFILE: tryParseBoolean(process.env.NODE_DEBUG_PROFILE, false), // *only* if no login server is running to authenticate accounts, this provides admin accs by username :) NODE_STAFF: tryParseArray(process.env.NODE_STAFF?.split(','), ['pazaz']), // todo: add staffmodlevel to database // no server routefinding until 2009 diff --git a/src/lostcity/util/PackFile.ts b/src/lostcity/util/PackFile.ts index 4065ca45b4..47600eb8e0 100644 --- a/src/lostcity/util/PackFile.ts +++ b/src/lostcity/util/PackFile.ts @@ -9,6 +9,8 @@ type PackFileValidator = (packfile: PackFile, ...args: any[]) => void; export class PackFile { type: string; + validator: PackFileValidator | null = null; + validatorArgs: any[] = []; pack: Map = new Map(); names: Set = new Set(); max: number = 0; @@ -20,11 +22,16 @@ export class PackFile { // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor(type: string, validator: PackFileValidator | null = null, ...validatorArgs: any[]) { this.type = type; + this.validator = validator; + this.validatorArgs = validatorArgs; + this.reload(); + } - if (validator !== null) { - validator(this, ...validatorArgs); + reload() { + if (this.validator !== null) { + this.validator(this, ...this.validatorArgs); } else { - this.load(`${Environment.BUILD_SRC_DIR}/pack/${type}.pack`); + this.load(`${Environment.BUILD_SRC_DIR}/pack/${this.type}.pack`); } } @@ -254,60 +261,60 @@ function regenScriptPack(pack: PackFile) { pack.save(); } -export let AnimPack = new PackFile('anim', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.frame'); -export let BasePack = new PackFile('base', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.base'); -export let CategoryPack = new PackFile('category', validateCategoryPack); -export let DbRowPack = new PackFile('dbrow', validateConfigPack, '.dbrow', true, false, false, true); -export let DbTablePack = new PackFile('dbtable', validateConfigPack, '.dbtable', true, false, false, true); -export let EnumPack = new PackFile('enum', validateConfigPack, '.enum', true, false, false, true); -export let FloPack = new PackFile('flo', validateConfigPack, '.flo'); -export let HuntPack = new PackFile('hunt', validateConfigPack, '.hunt', true, false, false, true); -export let IdkPack = new PackFile('idk', validateConfigPack, '.idk'); -export let InterfacePack = new PackFile('interface', validateInterfacePack); -export let InvPack = new PackFile('inv', validateConfigPack, '.inv', true); -export let LocPack = new PackFile('loc', validateConfigPack, '.loc'); -export let MesAnimPack = new PackFile('mesanim', validateConfigPack, '.mesanim', true, false, false, true); -export let ModelPack = new PackFile('model', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.ob2'); -export let NpcPack = new PackFile('npc', validateConfigPack, '.npc'); -export let ObjPack = new PackFile('obj', validateConfigPack, '.obj'); -export let ParamPack = new PackFile('param', validateConfigPack, '.param', true, false, false, true); -export let ScriptPack = new PackFile('script', regenScriptPack); -export let SeqPack = new PackFile('seq', validateConfigPack, '.seq'); -export let SoundPack = new PackFile('sound', validateFilesPack, `${Environment.BUILD_SRC_DIR}/sounds`, '.synth'); -export let SpotAnimPack = new PackFile('spotanim', validateConfigPack, '.spotanim'); -export let StructPack = new PackFile('struct', validateConfigPack, '.struct', true, false, false, true); -export let TexturePack = new PackFile('texture', validateImagePack, `${Environment.BUILD_SRC_DIR}/textures`, '.png'); -export let VarpPack = new PackFile('varp', validateConfigPack, '.varp', true); -export let VarnPack = new PackFile('varn', validateConfigPack, '.varn', true, false, false, true); -export let VarsPack = new PackFile('vars', validateConfigPack, '.vars', true, false, false, true); +export const AnimPack = new PackFile('anim', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.frame'); +export const BasePack = new PackFile('base', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.base'); +export const CategoryPack = new PackFile('category', validateCategoryPack); +export const DbRowPack = new PackFile('dbrow', validateConfigPack, '.dbrow', true, false, false, true); +export const DbTablePack = new PackFile('dbtable', validateConfigPack, '.dbtable', true, false, false, true); +export const EnumPack = new PackFile('enum', validateConfigPack, '.enum', true, false, false, true); +export const FloPack = new PackFile('flo', validateConfigPack, '.flo'); +export const HuntPack = new PackFile('hunt', validateConfigPack, '.hunt', true, false, false, true); +export const IdkPack = new PackFile('idk', validateConfigPack, '.idk'); +export const InterfacePack = new PackFile('interface', validateInterfacePack); +export const InvPack = new PackFile('inv', validateConfigPack, '.inv', true); +export const LocPack = new PackFile('loc', validateConfigPack, '.loc'); +export const MesAnimPack = new PackFile('mesanim', validateConfigPack, '.mesanim', true, false, false, true); +export const ModelPack = new PackFile('model', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.ob2'); +export const NpcPack = new PackFile('npc', validateConfigPack, '.npc'); +export const ObjPack = new PackFile('obj', validateConfigPack, '.obj'); +export const ParamPack = new PackFile('param', validateConfigPack, '.param', true, false, false, true); +export const ScriptPack = new PackFile('script', regenScriptPack); +export const SeqPack = new PackFile('seq', validateConfigPack, '.seq'); +export const SoundPack = new PackFile('sound', validateFilesPack, `${Environment.BUILD_SRC_DIR}/sounds`, '.synth'); +export const SpotAnimPack = new PackFile('spotanim', validateConfigPack, '.spotanim'); +export const StructPack = new PackFile('struct', validateConfigPack, '.struct', true, false, false, true); +export const TexturePack = new PackFile('texture', validateImagePack, `${Environment.BUILD_SRC_DIR}/textures`, '.png'); +export const VarpPack = new PackFile('varp', validateConfigPack, '.varp', true); +export const VarnPack = new PackFile('varn', validateConfigPack, '.varn', true, false, false, true); +export const VarsPack = new PackFile('vars', validateConfigPack, '.vars', true, false, false, true); export function revalidatePack() { - AnimPack = new PackFile('anim', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.frame'); - BasePack = new PackFile('base', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.base'); - CategoryPack = new PackFile('category', validateCategoryPack); - DbRowPack = new PackFile('dbrow', validateConfigPack, '.dbrow', true, false, false, true); - DbTablePack = new PackFile('dbtable', validateConfigPack, '.dbtable', true, false, false, true); - EnumPack = new PackFile('enum', validateConfigPack, '.enum', true, false, false, true); - FloPack = new PackFile('flo', validateConfigPack, '.flo'); - HuntPack = new PackFile('hunt', validateConfigPack, '.hunt', true, false, false, true); - IdkPack = new PackFile('idk', validateConfigPack, '.idk'); - InterfacePack = new PackFile('interface', validateInterfacePack); - InvPack = new PackFile('inv', validateConfigPack, '.inv', true); - LocPack = new PackFile('loc', validateConfigPack, '.loc'); - MesAnimPack = new PackFile('mesanim', validateConfigPack, '.mesanim', true, false, false, true); - ModelPack = new PackFile('model', validateFilesPack, `${Environment.BUILD_SRC_DIR}/models`, '.ob2'); - NpcPack = new PackFile('npc', validateConfigPack, '.npc'); - ObjPack = new PackFile('obj', validateConfigPack, '.obj'); - ParamPack = new PackFile('param', validateConfigPack, '.param', true, false, false, true); - ScriptPack = new PackFile('script', regenScriptPack); - SeqPack = new PackFile('seq', validateConfigPack, '.seq'); - SoundPack = new PackFile('sound', validateFilesPack, `${Environment.BUILD_SRC_DIR}/sounds`, '.synth'); - SpotAnimPack = new PackFile('spotanim', validateConfigPack, '.spotanim'); - StructPack = new PackFile('struct', validateConfigPack, '.struct', true, false, false, true); - TexturePack = new PackFile('texture', validateImagePack, `${Environment.BUILD_SRC_DIR}/textures`, '.png'); - VarpPack = new PackFile('varp', validateConfigPack, '.varp', true); - VarnPack = new PackFile('varn', validateConfigPack, '.varn', true, false, false, true); - VarsPack = new PackFile('vars', validateConfigPack, '.vars', true, false, false, true); + AnimPack.reload(); + BasePack.reload(); + CategoryPack.reload(); + DbRowPack.reload(); + DbTablePack.reload(); + EnumPack.reload(); + FloPack.reload(); + HuntPack.reload(); + IdkPack.reload(); + InterfacePack.reload(); + InvPack.reload(); + LocPack.reload(); + MesAnimPack.reload(); + ModelPack.reload(); + NpcPack.reload(); + ObjPack.reload(); + ParamPack.reload(); + ScriptPack.reload(); + SeqPack.reload(); + SoundPack.reload(); + SpotAnimPack.reload(); + StructPack.reload(); + TexturePack.reload(); + VarpPack.reload(); + VarnPack.reload(); + VarsPack.reload(); } export function crawlConfigNames(ext: string, includeBrackets = false) { diff --git a/src/lostcity/util/PackIds.ts b/src/lostcity/util/PackIds.ts deleted file mode 100644 index 9d2dcf5f34..0000000000 --- a/src/lostcity/util/PackIds.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { loadDir } from '#lostcity/util/NameMap.js'; - -export function crawlConfigNames(ext: string, includeBrackets = false) { - const names: string[] = []; - - loadDir('data/src/scripts', ext, (src, file) => { - if (file === 'engine.rs2') { - // these command signatures are specifically for the compiler to have type information - return; - } - - for (let i = 0; i < src.length; i++) { - const line = src[i]; - if (line.startsWith('//')) { - continue; - } - - if (line.startsWith('[')) { - let name = line.substring(0, line.indexOf(']') + 1); - if (!includeBrackets) { - name = name.substring(1, name.length - 1); - } - - if (names.indexOf(name) === -1) { - names.push(name); - } - } - } - }); - - return names; -} - -export function crawlConfigCategories() { - const names: string[] = []; - - loadDir('data/src/scripts', '.loc', src => { - for (let i = 0; i < src.length; i++) { - const line = src[i]; - - if (line.startsWith('category=')) { - const name = line.substring('category='.length); - - if (names.indexOf(name) === -1) { - names.push(name); - } - } - } - }); - - loadDir('data/src/scripts', '.npc', src => { - for (let i = 0; i < src.length; i++) { - const line = src[i]; - - if (line.startsWith('category=')) { - const name = line.substring('category='.length); - - if (names.indexOf(name) === -1) { - names.push(name); - } - } - } - }); - - loadDir('data/src/scripts', '.obj', src => { - for (let i = 0; i < src.length; i++) { - const line = src[i]; - - if (line.startsWith('category=')) { - const name = line.substring('category='.length); - - if (names.indexOf(name) === -1) { - names.push(name); - } - } - } - }); - - return names; -} - -export function regenPack(pack: string[], names: string[], reduce = false, reuse = false, recycle = false) { - const reuseIds = []; - - if (reduce) { - // remove missing ids (shifts ids) - pack = pack.filter(x => x); - - // remove missing names (shifts ids) - for (let i = 0; i < pack.length; i++) { - if (names.indexOf(pack[i]) === -1) { - pack.splice(i--, 1); - } - } - } else if (reuse) { - // if something was deleted, prioritize placing new names in those deleted slots - for (let i = 0; i < pack.length; i++) { - if (names.indexOf(pack[i]) === -1) { - reuseIds.push(i); - } - } - } else if (recycle) { - // completely scorched earth (resets ids) - pack = []; - } - - for (let i = 0; i < names.length; i++) { - const name = names[i]; - let id = pack.indexOf(name); - - if (id === -1) { - if (reuseIds.length) { - // ! is safe because we know reuseIds.length > 0 - id = reuseIds.shift()!; - pack[id] = name; - } else { - pack.push(name); - } - } - } - - return ( - pack - .map((name, id) => `${id}=${name}`) - .filter(x => x) - .join('\n') + '\n' - ); -} diff --git a/src/lostcity/util/Parse.ts b/src/lostcity/util/Parse.ts index 22130d62cc..60917b8d1d 100644 --- a/src/lostcity/util/Parse.ts +++ b/src/lostcity/util/Parse.ts @@ -23,7 +23,7 @@ export function loadFile(path: string): string[] { // fully-featured! strips out comments export function loadFileFull(path: string) { - const text = readTextNormalize(path)!.split('\n'); + const text = readTextNormalize(path).split('\n'); const lines = []; let multiCommentStart = 0; diff --git a/src/lostcity/util/PixPack.ts b/src/lostcity/util/PixPack.ts index 6d7d81ac32..a0283e2256 100644 --- a/src/lostcity/util/PixPack.ts +++ b/src/lostcity/util/PixPack.ts @@ -1,10 +1,9 @@ import fs from 'fs'; -import Jimp from 'jimp'; +import { Bitmap, Jimp } from 'jimp'; -import Packet from '#jagex2/io/Packet.js'; -import { printError } from './Logger.js'; +import Packet from '#jagex/io/Packet.js'; -export function generatePixelOrder(img: Jimp) { +export function generatePixelOrder(img: { bitmap: Bitmap }) { let rowMajorScore = 0; let columnMajorScore = 0; @@ -31,7 +30,7 @@ export function generatePixelOrder(img: Jimp) { return columnMajorScore < rowMajorScore ? 0 : 1; } -export function writeImage(img: Jimp, data: Packet, index: Packet, colors: number[], meta: Sprite | null = null) { +export function writeImage(img: { bitmap: Bitmap }, data: Packet, index: Packet, colors: number[], meta: Sprite | null = null) { let left = 0; let top = 0; let right = img.bitmap.width; @@ -49,14 +48,11 @@ export function writeImage(img: Jimp, data: Packet, index: Packet, colors: numbe index.p2(right); // actual width index.p2(bottom); // actual height - // console.log('\t', left, top, '-', right, bottom, '-', img.bitmap.width, img.bitmap.height); - let pixelOrder = generatePixelOrder(img); if (meta) { pixelOrder = meta.pixelOrder; } index.p1(pixelOrder); - // console.log('\t', pixelOrder ? 'row' : 'column'); if (pixelOrder === 0) { for (let j = 0; j < img.bitmap.width * img.bitmap.height; j++) { @@ -75,11 +71,6 @@ export function writeImage(img: Jimp, data: Packet, index: Packet, colors: numbe const index = colors.indexOf(rgb); if (index === -1) { - console.error( - 'color not found in palette', - rgb.toString(16), - colors.map(x => x.toString(16)) - ); break; } @@ -101,7 +92,6 @@ export function writeImage(img: Jimp, data: Packet, index: Packet, colors: numbe const index = colors.indexOf(rgb); if (index === -1) { - console.error('color not found in palette', rgb); break; } @@ -119,6 +109,28 @@ type Sprite = { pixelOrder: 0 | 1; }; +function generatePalette(img: { bitmap: Bitmap }) { + const colors = [0xff00ff]; + + for (let j = 0; j < img.bitmap.width * img.bitmap.height; j++) { + const pos = j * 4; + + const red = img.bitmap.data[pos + 0]; + const green = img.bitmap.data[pos + 1]; + const blue = img.bitmap.data[pos + 2]; + const rgb = ((red << 16) | (green << 8) | blue) >>> 0; + if (rgb === 0xff00ff) { + continue; + } + + if (colors.indexOf(rgb) === -1) { + colors.push(rgb); + } + } + + return colors; +} + export async function convertImage(index: Packet, srcPath: string, safeName: string) { const data = Packet.alloc(4); data.p2(index.pos); @@ -168,49 +180,19 @@ export async function convertImage(index: Packet, srcPath: string, safeName: str index.p2(tileX); index.p2(tileY); - const colors = [0xff00ff]; // reserved for transparency + let colors: number[] = []; if (fs.existsSync(`${srcPath}/meta/${safeName}.pal.png`)) { - // read color palette from file to preserve order - const pal = await Jimp.read(`${srcPath}/meta/${safeName}.pal.png`); - - for (let j = 0; j < pal.bitmap.width * pal.bitmap.height; j++) { - const pos = j * 4; - - const red = pal.bitmap.data[pos + 0]; - const green = pal.bitmap.data[pos + 1]; - const blue = pal.bitmap.data[pos + 2]; - const rgb = ((red << 16) | (green << 8) | blue) >>> 0; - if (rgb === 0xff00ff) { - continue; - } - - colors[j] = rgb; - } + // workaround to preserve CRC integrity (not required) + colors = generatePalette(await Jimp.read(`${srcPath}/meta/${safeName}.pal.png`)); } else { - // generate color palette by counting unique colors - - // console.log('generating color palette', safeName); - for (let j = 0; j < img.bitmap.width * img.bitmap.height; j++) { - const pos = j * 4; - - const red = img.bitmap.data[pos + 0]; - const green = img.bitmap.data[pos + 1]; - const blue = img.bitmap.data[pos + 2]; - const rgb = ((red << 16) | (green << 8) | blue) >>> 0; - if (rgb === 0xff00ff) { - continue; - } - - if (colors.indexOf(rgb) === -1) { - colors.push(rgb); - } - } + // todo: we're not producing the color palette in the same way, so this breaks CRC checks. + // however, the end result after decoding is the same + colors = generatePalette(img); } if (colors.length > 255) { - // TODO: automatic color quantization based on variable limit? - printError('too many colors: ' + colors.length + ' while only 255 are allowed'); - return; + img.quantize({ colors: 255 }); + colors = generatePalette(img); } index.p1(colors.length); @@ -221,7 +203,12 @@ export async function convertImage(index: Packet, srcPath: string, safeName: str if (sprites.length > 1) { for (let y = 0; y < img.bitmap.height / tileY; y++) { for (let x = 0; x < img.bitmap.width / tileX; x++) { - const tile = img.clone().crop(x * tileX, y * tileY, tileX, tileY); + const tile = img.clone().crop({ + x: x * tileX, + y: y * tileY, + w: tileX, + h: tileY + }); writeImage(tile, data, index, colors, sprites[x + y * (img.bitmap.width / tileX)]); } } diff --git a/src/lostcity/util/PixUnpack.ts b/src/lostcity/util/PixUnpack.ts deleted file mode 100644 index a7daaad8f0..0000000000 --- a/src/lostcity/util/PixUnpack.ts +++ /dev/null @@ -1,146 +0,0 @@ -import Jimp from 'jimp'; - -import Packet from '#jagex2/io/Packet.js'; - -export function pixSize(dat: Packet, idx: Packet) { - dat.pos = 0; - idx.pos = dat.g2(); - - const width = idx.g2(); - const height = idx.g2(); - - return { width, height }; -} - -export function countPix(dat: Packet, idx: Packet) { - dat.pos = 0; - idx.pos = dat.g2(); - - if (idx.pos > idx.data.length) { - // console.error('not pix encoding'); - return 0; - } - - const cropW = idx.g2(); - const cropH = idx.g2(); - - const paletteCount = idx.g1(); - for (let i = 0; i < paletteCount - 1; i++) { - idx.g3(); - } - - let count = 0; - for (let i = 0; i < 512; i++) { - if (dat.available <= 0) { - break; - } - - const cropX = idx.g1(); - const cropY = idx.g1(); - if (cropX > cropW || cropY > cropH) { - // console.error('invalid crop'); - break; - } - - const width = idx.g2(); - const height = idx.g2(); - if (width === 0 || height === 0 || width > cropW - cropX || height > cropH - cropY) { - // console.error('invalid size'); - break; - } - - dat.pos += width * height; - if (dat.pos > dat.data.length) { - // console.error('out of bounds'); - break; - } - - const pixelOrder = idx.g1(); - if (pixelOrder > 1) { - // console.error('invalid order'); - break; - } - - count++; - } - - return count; -} - -export function unpackPix(dat: Packet, idx: Packet, id = 0) { - dat.pos = 0; - idx.pos = dat.g2(); - - const cropW = idx.g2(); - const cropH = idx.g2(); - - const paletteCount = idx.g1(); - const palette = [0xff00ff]; - for (let i = 0; i < paletteCount - 1; i++) { - palette[i + 1] = idx.g3(); - } - - for (let i = 0; i < id; i++) { - idx.pos += 2; - dat.pos += idx.g2() * idx.g2(); - idx.pos++; - } - - const cropX = idx.g1(); - const cropY = idx.g1(); - const width = idx.g2(); - const height = idx.g2(); - - const img = new Jimp(cropW, cropH, 0xff00ffff).colorType(2); - - const pixelOrder = idx.g1(); - if (pixelOrder === 0) { - for (let i = 0; i < width * height; i++) { - const index = dat.g1(); - if (index === 0) { - continue; - } - - const startX = cropX + (i % width); - const startY = cropY + Math.floor(i / width); - const pos = (startX + startY * cropW) * 4; - - const pixel = palette[index]; - img.bitmap.data[pos] = (pixel >> 16) & 0xff; - img.bitmap.data[pos + 1] = (pixel >> 8) & 0xff; - img.bitmap.data[pos + 2] = pixel & 0xff; - img.bitmap.data[pos + 3] = 0xff; - } - } else if (pixelOrder === 1) { - for (let x = 0; x < width; x++) { - for (let y = 0; y < height; y++) { - const index = dat.g1(); - if (index === 0) { - continue; - } - - const startX = cropX + x; - const startY = cropY + y; - const pos = (startX + startY * cropW) * 4; - - const pixel = palette[index]; - img.bitmap.data[pos] = (pixel >> 16) & 0xff; - img.bitmap.data[pos + 1] = (pixel >> 8) & 0xff; - img.bitmap.data[pos + 2] = pixel & 0xff; - img.bitmap.data[pos + 3] = 0xff; - } - } - } - - return { - img, - cropW, - cropH, - cropX, - cropY, - width, - height, - pixelOrder, - palette - }; -} diff --git a/src/lostcity/util/RandomAccessFile.ts b/src/lostcity/util/RandomAccessFile.ts index d22fe51a09..219d718bf8 100644 --- a/src/lostcity/util/RandomAccessFile.ts +++ b/src/lostcity/util/RandomAccessFile.ts @@ -1,6 +1,6 @@ import fs from 'fs'; -import Packet from '#jagex2/io/Packet.js'; +import Packet from '#jagex/io/Packet.js'; export default class RandomAccessFile { fd: number; diff --git a/src/lostcity/util/WorkerFactory.ts b/src/lostcity/util/WorkerFactory.ts index 758adbccf9..0e1114bc87 100644 --- a/src/lostcity/util/WorkerFactory.ts +++ b/src/lostcity/util/WorkerFactory.ts @@ -1,11 +1,19 @@ -import { Worker as NodeWorker } from 'worker_threads'; +import { Worker as NodeWorker, WorkerOptions } from 'worker_threads'; import Environment from '#lostcity/util/Environment.js'; -export function createWorker(fileName: string): Worker | NodeWorker { +class TsWorker extends NodeWorker { + constructor(filename: string | URL, options: WorkerOptions = {}) { + options.workerData ??= {}; + options.workerData.__ts_worker_filename = filename.toString(); + super(new URL('../../worker.mjs', import.meta.url), options); + } +} + +export function createWorker(filename: string): Worker | NodeWorker { if (Environment.STANDALONE_BUNDLE) { - return new Worker(fileName, {type: 'module'}); + return new Worker(filename, {type: 'module'}); } else { - return new NodeWorker(fileName); + return new TsWorker(filename); } } diff --git a/src/lostcity/web.ts b/src/lostcity/web.ts index f53ae7b1c0..1ee66ad7a7 100644 --- a/src/lostcity/web.ts +++ b/src/lostcity/web.ts @@ -8,6 +8,7 @@ import { CrcBuffer } from '#lostcity/server/CrcTable.js'; import Environment from '#lostcity/util/Environment.js'; import { tryParseInt } from '#lostcity/util/TryParse.js'; +import { register } from 'prom-client'; const MIME_TYPES = new Map(); MIME_TYPES.set('.js', 'application/javascript'); @@ -32,7 +33,17 @@ const web = http.createServer(async (req, res) => { const url = new URL(req.url ?? '', `http://${req.headers.host}`); - if (url.pathname.startsWith('/crc')) { + if (url.pathname.endsWith('.mid')) { + // todo: packing process should spit out files with crc included in the name + // but the server needs to be aware of the crc so it can send the proper length + // so that's been pushed off til later... + + // strip _crc from filename, but keep extension + const filename = url.pathname.substring(1, url.pathname.lastIndexOf('_')) + '.mid'; + res.setHeader('Content-Type', 'application/octet-stream'); + res.writeHead(200); + res.end(await fsp.readFile('data/pack/client/songs/' + filename)); + } else if (url.pathname.startsWith('/crc')) { res.setHeader('Content-Type', 'application/octet-stream'); res.writeHead(200); res.end(CrcBuffer.data); @@ -134,22 +145,24 @@ const web = http.createServer(async (req, res) => { res.setHeader('Content-Type', MIME_TYPES.get(extname(url.pathname ?? '')) ?? 'text/plain'); res.writeHead(200); res.end(await fsp.readFile('public' + url.pathname)); - } else if (url.pathname.endsWith('.mid')) { - // todo: packing process should spit out files with crc included in the name - // but the server needs to be aware of the crc so it can send the proper length - // so that's been pushed off til later... - - // strip _crc from filename, but keep extension - const filename = url.pathname.substring(1, url.pathname.lastIndexOf('_')) + '.mid'; - res.setHeader('Content-Type', 'application/octet-stream'); - res.writeHead(200); - res.end(await fsp.readFile('data/pack/client/songs/' + filename)); } else { res.writeHead(404); res.end(); } } catch (err) { - res.writeHead(500); + res.end(); + } +}); + +const managementWeb = http.createServer(async (req, res) => { + const url = new URL(req.url ?? '', `http://${req.headers.host}`); + + if (url.pathname === '/prometheus') { + res.setHeader('Content-Type', register.contentType); + res.writeHead(200); + res.end(await register.metrics()); + } else { + res.writeHead(404); res.end(); } }); @@ -157,3 +170,7 @@ const web = http.createServer(async (req, res) => { export function startWeb() { web.listen(Environment.WEB_PORT, '0.0.0.0'); } + +export function startManagementWeb() { + managementWeb.listen(Environment.WEB_MANAGEMENT_PORT, '0.0.0.0'); +} diff --git a/src/worker.mjs b/src/worker.mjs new file mode 100644 index 0000000000..3e7d026164 --- /dev/null +++ b/src/worker.mjs @@ -0,0 +1,4 @@ +import { tsImport } from 'tsx/esm/api'; +import { workerData } from 'node:worker_threads'; + +tsImport(workerData.__ts_worker_filename, import.meta.url); diff --git a/tsconfig.json b/tsconfig.json index 21e3d138f2..7230a25f63 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "baseUrl": ".", "paths": { "#3rdparty/*": ["src/3rdparty/*"], - "#jagex2/*": ["src/jagex2/*"], + "#jagex/*": ["src/jagex/*"], "#lostcity/*": ["src/lostcity/*"] }, "types": ["node", "bun-types", "vitest/globals"],