#todo #convert npc limit to map of profession/number and track the owned npc objects #implement npc death handling #todo add sensible spawn mechanic #clean up editing modes with a single action and id combination and change to choose command mayor_script: type: world events: #gives mayor spawn item on player right clicks stone_bricks with wheat: - wait 1t - take iteminhand - drop mayor_placer on player right clicks block with mayor_placer: #check if the player already has a mayor, if not take the spawn item and spawn the mayor - if !: - determine passively cancelled - wait 1t - take iteminhand - create player mayor save:mayor_obj - assignment set script:mayor_assignment npc: #set owner so the player can interact with the npc - adjust owner: - adjust lookclose:true - flag player owned_npcs:->: - determine cancelled - else: - narrate "you already have a mayor<&nl>dismiss your mayor to be able to spawn a new one<&nl>or type /resetmayor to remove your mayor" - determine cancelled # # #mayor interactions # # #create a soldier npc on player clicks mayor_hire_soldier in mayor_menu: #check for hiring cost and soldier limit #todo make both configurable configurable - if >= 64 && < 5: - take wheat quantity:64 - narrate "you hired a soldier" #summon the sentinel npc - create player soldier trait:sentinel save:soldier_obj #increment the amount of soldiers the players has - flag player soldier:++ - flag player owned_npcs_soldier:->: - assignment set script:soldier_assignment npc: #set ownership so the player can interact with the npc - adjust owner: #configure the npc - adjust speed:1.3 - execute as_op "npc select " silent - execute as_op "npc skin --url https://i.imgur.com/nwUVLKc.png" silent - execute as_server "sentinel chaserange 15 --id " - execute as_server "sentinel addtarget monsters --id " - execute as_server "sentinel guard --id " - execute as_server "sentinel attackrate 1 --id " - execute as_server "sentinel realistic --id " - execute as_server "sentinel safeshot true --id " - execute as_server "sentinel speed 1.5 --id " - execute as_server "sentinel respawntime -1 --id " #reopen the menu to refresh the total soldier count - inventory open d:mayor_menu - determine cancelled - else: - if >= 5: - narrate "soldier limit reached for mayor(5)" - determine cancelled - else: - narrate "you dont have enough wheat" - determine cancelled #create a farmer npc on player clicks mayor_hire_farmer in mayor_menu: #check for hiring cost and farmer limit #todo make both configurable - if >= 10 && < 3: - take iron_ingot quantity:10 - narrate "you hired a farmer" - create player farmer save:farmer_obj #increment the amount of farmers the player has - flag player farmer:++ - flag player owned_npcs_farmer:->: - assignment set script:farmer_assignment npc: - flag gather_seeds:true - flag profession:farmer - adjust owner: - adjust speed:1.3 - inventory open d:mayor_menu - determine cancelled - else: - if > 3: - narrate "farmer limit reached for mayor(3)" - determine cancelled - else: - narrate "you dont have enough iron" - determine cancelled on player clicks mayor_hire_builder in mayor_menu: - if >= 10 && < 1: - take stone_bricks quantity:10 - narrate "you hired a builder" - create player builder save:builder_obj #increment the amount of builders the player has - flag player builder:++ - flag player owned_npcs_builder: - flag rate:1s updatequeue:true - flag status:ready - assignment set script:builder_assignment npc: - flag profession:builder - adjust owner: - adjust speed:1.3 - inventory open d:mayor_menu - determine cancelled - else: - if > 1: - narrate "builder limit reached for mayor(1)" - determine cancelled - else: - narrate "you dont have enough stone bricks" - determine cancelled - determine cancelled #remove the npc the player is talking with on player clicks mayor_dismiss in mayor_menu: - narrate "goodbye" - remove - flag player owned_npcs_mayor:! - inventory close - determine cancelled soldier_script: type: world events: # # #soldier interactions # # on player clicks soldier_equip in soldier_menu: #check if theyre not already equiping or setting a path for this npc - if != && != : #enter equipment editor - execute as_op "npc select " silent - execute as_op "npc equip" - narrate "Shift left click with an empty hand to exit" - flag player equiping: - inventory close - determine cancelled - else: - if == : - narrate "already equiping this soldier, shift left click to cancel" - inventory close - determine cancelled - else: - narrate "already setting a path for this soldier, shift left click to cancel" - inventory close - determine cancelled on player clicks soldier_path in soldier_menu: - if != && != : #enter path editor - execute as_op "npc select " silent - execute as_op "npc path" - flag player pathing: - inventory close - determine cancelled - else: - if == : - narrate "already equiping this soldier, shift left click to cancel" - inventory close - determine cancelled - else: - narrate "already setting a path for this soldier, shift left click to cancel" - inventory close - determine cancelled on player clicks soldier_guard in soldier_menu: - execute as_op "sentinel guard --id " - narrate "soldier is now guarding you" - determine cancelled #remove the npc the player is interacting with on player clicks soldier_dismiss in soldier_menu: - narrate "goodbye" - drop - remove - flag player owned_npcs_soldier:<-: - flag player soldier:-- - inventory close - determine cancelled farmer_script: type: world debug: false events: #farmer interactions on player clicks farmer_area in farmer_menu: - if == null - narrate "right click corners with an empty hand to mark the area" - narrate "shift click with an empty hand to cancel" #flag the npc id the player is interacting with for referencing the npc - flag player editing: #set the flag to enable area editing - flag player edit_farm_area:1 - inventory close - determine cancelled on player clicks farmer_inventory in farmer_menu: - determine passively cancelled - inventory close #open the inventory of the npc the player is currently interacting with - inventory open d: on player clicks farmer_seeds in farmer_menu: #toggles whether the npc should collect seeds - flag gather_seeds: #reopens the inventory to update the value - inventory open d:farmer_menu - determine cancelled on player clicks farmer_dismiss in farmer_menu: - narrate "goodbye" - if !]||null> == null: #remove the npcs farm area from the area being checked for crop growth - note ]>]> as:farmcube #remove the farm area itself - note remove as:]> #remove the owner npc id/area from the server flag - flag server farm_cuboids: ]>]> - flag server farm_cuboids: ]> - flag player owned_npcs_farner:<-: - flag player farmer:-- - inventory close - drop - remove - determine cancelled #defining farm area and add to the area being checked for crop growth on player right clicks block with air: - if == 1: - showfake redstone_block duration:2s - narrate "corner set at " - flag player corner1: - flag player edit_farm_area:++ - determine cancelled - else: - if == 2: - showfake redstone_block duration:2s - define new_area:|]> - define area_name:]||null> - define area_index:].replace[farm_area_]||null> #checks if the area is too large - if <[new_area].size.x> > 18: - narrate "error:x axis too long:<[new_area].size.x> blocks, maximum is 18 blocks<&nl> right click to select a new are <&nl> shift left click to cancel" - determine cancelled - stop - if <[new_area].size.z> > 18: - narrate "error:z axis too long:<[new_area].size.z> blocks, maximum is 18 blocks<&nl> right click to select a new are <&nl> shift left click to cancel" - determine cancelled - stop - if <[new_area].size.x.mul_int[<[new_area].size.z>]> > 100: - narrate "error:area is too large:<[new_area].size.x.mul_int[<[new_area].size.z>]> blocks maximum size is 100 blocks<&nl> right click to select a new are <&nl> shift left click to cancel" - determine cancelled - stop #check if the player is overwriting a previous region(if null .length returns 4) - if <[area_name].length> > 4: #removes the old cuboid so it does not intersect with the current area - note ]> as:farmcube #if the new area does not overlap another area replace the old area and add the new one to the area being checked for crop growth - if !]>: - note <[new_area]> as:farm_area_<[area_index]> - note ].at[<[area_index]>]> as:farmcube #path the npc to the area - walk auto_range - narrate "replaced old area with new area" - flag player edit_farm_area:! - flag player editing:! - determine cancelled #if it overlaps restore the previous area to the farm cube and return an error - else: - narrate "Error: this area overlaps another farm area <&nl> Restoring previous area <&nl> right click to select a new are <&nl> shift left click to cancel" #restore the original farm area - note ].at[<[area_index]>]> as:farmcube #restarts the new area creation - flag player edit_farm_area:1 - determine cancelled #when there is no old area create a new one with the next available index - else: - if !]>: #create the farm area and add it to the area being checked for crop growth - note <[new_area]> as:farm_area_ - note ]> as:farmcube #list the npc that owns the area and its name, advance the index by 1 - flag server farm_cuboids:->:/farm_area_ #path to the area - walk auto_range - flag server farm_cuboids_next_index:++ - narrate "farm area created" - flag player edit_farm_area:! - flag player editing:! - determine cancelled - else: - narrate "Error: this area overlaps another farm area <&nl> Restoring previous area <&nl> right click to select a new are <&nl> shift left click to cancel" #restore the original farm area and restart area creation - note ]>]> as:farmcube - flag player edit_farm_area:1 - determine cancelled #if wheat grows to its last stage in the farmcube area(containing all the farm areas) on wheat grows to:7 in:farmcube: #check in which area the wheat has grown(returns farmcube,farm_area) - define npc_tag:]> - wait 1t #always passes unless inventory is full, check every 10 seconds if inventory is no longer full - waituntil rate:10s <[npc_tag].inventory.can_fit[wheat]> && <[npc_tag].inventory.can_fit[wheat_seeds].quantity[3]>: - if <[npc_tag].flag[timeout]||null> == null && !<[npc_tag].flag[break_queue_finished]>: - run task_timeout def:<[npc_tag]>|10|1s #wait for the timeout or breakqueue to finish - waituntil rate:40t <[npc_tag].flag[break_queue_finished].get[1]||[npc_tag].flag[timeout]> - if <[npc_tag].flag[break_queue_finished].get[1]>: - flag <[npc_tag]> break_queue_finished:false - flag <[npc_tag]> timeout:! #flag all grown wheat for breaking - flag <[npc_tag]> targets: - foreach <[npc_tag].flag[targets].get[1]>: - if <[npc_tag].inventory.can_fit[wheat]> && <[npc_tag].inventory.can_fit[wheat_seeds].quantity[3]>: #path the npc to the wheat - ~walk <[npc_tag]> <[value]> auto_range #remove the current target - flag <[npc_tag]> targets[1]:<- - if <[value].material.age> == 7: #break wheat - animate <[npc_tag]> animation:ARM_SWING - playsound <[value]> sound:BLOCK_CROP_BREAK volume:5 - modifyblock <[value]> air #simmulate the wheat drops and replant if seeds are available - give wheat to:<[npc_tag].inventory> - if <[npc_tag].flag[gather_seeds]>: - give wheat_seeds quantity: to:<[npc_tag].inventory> - else: - give wheat_seeds to:<[npc_tag].inventory> - if <[npc_tag].inventory.quantity.material[wheat_seeds]> > 0: - wait 5t - animate <[npc_tag]> animation:ARM_SWING - playsound <[value]> sound:ITEM_CROP_PLANT volume:5 - modifyblock <[value]> wheat - take wheat_seeds from:<[npc_tag].inventory> - else: - flag <[npc_tag]> targets:! - flag <[npc_tag]> break_queue_finished:true #end world_script: type: world debug: false events: #world events #create area/owner list, index of next available spot in the list and the area that is checked for crop growth, if they dont exist on world loads: #replace with config file and material file - flag server buildinglist: - flag server hovel_material_list: - flag server farm_material_list - flag server town_material_list - if == null: - note as:farmcube - if == null: - flag server farm_cuboids:server/farmcube - if || null> == null: - flag server farm_cuboids_next_index:2 - if == null: - note as:buildingcube - if == null: - flag server building_cuboids:server/buildingcube - if || null> == null: - flag server building_cuboids_next_index:2 #set the amount of npcs to 0 so the menu shows it properly on player joins: - if : - flag player new:false - flag player farmer:0 - flag player builder:0 - flag player soldier:0 - flag player building_index:1 #on npc death: #todo FIX #- flag : #cancelling editing modes on player left clicks with air: - if : - if : - execute as_op "npc equip" - flag player equiping:! - determine cancelled - else: - if : - execute as_op "npc path" - execute as_op "sentinel guard" - narrate "stopped waypoint assignment" - flag player pathing:! - determine cancelled - else: - if : - flag player edit_farm_area:! - flag player editing:! - narrate "cancelled area creation" - determine cancelled - else: - if : - flag player builder_pickup:! - narrate "cancelled pickup point assignment" - determine cancelled builder_script: type: world events: #menu interactions on player clicks builder_available_buildings in builder_menu_main: - inventory open d:builder_menu_buildings - determine cancelled on player clicks builder_inventory in builder_menu_main: - inventory open d: - determine cancelled on player clicks builder_pickup_point in builder_menu_main: - flag player builder_pickup: - narrate "right click a chest to assign the resource pickup point" - determine cancelled on player right clicks chest with air: - if : - flag pickup_point: - narrate "pickup point assigned" - flag player builder_pickup:! - determine cancelled #buildings menu on player clicks building_farm in builder_menu_buildings: - define structure:farm - give - determine cancelled on player clicks building_hovel in builder_menu_buildings: - define structure:hovel - give - determine cancelled on player clicks building_town_hall in builder_menu_buildings: - define structure:town_hall - give - determine cancelled on player clicks builder_status in builder_menu_main: - if == waiting: - flag update_queue:true - determine cancelled on player clicks builder_dismiss in builder_menu_main: - narrate "goodbye" - drop - remove - flag player builder:-- - flag player owner_npcs_builder:<-: - inventory close - determine cancelled #building script on player right clicks block with builder_schematic: - if != ready: - narrate "this builder is currently building a <&nl>get another builder to construct this building or wait for this one to finish construction" - determine cancelled #if the player already placed a preview on this block - if == && == : - define new_area:|].width>,].height>,].length>]>]> - if ]>: - narrate "error: area intersects another buildings area" - determine cancelled #when no intersection with other buildings is found - else: #load a copy of the schematic if its not loaded already - if !_]||false>: - ~schematic load name:_ filename: - waituntil _]> #check builder inventory for needed materials - flag has_materials:true - foreach _material_list].unescaped.as_list>: - define material_mask:<[value].unescaped.as_list.get_sub_items[1].get[1]> - define material_quantity:<[value].unescaped.as_list.get_sub_items[3].get[1]> - if ]> < <[material_quantity]> && : - flag has_materials:false - if !: - if : - ~walk auto_range #dump inventory if possible - if ]||true>: - inventory add origin: d: - inventory clear d: - run task_timeout def:|120|1s - while !: - waituntil rate:1s || - if : - flag status:ready - determine cancelled - flag has_materials:true - flag update_queue:false - foreach _material_list].unescaped.as_list>: - define material_mask:<[value].unescaped.as_list.get_sub_items[1].get[1]> - define material_quantity:<[value].unescaped.as_list.get_sub_items[3].get[1]> - if ]> < <[material_quantity]>: - define needed_quantity:<[material_quantity].sub[]>]> - if ]> >= <[needed_quantity]>: - if ].quantity[<[needed_quantity]>]>: - take <[material_mask]> quantity:<[needed_quantity]> from: - give <[material_mask]> quantity:<[needed_quantity]> to: - else: - narrate "builder inventory and pickup point are too full" - flag status:waiting - flag has_materials:false - else: - narrate "insufficient materials in pick up point <&nl>need <[needed_quantity]> <[material_mask].as_material.name>" - flag status:waiting - flag required_quantity:<[needed_quantity].sub[]>]> - flag required_material - flag has_materials:false - flag update_queue:true - else: - narrate "give the builder the necesarry items or assign a pickup point" - determine cancelled #materials are available, start construction - wait 1t - flag status:building - define structure: - take scriptname:builder_schematic - narrate "construction started" - choose : - case north: - ~schematic rotate angle:180 name:_ - ~run task_rotation_map def:|_ - ~run task_convert def:|_ - ~run task_rotate_blocks def:|_|180 - case east: - flag converted:false - narrate "flag set" - ~schematic rotate angle:90 name:_ - ~run task_rotation_map def:|_ - ~run task_convert def:|_ - waituntil rate:1s - ~run task_rotate_blocks def:|_|90 - case west: - ~schematic rotate angle:270 name:_ - ~run task_rotation_map def:|_ - ~run task_convert def:|_ - ~run task_rotate_blocks def:|_|270 - case south: #buildings face north so no rotation required as the player is north of the building site - ~run task_convert def:|_ - flag status:ready #add clear flags at end of building - stop - ~run task_clear_area def:|_| - foreach _material_list].unescaped.as_list>: - define material_mask:<[value].unescaped.as_list.get_sub_items[1].get[1]> - define material_sound:<[value].unescaped.as_list.get_sub_items[2].get[1]> - ~run task_build def:|_||]>|<[material_sound]> - note <[new_area]> as:_building_ - note ]> as:buildingcube - flag server building_cuboids:->:/_building_ - flag building:! - flag status:ready - schematic unload name:_ #else place a preview - else: - if !]||false>: - ~schematic load name: - waituntil ]> - if !_]||false>: - ~schematic load name:_ filename: - waituntil _]> - choose : - case north: - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel" - ~schematic rotate angle:180 name:_ - schematic paste fake_to: fake_duration:5s name:_ ].width.div_int[2]>,0,].length.sub[1]>]> - flag building: - flag building_location: - flag origin:].width.div_int[2]>,0,].length.sub[1]>]> - flag building_facing:north - schematic unload name:_ - stop - case east: - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel" - ~schematic rotate angle:90 name:_ - schematic paste fake_to: fake_duration:5s name:_ ].length.div_int[2]>]> - flag building: - flag building_location: - flag origin:].length.div_int[2]>]> - flag building_facing:east - schematic unload name:_ - stop - case south: - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel" - schematic paste fake_to: fake_duration:5s name:_ ].width.div_int[2]>,0,0]> - flag building: - flag building_location: - flag origin:].width.div_int[2]>,0,0]> - flag building_facing:south - schematic unload name:_ - stop - case west: - narrate "preview placed, right click this location again to confirm this building location <&nl>shift left click to cancel" - ~schematic rotate angle:270 name:_ - schematic paste fake_to: fake_duration:5s name:_ ].width.sub[1]>,0,].length.div_int[2]>]> - flag building: - flag building_location: - flag origin:].width.sub[1]>,0,].length.div_int[2]>]> - flag building_facing:west - schematic unload name:_ - stop - default: - narrate "face north east south or west to place a preview" - flag building_location:! - schematic unload name:_ #mayor interaction scripts mayor_assignment: type: assignment actions: on assignment: - trigger name:click state:true interact scripts: - mayor_interact mayor_interact: type: interact steps: 1: click trigger: script: #open the menu and flag the npc as the one being interacted with if the player is the owner - if == : - flag player last_interaction_id: - inventory open d:mayor_menu - else: - narrate "this mayor does not obey you" mayor_menu: type: inventory inventory: chest title: Mayor size: 9 slots: - "[mayor_dismiss] [] [] [] [mayor_hire_farmer] [mayor_hire_soldier] [mayor_hire_builder] [] []" #menu items mayor_placer: type: item material: bat_spawn_egg display name: Mayor spawner mayor_hire_soldier: type: item material: stone_sword display name: Hire a soldier for 64 Wheat (/5) mayor_hire_farmer: type: item material: stone_hoe display name: Hire a farmer for 10 iron ingots (/3) mayor_hire_builder: type: item material: brick display name: Hire a builder for 10 stone bricks (/1) mayor_dismiss: type: item material: barrier display name: Dismiss the mayor #soldier interaction scripts soldier_assignment: type: assignment actions: on assignment: - trigger name:click state:true interact scripts: - soldier_interact soldier_interact: type: interact steps: 1: click trigger: script: #open the menu and flag the npc as the one being interacted with if the player is the owner - if == : - flag player last_interaction_id: - inventory open d:soldier_menu - else: - narrate "this soldier does not obey you" soldier_menu: type: inventory inventory: chest title: Soldier size: 9 slots: - "[soldier_dismiss] [] [] [soldier_path] [soldier_guard] [soldier_equip] [] [] []" #menu items soldier_path: type: item material: stick display name: set the patrol path soldier_guard: type: item material: shield display name: guard the player soldier_equip: type: item material: iron_chestplate display name: equip your soldier soldier_dismiss: type: item material: barrier display name: Dismiss this soldier #farmer interaction scripts farmer_assignment: type: assignment actions: on assignment: - trigger name:click state:true interact scripts: - farmer_interact farmer_interact: type: interact steps: 1: click trigger: script: #open the menu and flag the npc as the one being interacted with if the player is the owner - if == : - flag player last_interaction_id: - inventory open d:farmer_menu - else: - narrate "this farmer does not obey you" farmer_menu: type: inventory inventory: chest title: Farmer size: 9 slots: - "[farmer_dismiss] [] [] [farmer_area] [farmer_seeds] [farmer_inventory] [] [] []" #menu items farmer_area: type: item material: iron_hoe display name: set farming area farmer_seeds: type: item material: wheat_seeds display name: toggle seed collection (currently ) farmer_inventory: type: item material: chest display name: farmer inventory farmer_deposit: type: item material: leather_boots display name: Change deposit location farmer_interval: type: item material: clock display name: Change deposit interval farmer_dismiss: type: item material: barrier display name: dismiss farmer #builder interaction scripts builder_assignment: type: assignment actions: on assignment: - trigger name:click state:true interact scripts: - builder_interact builder_interact: type: interact steps: 1: click trigger: script: #open the menu and flag the npc as the one being interacted with if the player is the owner - if == : - flag player last_interaction_id: - inventory open d:builder_menu_main - else: - narrate "this builder does not obey you" builder_menu_main: type: inventory inventory: chest title: builder size: 9 slots: - "[builder_dismiss] [] [builder_status] [builder_available_buildings] [builder_inventory] [builder_pickup_point] [] [] []" builder_menu_buildings: type: inventory title: available buildings size: 27 slots: - "[] [] [building_farm] [building_hovel] [building_town_hall] [] [] [] [] " - "[] [] [] [] [] [] [] [] [] " - "[] [] [] [] [] [] [] [] [] " #buildings building_farm: type: item material: wheat display name: farm building_hovel: type: item material: hay_block display name: basic house building_town_hall: type: item material: iron_helmet display name: town hall #menu items builder_schematic: type: item material: paper mechanisms: nbt: structure/<[structure]>|builder/ display name: building schematic lore: - "<[structure]>" builder_pickup_point: type: item material: crafting_table display name: designate resource pick up point builder_available_buildings: type: item material: bricks display name: order a new project builder_inventory: type: item material: chest display name: builder inventory builder_status: type: item material: |material_name]> display name: |item_name]> builder_dismiss: type: item material: barrier display name: dismiss builder builder_status_procedure: type: procedure definitions: status|return_type script: - if <[return_type]> == material_name: - choose <[status]>: - case ready: - determine green_stained_glass_pane - case building: - determine orange_stained_glass_pane - case collecting: - determine lime_stained_glass_pane - case waiting: - determine red_stained_glass_pane - else: - if <[return_type]> == item_name: - choose <[status]>: - case ready: - determine "waiting for a new project" - case building: - determine "constructing a " - case collecting: - determine "collecting resources for construction" - case waiting: - determine "waiting for items" task_timeout: type: task debug: false definitions: npc_tag|time|interval script: - flag <[npc_tag]> timeout:false - while <[time]> > 0: - define time:<[time].sub[1]> - wait <[interval]> - if <[npc_tag].flag[timeout]||null> != null: - flag <[npc_tag]> timeout:true #builder tasks task_convert: type: task definitions: builder_obj|passed_schematic debug: false script: #create a matrix containting the blocks from the schematic at their relative locations in the schematic # x y and z in the matrix are 1 higher since the schematic starts at 0,0,0 and the matrix starts at index 1,1,1 - define x:0 - define y:0 - define z:0 - while <[y]> < ].height>: - while <[x]> < ].width>: - wait 1t - while <[z]> < ].length>: #set the block in the row - flag <[builder_obj]> <[passed_schematic]>[<[z].add[1]>]:].block[<[x]>,<[y]>,<[z]>]> - define z:<[z].add[1]> #add the row to the plane - flag <[builder_obj]> <[passed_schematic]>_square[<[x].add[1]>]:<[builder_obj].flag[<[passed_schematic]>].escaped> - define x:<[x].add[1]> - define z:0 #add the plane to the square - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_square].escaped> - define y:<[y].add[1]> - define x:0 - flag <[builder_obj]> converted:true task_rotation_map: type: task debug: false definitions: builder_obj|passed_schematic script: #create a matrix of rotatable blocks - define x:0 - define y:0 - define z:0 - while <[y]> < ].height>: - while <[x]> < ].width>: - while <[z]> < ].length>: - if ].block[<[x]>,<[y]>,<[z]>].is_directional>: - flag <[builder_obj]> <[passed_schematic]>_rotation[<[z].add[1]>]:].block[<[x]>,<[y]>,<[z]>].direction> - else: - flag <[builder_obj]> <[passed_schematic]>_rotation[<[z].add[1]>]:false - define z:<[z].add[1]> #add the row to the plane - flag <[builder_obj]> <[passed_schematic]>_rotation_square[<[x].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_rotation].escaped> - define x:<[x].add[1]> - define z:0 #add the plane to the square - flag <[builder_obj]> <[passed_schematic]>_rotation_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_rotation_square].escaped> - define y:<[y].add[1]> - define x:0 task_rotate_blocks: type: task debug: true definitions: builder_obj|passed_schematic|rotation script: - define x:0 - define y:0 - define z:0 #set the rotation - while <[y]> < ].height>: - while <[x]> < ].width>: - wait 1t - while <[z]> < ].length>: #define the current block rotation - define current_block_rotation:<[builder_obj].flag[<[passed_schematic]>_rotation_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]> - define square_plane:[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list - define current_material:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]> - if <[current_block_rotation]> != false: - choose <[current_block_rotation]>: #2 DIRECTIONAL MATERIALS SUCH AS LOGS - case X: - if <[rotation]> == 90 || <[rotation]> == 270: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=Z]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - case Z: - if <[rotation]> == 90 || <[rotation]> == 270: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=X]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> #4 DIRECTIONAL MATERIALS SUCH AS LADDERS - case NORTH: - if <[rotation]> == 90: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=WEST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 180: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=SOUTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 270: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=EAST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - case EAST: - if <[rotation]> == 90: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=NORTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 180: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=WEST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 270: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=SOTUH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - case SOUTH: - if <[rotation]> == 90: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=EAST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 180: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=NORTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 270: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=WEST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - case WEST: - if <[rotation]> == 90: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=SOUTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 180: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=EAST]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - if <[rotation]> == 270: - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[square_plane].set[<[square_plane].get[<[x].add[1]>].unescaped.as_list.set[<[current_material].with[direction=NORTH]>].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> - define z:<[z].add[1]> - define x:<[x].add[1]> - define z:0 - define y:<[y].add[1]> - define x:0 task_build: type: task debug: false definitions: builder_obj|passed_schematic|origin|material_mask|material_sound script: - define x:0 - define y:0 - define z:0 # get material value at x y z <[builder_obj].flag[<[schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]> # set material value at x y z - flag <[builder_obj]> <[schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[[schematic]_cubic].get[<[y].add[1]>].as_list.unescaped.set[<[schematic]_cubic.get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[].at[<[z].add[1]>]>].at[<[x].add[1]>]> - while <[y]> < ].height>: - while <[x]> < ].width>: - wait 1t - while <[z]> < ].length>: #if the material in the schematic matrix matches the mask and the space is empty - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>].as_material.name> == <[material_mask].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air: - define current_material:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>]> - if <[builder_obj].inventory.contains.material[<[current_material]>]>: - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range radius:1 - wait 1t #walk to the location and place the block - take <[current_material].name> from:<[builder_obj].inventory> - modifyblock <[origin].add[<[x]>,<[y]>,<[z]>]> <[current_material]> - animate <[builder_obj]> animation:ARM_SWING - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]> #set the material in the schematic matrix to air - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> #place cooldown - wait 10t #check adjacent blocks in the schematic matrix for the same material - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x]>|<[y]>|<[z]> - define z:<[z].add[1]> - define x:<[x].add[1]> - define z:0 - define y:<[y].add[1]> - define x:0 task_check_adjacent: type: task definitions: builder_obj|passed_schematic|origin|current_material|material_sound|x|y|z debug: fasle script: #adjacent blocks if they match the material of the last placed block #only the next x y and z are checked, all previous ones have already been checked by the build task #fix <> in .get[] tag - if <[x].add[2]> <= ].width>: #check next x for current material and check if the space is empty - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[2]>].unescaped.as_list.get[<[z].add[1]>].as_material.name> == <[current_material].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air: - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range radius:1 #replace the block and add effects - modifyblock <[origin].add[<[x].add[1]>,<[y]>,<[z]>]> <[current_material]> - animate <[builder_obj]> animation:ARM_SWING - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]> #set the block to air in the schematic matrix - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> #break cooldown - wait 10t - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x].add[1]>|<[y]>|<[z]> #check next z for current material and check if the space is empty - if <[z].add[2]> <= ].length>: - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[2]>].as_material.name> == <[current_material].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air: - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range #replace the block and add effects - modifyblock <[origin].add[<[x]>,<[y]>,<[z].add[1]>]> <[current_material]> - animate <[builder_obj]> animation:ARM_SWING - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]> #set the block to air in the schematic matrix - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[1]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[1]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> #break cooldown - wait 10t - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x]>|<[y]>|<[z].add[1]> #check next y for current material and check if the space is empty - if <[y].add[2]> <= ].length>: - if <[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[2]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.get[<[z].add[1]>].as_material.name> == <[current_material].name> && <[origin].add[<[x]>,<[y]>,<[z]>].material.name> == air: - ~walk <[builder_obj]> <[origin].add[<[x]>,<[y]>,<[z]>]> auto_range #replace the block and add effects - modifyblock <[origin].add[<[x]>,<[y].add[1]>,<[z]>]> <[current_material]> - animate <[builder_obj]> animation:ARM_SWING - playsound <[origin].add[<[x]>,<[y]>,<[z]>]> sound:<[material_sound]> #set the block to air in the schematic matrix - flag <[builder_obj]> <[passed_schematic]>_cubic[<[y].add[2]>]:<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[2]>].unescaped.as_list.set[<[builder_obj].flag[<[passed_schematic]>_cubic].get[<[y].add[2]>].unescaped.as_list.get[<[x].add[1]>].unescaped.as_list.set[].at[<[z].add[1]>].escaped>].at[<[x].add[1]>].escaped> #break cooldown - wait 10t - ~run task_check_adjacent def:<[builder_obj]>|<[passed_schematic]>|<[origin]>|<[current_material]>|<[material_sound]>|<[x]>|<[y].add[1]>|<[z]> #commands task_clear_area: type: task debug: false definitions: builder_obj|current_schematic|origin script: #clear the area for a schematic, top to bottom - define x:0 - define y:].height.sub[1]> - define z:0 - while <[y]> >= 0: - while <[x]> < ].width>: - wait 1t - while <[z]> < ].length>: #check if there is something to remove thats not bedrock - if ].add[<[x]>,<[y]>,<[z]>].material> != && ].add[<[x]>,<[y]>,<[z]>].material> != : #move to the block and break it, gain the item if its breakable with an iron pickaxe - ~walk ]> ].add[<[x]>,<[y]>,<[z]>]> auto_range - give ].add[<[x]>,<[y]>,<[z]>].drops[iron_pickaxe]> to:].inventory> - modifyblock ].add[<[x]>,<[y]>,<[z]>]> - animate <[builder_obj]> animation:ARM_SWING #break cooldown - wait 10t - define z:<[z].add[1]> - define x:<[x].add[1]> - define z:0 - define y:<[y].sub[1]> - define x:0 reset_command: