diff --git a/compiler.rkt b/compiler.rkt index 3972821..750b4fa 100644 --- a/compiler.rkt +++ b/compiler.rkt @@ -37,6 +37,15 @@ "minetest.register_craft(~a)\n\n" (compile-v (asset->hash b))))))) +(define (compile-entity b) + (special-compile + (thunk + (++ "-- My entity is named " (asset-name b) "\n" + (format + "mobs:register_mob(~s, ~a)\n\n" + (asset-name b) + (compile-v (asset->hash b))))))) + (define (compile-lua-def b) (special-compile @@ -76,6 +85,8 @@ (mod-struct-blocks m)) (map compile-recipe (mod-struct-recipes m)) + (map compile-entity + (mod-struct-entities m)) ))) #t) diff --git a/core.rkt b/core.rkt index ab5cf9b..13716e2 100644 --- a/core.rkt +++ b/core.rkt @@ -7,6 +7,8 @@ (provide mod-struct-blocks) (provide mod-struct-items) (provide mod-struct-recipes) +(provide mod-struct-lua-defs) +(provide mod-struct-entities) (provide MINETEST_PATH) (provide path-for) (provide asset-name) @@ -24,6 +26,8 @@ (provide compile-asset-description) +(provide anonymous-compileable-image) + (provide lua-file-for) (provide path-for) @@ -35,7 +39,7 @@ (provide mod-struct) (provide mod-struct?) (provide mod-struct-name) -(provide mod-struct-lua-defs) + (provide set-my-mod!) (provide my-mod) @@ -43,12 +47,15 @@ (provide add-block) (provide add-recipe) (provide add-lua-def) +(provide add-entity) (provide list_) (provide add-behaviour-to) (provide add-behaviour) +(provide variableify) + (require (for-syntax racket/syntax)) ;UTIL @@ -79,7 +86,7 @@ (struct special-compile (f)) -(struct mod-struct (name items blocks recipes lua-defs) ) +(struct mod-struct (name items blocks recipes entities lua-defs) ) (struct asset-struct (name description more mod) #:transparent) @@ -114,6 +121,7 @@ (replace-in-list (mod-struct-items m) t1 t2) (replace-in-list (mod-struct-blocks m) t1 t2) (replace-in-list (mod-struct-recipes m) t1 t2) + (replace-in-list (mod-struct-entities m) t1 t2) (replace-in-list (mod-struct-lua-defs m) t1 t2))) (define (replace-in-list l t1 t2) @@ -125,7 +133,7 @@ (define (add-to-more a kv) (let ([new-more (hash-set (asset-struct-more a) - (string->symbol (first kv)) + (string->symbol (variableify (first kv))) (second kv))]) (struct-copy asset-struct a [more new-more]))) @@ -134,10 +142,10 @@ (provide default-mod) (define default-mod - (mod-struct "default" '() '() '() '())) + (mod-struct "default" '() '() '() '() '())) (define my-mod - (mod-struct "my_racket_mod" '() '() '() '())) + (mod-struct "my_racket_mod" '() '() '() '() '())) (define (set-my-mod! m) (set! my-mod m)) @@ -159,14 +167,20 @@ (struct-copy mod-struct m [lua-defs (cons i (mod-struct-lua-defs m))])) +(define (add-entity m i) + (struct-copy mod-struct m + [entities (cons i (mod-struct-entities m))])) (define (variableify s) (string-downcase (string-replace - s - " " + (string-replace + s + " " + "_") + "-" "_"))) (define (asset-short-name m a) @@ -198,9 +212,12 @@ (define/contract (compile-v v) (-> any/c any/c) - (cond [(special-compile? v) ((special-compile-f v))] + (cond [(asset-struct? v) (format "~s" (asset-name v))] + [(image? v) (compile-v (anonymous-compileable-image v))] + [(special-compile? v) ((special-compile-f v))] [(string? v) (format "\"~a\"" v)] [(number? v) (number->string v)] + [(boolean? v) (if v "true" "false")] [(hash? v) (compile-hash v)] [(list? v) (++ "{" (string-join (map compile-v v) ",") "}")] [else @@ -241,6 +258,11 @@ (format "~s" (++ id ".png")) ))) +(define (anonymous-compileable-image img) + (compileable-image my-mod (random-file-id) img)) + +(define (random-file-id) + (number->string (random 1000000))) (define/contract (export-image-to-file m id img) (-> mod-struct? string? image? boolean?) diff --git a/entities.rkt b/entities.rkt new file mode 100644 index 0000000..a332b31 --- /dev/null +++ b/entities.rkt @@ -0,0 +1,119 @@ +#lang racket + + +(provide define-entity) + +(require (for-syntax racket/syntax)) + +(require 2htdp/image) +(require "lua.rkt") +(require "mob-api-raw.rkt") +(require "core.rkt") + +;;Injects a ton of code by PilzAdam into the user's mod. Allowing for calls to register_mob +;; Instead of register_entity. +(define-lua-raw mob-api mob-api-raw) + + +;minetest.register_node("mymod:diamond", { +; description = "Alien Diamond", +; tiles = {"mymod_diamond.png"}, +; is_ground_content = true, +; groups = {cracky=3, stone=1} +;}) + +(define (entity-struct name desc tiles m) + (asset-struct name desc + (make-immutable-hash + (list + (cons 'type "animal") + (cons 'hp_max 1) + (cons 'visual "cube") + (cons 'physical #t) + (cons 'walk_velocity 1) + (cons 'run_velocity 1) + (cons 'visual_size + (make-hash + (list + (cons 'x 1) + (cons 'y 1)))) + + ;;For this one, we also need to make sure the length = 6, + ;; So we pad by duplicating the first entry... + (cons 'textures + (map anonymous-compileable-image + (pad tiles 6))))) + m)) + +(define (pad tiles len) + (if (= len (length tiles)) + tiles + (pad (cons (first tiles) tiles) len))) + + +(define-syntax (define-entity stx) + (syntax-case stx () + [(_ id desc tiles ... ) + (with-syntax* ([item-id (format-id stx "~a" #'id)] + [name (symbol->string (format-symbol "~a" #'id))]) + #`(begin + (define id (entity-struct name desc (list_ tiles ...) my-mod)) + (set-my-mod! (add-entity my-mod id))) + )])) + + + + + + + + + +#;( +;;Makes a stub -- e.g. for default:stone +(define (default-block id) + (entity-struct (++ "" id) + (++ "The default " id) + '() + default-mod)) + +(define-syntax (define-default-block stx) + (syntax-case stx () + [(_ x ) + (with-syntax* ([name (symbol->string (format-symbol "~a" #'x))]) + #`(begin + (define x (default-block name) ) + (provide x) + ) ) ])) + +(define-syntax (define-default-blocks stx) + (syntax-case stx () + [(_ x ... ) + #`(begin + (define-default-block x ) ... + ) ])) + +(define-default-blocks + cobble + stonebrick + stone_block + mossycobble + desert_stone + desert_cobble + desert_stonebrick + desert_stone_block + sandstone + sandstonebrick + sandstone_block + desert_sandstone + desert_sandstone_brick + desert_sandstone_block + silver_sandstone + silver_sandstone_brick + silver_sandstone_block + obsidian + obsidianbrick + obsidian_block) +) + + diff --git a/example-mod.rkt b/example-mod.rkt index 66b8269..e325e2c 100644 --- a/example-mod.rkt +++ b/example-mod.rkt @@ -290,34 +290,18 @@ 0 -1 -1 4 1 #"\0" 0 -1 1 #"\0" 1.0 0 92 -1 -1 -1 -1 -1 0 0 0 0 0 1 0.0 0.0 0.0 0.0 0.0 0.0 0 0 0 255 -255 0 -1 -1 0 571 0 28 3 12 #"#lang racket" +255 0 -1 -1 0 711 0 28 3 12 #"#lang racket" 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 17 3 14 #";Housecleaning" 0 0 24 29 1 #"\n" -0 0 17 3 62 -#";TODO: Helpful compiler messages: don't allow same name things" -0 0 24 29 1 #"\n" 0 0 17 3 46 #";TODO: Do #lang? (What's a marketable name??)" 0 0 24 29 1 #"\n" -0 0 24 29 1 #"\n" -0 0 17 3 33 #";Features - To redo curriculum..." -0 0 24 29 1 #"\n" -0 0 17 3 49 #";TODO: Support callback functions on the above..." -0 0 24 29 1 #"\n" -0 0 17 3 48 #"; Added minimal support for function defs." -0 0 24 29 1 #"\n" -0 0 17 3 54 #"; Now, how do we attach on_punch=(lua-call foo)?" -0 0 24 29 1 #"\n" 0 0 17 3 73 ( - #"; Optional things in macro? Or a second pass? (add-attrib" - #"ute?)" + #"; Put on github as a module, so we can easily install it in drr" + #"acket" ) 0 0 24 29 1 #"\n" -0 0 17 3 24 #";TODO: Support particles" -0 0 24 29 1 #"\n" -0 0 24 29 1 #"\n" -0 0 17 3 19 #";TODO: Support mobs" 0 0 24 29 1 #"\n" 0 0 17 3 55 #";TODO: Support building. (Functional API, not drones.)" 0 0 24 29 1 #"\n" @@ -330,9 +314,6 @@ #"; Racket to generate assets. Lua for in-game scripting..." 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" -0 0 17 3 29 #";TODO: Active block modifiers" -0 0 24 29 1 #"\n" -0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 24 3 1 #"(" 0 0 15 3 7 #"require" @@ -368,6 +349,12 @@ 0 0 24 3 1 #"(" 0 0 15 3 7 #"require" 0 0 24 3 1 #" " +0 0 19 3 14 #"\"entities.rkt\"" +0 0 24 3 1 #")" +0 0 24 29 1 #"\n" +0 0 24 3 1 #"(" +0 0 15 3 7 #"require" +0 0 24 3 1 #" " 0 0 19 3 9 #"\"lua.rkt\"" 0 0 24 3 3 #") " 0 0 24 29 1 #"\n" @@ -579,7 +566,9 @@ 0 0 24 3 1 #"(" 0 0 15 3 11 #"define-item" 0 0 24 3 1 #" " -0 0 14 3 13 #"zelda_thing_1" +0 0 14 3 6 #"zelda-" +0 0 14 3 6 #"thing-" +0 0 14 3 1 #"1" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 18 #"\"Zelda Thingy Red\"" @@ -600,7 +589,9 @@ 0 0 24 3 1 #"(" 0 0 15 3 11 #"define-item" 0 0 24 3 1 #" " -0 0 14 3 13 #"zelda_thing_2" +0 0 14 3 6 #"zelda-" +0 0 14 3 6 #"thing-" +0 0 14 3 1 #"2" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 19 #"\"Zelda Thingy Blue\"" @@ -621,7 +612,10 @@ 0 0 24 3 1 #"(" 0 0 15 3 11 #"define-item" 0 0 24 3 1 #" " -0 0 14 3 13 #"zelda_thing_3" +0 0 14 3 5 #"zelda" +0 0 14 3 1 #"-" +0 0 14 3 6 #"thing-" +0 0 14 3 1 #"3" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 20 #"\"Zelda Thingy Green\"" @@ -642,7 +636,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 11 #"define-item" 0 0 24 3 1 #" " -0 0 14 3 13 #"diamond_green" +0 0 14 3 8 #"diamond-" +0 0 14 3 5 #"green" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 15 #"\"Green Diamond\"" @@ -657,7 +652,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 11 #"define-item" 0 0 24 3 1 #" " -0 0 14 3 11 #"diamond_red" +0 0 14 3 8 #"diamond-" +0 0 14 3 3 #"red" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 13 #"\"Red Diamond\"" @@ -673,7 +669,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 11 #"define-item" 0 0 24 3 1 #" " -0 0 14 3 12 #"diamond_blue" +0 0 14 3 8 #"diamond-" +0 0 14 3 4 #"blue" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 14 #"\"Blue Diamond\"" @@ -690,7 +687,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 12 #"define-block" 0 0 24 3 1 #" " -0 0 14 3 9 #"red_block" +0 0 14 3 4 #"red-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 11 #"\"Red Block\"" @@ -705,7 +703,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 12 #"define-block" 0 0 24 3 1 #" " -0 0 14 3 11 #"green_block" +0 0 14 3 6 #"green-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 13 #"\"Green Block\"" @@ -720,7 +719,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 12 #"define-block" 0 0 24 3 1 #" " -0 0 14 3 10 #"blue_block" +0 0 14 3 5 #"blue-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 12 #"\"Blue Block\"" @@ -735,7 +735,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 12 #"define-block" 0 0 24 3 1 #" " -0 0 14 3 13 #"magenta_block" +0 0 14 3 8 #"magenta-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 15 #"\"Magenta Block\"" @@ -750,7 +751,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 12 #"define-block" 0 0 24 3 1 #" " -0 0 14 3 10 #"cyan_block" +0 0 14 3 5 #"cyan-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 12 #"\"Cyan Block\"" @@ -765,7 +767,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 12 #"define-block" 0 0 24 3 1 #" " -0 0 14 3 12 #"purple_block" +0 0 14 3 7 #"purple-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 14 #"\"Purple Block\"" @@ -782,7 +785,8 @@ 0 0 24 3 1 #"(" 0 0 15 3 12 #"define-block" 0 0 24 3 1 #" " -0 0 14 3 12 #"yellow_block" +0 0 14 3 7 #"yellow-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 19 3 14 #"\"Yellow Block\"" @@ -799,35 +803,41 @@ 0 0 24 3 1 #"(" 0 0 15 3 13 #"define-recipe" 0 0 24 3 1 #" " -0 0 14 3 10 #"my_recipe1" +0 0 14 3 3 #"my-" +0 0 14 3 7 #"recipe1" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 14 3 5 #"make:" 0 0 24 3 1 #" " 0 0 21 3 1 #"1" 0 0 24 3 1 #" " -0 0 14 3 11 #"green_block" +0 0 14 3 6 #"green-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 14 3 5 #"from:" 0 0 24 3 1 #" " -0 0 14 3 12 #"yellow_block" +0 0 14 3 7 #"yellow-" +0 0 14 3 5 #"block" 0 0 24 3 1 #" " -0 0 14 3 10 #"blue_block" +0 0 14 3 5 #"blue-" +0 0 14 3 5 #"block" 0 0 24 3 1 #")" 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 24 3 1 #"(" 0 0 15 3 13 #"define-recipe" 0 0 24 3 1 #" " -0 0 14 3 10 #"my_recipe2" +0 0 14 3 3 #"my-" +0 0 14 3 7 #"recipe2" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 14 3 5 #"make:" 0 0 24 3 1 #" " 0 0 21 3 1 #"1" 0 0 24 3 1 #" " -0 0 14 3 11 #"green_block" +0 0 14 3 6 #"green-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 14 3 5 #"from:" @@ -842,74 +852,599 @@ 0 0 24 3 1 #"(" 0 0 15 3 13 #"define-recipe" 0 0 24 3 1 #" " -0 0 14 3 10 #"my_recipe3" +0 0 14 3 3 #"my-" +0 0 14 3 7 #"recipe3" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 14 3 5 #"make:" 0 0 24 3 1 #" " 0 0 21 3 1 #"5" 0 0 24 3 1 #" " -0 0 14 3 12 #"purple_block" +0 0 14 3 7 #"purple-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 2 #" " 0 0 14 3 5 #"from:" 0 0 24 3 2 #" (" -0 0 14 3 10 #"blue_block" +0 0 14 3 5 #"blue-" +0 0 14 3 5 #"block" 0 0 24 3 1 #" " -0 0 14 3 9 #"red_block" +0 0 14 3 4 #"red-" +0 0 14 3 5 #"block" 0 0 24 3 1 #")" 0 0 24 29 1 #"\n" 0 0 24 3 9 #" (" -0 0 14 3 9 #"red_block" +0 0 14 3 4 #"red-" +0 0 14 3 5 #"block" 0 0 24 3 1 #" " -0 0 14 3 10 #"blue_block" +0 0 14 3 5 #"blue-" +0 0 14 3 5 #"block" 0 0 24 3 1 #")" 0 0 24 29 1 #"\n" 0 0 24 3 3 #" )" 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" +0 0 24 3 1 #"(" +0 0 15 3 6 #"define" +0 0 24 3 2 #" (" +0 0 14 3 14 #"star-particles" +0 0 24 3 1 #" " +0 0 14 3 5 #"color" +0 0 24 3 1 #")" +0 0 24 29 1 #"\n" +0 0 24 3 3 #" (" +0 0 14 3 9 #"particles" +0 0 24 29 1 #"\n" +0 0 24 3 4 #" (" +0 0 14 3 7 #"overlay" +0 0 24 29 1 #"\n" +0 0 24 3 5 #" (" +0 0 14 3 4 #"star" +0 0 24 3 1 #" " +0 0 21 3 2 #"30" +0 0 24 3 1 #" " +0 0 19 3 7 #"\"solid\"" +0 0 24 3 1 #" " +0 0 14 3 5 #"color" +0 0 24 3 1 #")" +0 0 24 29 1 #"\n" +0 0 24 3 5 #" (" +0 0 14 3 4 #"star" +0 0 24 3 1 #" " +0 0 21 3 2 #"36" +0 0 24 3 1 #" " +0 0 19 3 7 #"\"solid\"" +0 0 24 3 1 #" " +0 0 19 3 7 #"\"black\"" +0 0 24 3 4 #"))))" +0 0 24 29 1 #"\n" +0 0 24 29 1 #"\n" +0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 24 3 1 #"(" -0 0 15 3 10 #"define-lua" +0 0 15 3 6 #"define" +0 0 24 3 2 #" (" +0 0 14 3 12 #"pig-textures" 0 0 24 3 1 #" " -0 0 14 3 8 #"testtest" -0 0 24 29 1 #"\n" -0 0 19 3 1 #"\"" -0 0 19 29 1 #"\n" -0 0 19 3 20 #" return function(" -0 0 19 3 3 #"pos" -0 0 19 3 1 #"," -0 0 19 3 1 #" " -0 0 19 3 4 #"node" -0 0 19 3 1 #"," -0 0 19 3 8 #" puncher" -0 0 19 3 1 #"," -0 0 19 3 1 #" " -0 0 19 3 13 #"pointed_thing" -0 0 19 3 1 #")" -0 0 19 29 1 #"\n" -0 0 19 3 26 #" print('hello world')" -0 0 19 29 1 #"\n" -0 0 19 3 7 #" end" -0 0 19 29 1 #"\n" -0 0 19 3 1 #"\"" +0 0 14 3 5 #"color" 0 0 24 3 1 #")" 0 0 24 29 1 #"\n" +0 0 24 3 3 #" (" +0 0 14 3 3 #"map" +0 0 24 3 2 #" (" +0 0 14 3 5 #"curry" +0 0 24 3 1 #" " +0 0 14 3 11 #"color-frame" +0 0 24 3 1 #" " +0 0 14 3 5 #"color" +0 0 24 3 1 #")" +0 0 24 29 1 #"\n" +0 0 24 3 8 #" (" +0 0 14 3 3 #"map" +0 0 24 3 2 #" (" +0 0 14 3 5 #"curry" +0 0 24 3 1 #" " +0 0 14 3 5 #"scale" +0 0 24 3 1 #" " +0 0 21 3 3 #"0.2" +0 0 24 3 3 #") (" +0 0 14 3 4 #"list" +0 0 24 3 1 #" " +0 6 4 21 3766 +( + #"(#(struct:scale 5 5 #(struct:translate 8 8 #(struct:bitmap #(#\"\\37" + #"7\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp" + #"\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\3" + #"74pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\37" + #"7\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp" + #"\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\3" + #"74pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\377\\200\\200\\377\\3" + #"77\\202\\202\\377\\377\\201\\201\\" + #"377\\377\\200\\200\\377\\377\\201\\" + #"201\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377\\374pp\\377" + #"\\374pp\\377\\377\\200\\200\\377\\" + #"377\\201\\201\\377\\377\\200\\200\\377\\376\\177\\177\\377\\375~~\\3" + #"77\\377\\202\\202\\377\\377\\200\\200\\377\\377ww\\377\\377ww\\377\\" + #"377\\200\\200\\377\\377\\202\\202\\377\\377\\202\\202\\377\\377\\202" + #"\\202\\377\\377\\202\\202\\377\\376\\177\\177\\377\\377\\201\\201\\3" + #"77\\377\\200\\200\\377\\377ww\\377\\377ww\\377\\377\\200\\200\\377\\" + #"377\\202\\202\\377\\376\\177\\177\\377\\377\\200\\200\\377\\377ww\\3" + #"77\\377ww\\377\\377\\200\\200\\377\\377\\202\\202\\377\\377\\202\\20" + #"2\\377\\376\\177\\177\\377\\376\\177\\177\\377\\377\\201\\201\\377\\" + #"377\\201\\201\\377\\376\\177\\177\\" + #"377\\377ww\\377\\377ww\\377\\377\\" + #"200\\200\\377\\376\\177\\177\\377\\377\\201\\201\\377\\377\\200\\200" + #"\\377\\377\\202\\202\\377\\377\\201\\201\\377\\377\\200\\200\\377\\3" + #"77\\201\\201\\377\\377\\200\\200\\" + #"377\\376\\177\\177\\377\\377\\201\\201\\377\\377\\202\\202\\377\\377" + #"\\200\\200\\377\\377\\201\\201\\377\\376\\177\\177\\377\\377\\201\\2" + #"01\\377\\377\\202\\202\\377\\377\\" + #"202\\202\\377\\377\\200\\200\\377\\377\\200\\200\\377\\377\\202\\202" + #"\\377\\377\\202\\202\\377\\377\\202\\202\\377\\377\\200\\200\\377\\3" + #"77\\200\\200\\377\\377\\200\\200\\" + #"377\\377\\200\\200\\377\\377\\200\\200\\377\\377\\200\\200\\377\\377" + #"\\200\\200\\377\\377\\200\\200\\377\\377\\200\\200\\377\\377\\200\\2" + #"00\\377\\377\\200\\200\\377\\377\\" + #"200\\200\\377\\377\\200\\200\\377\\377\\202\\202\\377\\377\\202\\202" + #"\\377\\376\\177\\177\\377\\377\\202\\202\\377\\377\\200\\200\\377\\3" + #"75~~\\377\\377\\202\\202\\377\\377\\201\\201\\377\\377\\201\\201\\37" + #"7\\376\\177\\177\\377\\377\\201\\201\\377\\377\\202\\202\\377\\377\\" + #"201\\201\\377\\377\\202\\202\\377\\377\\201\\201\\377\\377\\200\\200" + #"\\377\\377\\201\\201\\377\\377\\200\\200\\377\\376\\177\\177\\377\\3" + #"76\\177\\177\\377\\377\\200\\200\\" + #"377\\377\\201\\201\\377\\377\\202\\202\\377\\377\\200\\200\\377\\377" + #"\\201\\201\\377\\376\\177\\177\\377\\377\\201\\201\\377\\377\\201\\2" + #"01\\377\\377\\202\\202\\377\\377\\" + #"200\\200\\377\\377\\201\\201\\377\\377\\200\\200\\377\\375~~\\377\\3" + #"77\\202\\202\\377\\377\\201\\201\\" + #"377\\376\\177\\177\\377\\377\\200\\200\\377\\377\\201\\201\\377\\375" + #"~~\\377\\377\\202\\202\\377\\375~~\\377\\377\\202\\202\\377\\377\\20" + #"2\\202\\377\\377\\202\\202\\377\\377\\201\\201\\377\\376\\177\\177\\" + #"377\\377\\201\\201\\377\\376\\177\\177\\377\\376\\177\\177\\377\\377" + #"\\200\\200\\377\\377\\200\\200\\377\\377\\202\\202\\377\\377\\202\\2" + #"02\\377\\377\\201\\201\\377\\377\\202\\202\\377\\375~~\\377\\377\\20" + #"2\\202\\377\\377\\201\\201\\377\\377\\201\\201\\377\\377\\200\\200\\" + #"377\\377\\200\\200\\377\\376\\177\\177\\377\\377\\200\\200\\377\\377" + #"\\201\\201\\377\\376\\177\\177\\377\\377\\201\\201\\377\\377\\202\\2" + #"02\\377\\377\\202\\202\\377\\377\\" + #"201\\201\\377\\377\\201\\201\\377\\377\\201\\201\\377\\376\\177\\177" + #"\\377\\377\\200\\200\\377\\376\\177\\177\\377\\377\\201\\201\\377\\3" + #"77\\201\\201\\377\\377\\202\\202\\377\\375~~\\377\\377\\200\\200\\37" + #"7\\376\\177\\177\\377\\377\\200\\200\\377\\377\\202\\202\\377\\377\\" + #"201\\201\\377\\376\\177\\177\\377\\376\\177\\177\\377\\377\\200\\200" + #"\\377\\377\\200\\200\\377\\377\\20" + #"0\\200\\377\\375~~\\377\\377\\201\\201\\377\\375~~\\377\\376\\177\\1" + #"77\\377\\377\\200\\200\\377\\377\\" + #"201\\201\\377\\377\\202\\202\\377\\375~~\\377\\377\\202\\202\\377\\3" + #"77\\201\\201\\377\\377\\202\\202\\377\\375~~\\377\\377\\201\\201\\37" + #"7\\375~~\\377\\377\\202\\202\\377\\377\\201\\201\\377\\377\\202\\202" + #"\\377\\377\\201\\201\\377\\377\\202\\202\\377\\376\\177\\177\\377\\3" + #"77\\202\\202\\377\\377\\202\\202\\" + #"377\\377\\200\\200\\377\\377\\200\\200\\377\\377\\200\\200\\377\\377" + #"\\200\\200\\377\\377\\200\\200\\377\\377\\202\\202\\377\\377\\202\\2" + #"02\\377\\377\\202\\202\\377\\377\\" + #"202\\202\\377\\377\\202\\202\\377\\377\\202\\202\\377\\377\\202\\202" + #"\\377\\377\\202\\202\\377\\377\\202\\202\\377\\377\\202\\202\\377\\3" + #"77\\202\\202\\377\\377ww\\377\\377ww\\377\\377ww\\377\\377ww\\377\\3" + #"77ww\\377\\377ww\\377\\377ww\\377\\377ww\\377\\377ww\\377\\377ww\\37" + #"7\\377ww\\377\\377ww\\377\\377ww\\377\\377ww\\377\\377ww\\377\\377ww" + #"\" 16 16) 0 1 1 #hash()))) #(struct:bb 80 80 80) #f)" +) 0 0 24 3 1 #" " +0 6 4 21 2758 +( + #"(#(struct:scale 5 5 #(struct:translate 8 8 #(struct:bitmap #(#\"\\37" + #"7\\377[[\\377\\377]]\\377\\376ZZ\\377\\377\\\\\\\\\\377\\377\\\\\\\\" + #"\\377\\377\\\\\\\\\\377\\375YY\\377\\377\\\\\\\\\\377\\377[[\\377\\3" + #"77]]\\377\\377[[\\377\\375YY\\377\\377]]\\377\\377]]\\377\\375YY\\37" + #"7\\375YY\\377\\376ZZ\\377\\376ZZ\\377\\376ZZ\\377\\377[[\\377\\377[[" + #"\\377\\376ZZ\\377\\377\\\\\\\\\\377\\377\\\\\\\\\\377\\376ZZ\\377\\3" + #"76ZZ\\377\\375YY\\377\\377\\\\\\\\\\377\\375YY\\377\\377\\\\\\\\\\37" + #"7\\377\\\\\\\\\\377\\377[[\\377\\376ZZ\\377\\377\\\\\\\\\\377\\376ZZ" + #"\\377\\377]]\\377\\1\\1\\1\\377\\1\\1\\1\\377\\1\\1\\1\\377\\376ZZ\\" + #"377\\375YY\\377\\0\\0\\0\\377\\2\\2\\2\\377\\2\\2\\2\\377\\377]]\\37" + #"7\\376ZZ\\377\\376ZZ\\377\\375YY\\377\\375YY\\377\\377]]\\377\\376ZZ" + #"\\377\\375YY\\377\\0\\0\\0\\377\\0\\0\\0\\377\\1\\1\\1\\377\\377\\\\" + #"\\\\\\377\\377]]\\377\\1\\1\\1\\377\\0\\0\\0\\377\\0\\0\\0\\377\\376" + #"ZZ\\377\\377\\\\\\\\\\377\\375YY\\377\\377]]\\377\\377[[\\377\\377\\" + #"\\\\\\\\377\\377]]\\377\\376ZZ\\377\\0\\0\\0\\377\\2\\2\\2\\377\\1\\" + #"1\\1\\377\\377\\\\\\\\\\377\\377[[" + #"\\377\\0\\0\\0\\377\\1\\1\\1\\377\\0\\0\\0\\377\\377]]\\377\\377[[\\" + #"377\\375YY\\377\\377\\\\\\\\\\377\\375YY\\377\\376ZZ\\377\\376ZZ\\37" + #"7\\376ZZ\\377\\377[[\\377\\377[[\\377\\377]]\\377\\375YY\\377\\376ZZ" + #"\\377\\377]]\\377\\377]]\\377\\377]]\\377\\377]]\\377\\377\\\\\\\\\\" + #"377\\376ZZ\\377\\377]]\\377\\377\\\\\\\\\\377\\375YY\\377\\376ZZ\\37" + #"7\\375YY\\377\\377[[\\377\\377]]\\377\\377]]\\377\\377[[\\377\\377]]" + #"\\377\\376ZZ\\377\\377[[\\377\\377]]\\377\\377\\\\\\\\\\377\\377[[\\" + #"377\\377\\\\\\\\\\377\\376ZZ\\377\\377\\\\\\\\\\377\\376ZZ\\377\\375" + #"YY\\377\\376ZZ\\377\\2\\2\\2\\377\\1\\1\\1\\377\\0\\0\\0\\377\\377]]" + #"\\377\\377]]\\377\\1\\1\\1\\377\\0\\0\\0\\377\\1\\1\\1\\377\\375YY\\" + #"377\\377\\\\\\\\\\377\\377[[\\377\\375YY\\377\\377[[\\377\\375YY\\37" + #"7\\377]]\\377\\376ZZ\\377\\0\\0\\" + #"0\\377\\0\\0\\0\\377\\2\\2\\2\\377\\" + #"377[[\\377\\377[[\\377\\2\\2\\2\\377\\2\\2\\2\\377\\1\\1\\1\\377\\37" + #"5YY\\377\\377]]\\377\\377\\\\\\\\\\3" + #"77\\377]]\\377\\376ZZ\\377\\377\\\\\\\\\\377\\375YY\\377\\376ZZ\\377" + #"\\1\\1\\1\\377\\0\\0\\0\\377\\1\\1\\1\\377\\376ZZ\\377\\377[[\\377\\" + #"0\\0\\0\\377\\0\\0\\0\\377\\2\\2\\2\\377\\377]]\\377\\375YY\\377\\37" + #"6ZZ\\377\\376ZZ\\377\\377\\\\\\\\\\377\\375YY\\377\\376ZZ\\377\\375Y" + #"Y\\377\\377\\\\\\\\\\377\\377\\\\\\\\" + #"\\377\\377\\\\\\\\\\377\\377[[\\377\\377[[\\377\\377]]\\377\\377[[\\" + #"377\\377[[\\377\\377]]\\377\\376ZZ\\377\\376ZZ\\377\\377\\\\\\\\\\37" + #"7\\377\\\\\\\\\\377\\377]]\\377\\377" + #"[[\\377\\376ZZ\\377\\375YY\\377\\377\\\\\\\\\\377\\376ZZ\\377\\376ZZ" + #"\\377\\377]]\\377\\377]]\\377\\375YY\\377\\376ZZ\\377\\376ZZ\\377\\3" + #"77\\\\\\\\\\377\\376ZZ\\377\\375YY\\377\\377[[\\377\\377]]\\377\\375" + #"YY\\377\\377[[\\377\\375YY\\377\\3" + #"77[[\\377\\377[[\\377\\377[[\\377\\377[[\\377\\377\\\\\\\\\\377\\376" + #"ZZ\\377\\377[[\\377\\375YY\\377\\3" + #"77]]\\377\\377[[\\377\\376ZZ\\377\\377\\\\\\\\\\377\\377\\\\\\\\\\37" + #"7\\377\\\\\\\\\\377\\376ZZ\\377\\377" + #"[[\\377\\377[[\\377\\376ZZ\\377\\375YY\\377\\377[[\\377\\377\\\\\\\\" + #"\\377\\375YY\\377\\377\\\\\\\\\\377\\377\\\\\\\\\\377\\377]]\\377\\3" + #"75YY\\377\\375YY\\377\\375YY\\377\\376ZZ\\377\\377\\\\\\\\\\377\\375" + #"YY\\377\\377]]\\377\\377]]\\377\\3" + #"77[[\\377\\377[[\\377\\376ZZ\\377\\377[[\\377\\377]]\\377\\376ZZ\\37" + #"7\\377\\\\\\\\\\377\\377[[\\377\\375" + #"YY\\377\\376ZZ\\377\\377[[\\377\\3" + #"77]]\\377\\377]]\\377\\377]]\\377\\377[[\\377\\377\\\\\\\\\\377\\376" + #"ZZ\\377\\376ZZ\\377\\376ZZ\\377\\3" + #"77]]\\377\\375YY\\377\\376ZZ\\377\\377\\\\\\\\\\377\\376ZZ\\377\\377" + #"]]\\377\\377]]\" 16 16) 0 1 1 #hash()))) #(struct:bb 80 80 80) #f)" +) 0 0 24 3 1 #" " +0 6 4 21 3322 +( + #"(#(struct:scale 5 5 #(struct:translate 8 8 #(struct:bitmap #(#\"\\37" + #"7\\327Ua\\377\\331Wc\\377\\331Wc\\377\\331Wc\\377\\330Vb\\377\\330Vb" + #"\\377\\331Wc\\377\\333Ye\\377\\332Xd\\377\\333Ye\\377\\333Ye\\377\\3" + #"31Wc\\377\\333Ye\\377\\327Ua\\377\\332Xd\\377\\332Xd\\377\\327Ua\\37" + #"7\\327Ua\\377\\332Xd\\377\\327Ua\\377\\331Wc\\377\\333Ye\\377\\327Ua" + #"\\377\\330Vb\\377\\330Vb\\377\\331Wc\\377\\327Ua\\377\\333Ye\\377\\3" + #"27Ua\\377\\331Wc\\377\\330Vb\\377\\327Ua\\377\\333Ye\\377\\327Ua\\37" + #"7\\330Vb\\377\\327Ua\\377\\330Vb\\377\\327Ua\\377\\332Xd\\377\\333Ye" + #"\\377\\330Vb\\377\\333Ye\\377\\327Ua\\377\\333Ye\\377\\330Vb\\377\\3" + #"27Ua\\377\\331Wc\\377\\333Ye\\377\\331Wc\\377\\331Wc\\377\\327Ua\\37" + #"7\\333Ye\\377\\327Ua\\377\\331Wc\\377\\333Ye\\377\\327Ua\\377\\331Wc" + #"\\377\\330Vb\\377\\333Ye\\377\\332Xd\\377\\330Vb\\377\\331Wc\\377\\3" + #"30Vb\\377\\333Ye\\377\\331Wc\\377\\327Ua\\377\\333Ye\\377\\330Vb\\37" + #"7\\332Xd\\377\\333Ye\\377\\333Ye\\377\\327Ua\\377\\333Ye\\377\\333Ye" + #"\\377\\327Ua\\377\\333Ye\\377\\330Vb\\377\\331Wc\\377\\333Ye\\377\\3" + #"27Ua\\377\\331Wc\\377\\333Ye\\377\\333Ye\\377\\333Ye\\377\\327Ua\\37" + #"7\\331Wc\\377\\327Ua\\377\\330Vb\\377\\333Ye\\377\\330Vb\\377\\331Wc" + #"\\377\\330Vb\\377\\332Xd\\377\\327Ua\\377\\330Vb\\377\\333Ye\\377\\3" + #"33Ye\\377\\377\\202\\202\\377\\377\\203\\203\\377\\377\\204\\204\\37" + #"7\\376\\200\\200\\377\\375\\177\\177\\377\\377\\202\\202\\377\\377\\" + #"202\\202\\377\\377\\204\\204\\377\\377\\204\\204\\377\\377\\201\\201" + #"\\377\\377\\201\\201\\377\\377\\202\\202\\377\\377\\202\\202\\377\\3" + #"75\\177\\177\\377\\377\\201\\201\\377\\377^^\\377\\377\\201\\201\\37" + #"7\\377\\204\\204\\377\\377\\201\\201\\377\\376\\200\\200\\377\\377\\" + #"204\\204\\377\\377\\201\\201\\377\\377\\204\\204\\377\\377\\202\\202" + #"\\377\\377\\201\\201\\377\\377\\204\\204\\377\\374~~\\377\\374~~\\37" + #"7\\377\\201\\201\\377\\374~~\\377\\377\\201\\201\\377\\377^^\\377\\3" + #"77\\201\\201\\377\\377\\202\\202\\" + #"377\\377\\201\\201\\377\\377\\201\\201\\377\\376\\200\\200\\377\\377" + #"\\201\\201\\377\\375\\177\\177\\37" + #"7\\375\\177\\177\\377\\374~~\\377\\377\\204\\204\\377\\374~~\\377\\3" + #"74~~\\377\\377\\201\\201\\377\\377\\203\\203\\377\\377\\201\\201\\37" + #"7\\377^^\\377\\377\\203\\203\\377\\377\\201\\201\\377\\377\\204\\204" + #"\\377\\377\\203\\203\\377\\377\\202\\202\\377\\377\\203\\203\\377\\3" + #"74~~\\377\\377\\201\\201\\377\\377\\201\\201\\377\\377\\201\\201\\37" + #"7\\376\\200\\200\\377\\377\\203\\203\\377\\377\\203\\203\\377\\374pp" + #"\\377\\374pp\\377\\377^^\\377\\377\\201\\201\\377\\375\\177\\177\\37" + #"7\\377\\201\\201\\377\\374~~\\377\\374~~\\377\\377\\204\\204\\377\\3" + #"77\\201\\201\\377\\377\\204\\204\\" + #"377\\377\\203\\203\\377\\375\\177\\177\\377\\376\\200\\200\\377\\375" + #"\\177\\177\\377\\377\\204\\204\\377\\374pp\\377\\374pp\\377\\327Ua\\" + #"377\\375\\177\\177\\377\\377\\201\\201\\377\\376\\200\\200\\377\\375" + #"\\177\\177\\377\\377\\201\\201\\377\\375\\177\\177\\377\\377\\203\\2" + #"03\\377\\374~~\\377\\377\\201\\201\\377\\377\\203\\203\\377\\377\\20" + #"3\\203\\377\\377\\201\\201\\377\\375\\177\\177\\377\\374pp\\377\\374" + #"pp\\377\\331Wc\\377\\377\\203\\203\\377\\377\\201\\201\\377\\375\\17" + #"7\\177\\377\\377\\201\\201\\377\\377\\201\\201\\377\\376\\200\\200\\" + #"377\\377\\203\\203\\377\\377\\201\\201\\377\\377\\203\\203\\377\\377" + #"\\201\\201\\377\\377\\201\\201\\377\\375\\177\\177\\377\\377\\203\\2" + #"03\\377\\374pp\\377\\374pp\\377\\333Ye\\377\\376\\200\\200\\377\\375" + #"\\177\\177\\377\\377\\202\\202\\377\\374~~\\377\\374~~\\377\\377\\20" + #"4\\204\\377\\377\\204\\204\\377\\376\\200\\200\\377\\377\\202\\202\\" + #"377\\374~~\\377\\377\\201\\201\\377\\376\\200\\200\\377\\376\\200\\2" + #"00\\377\\374pp\\377\\374pp\\377\\332Xd\\377\\376\\200\\200\\377\\377" + #"\\202\\202\\377\\377\\202\\202\\37" + #"7\\374~~\\377\\376\\200\\200\\377\\377\\202\\202\\377\\377\\202\\202" + #"\\377\\374~~\\377\\377\\203\\203\\" + #"377\\377\\202\\202\\377\\377\\202\\202\\377\\377\\203\\203\\377\\375" + #"\\177\\177\\377\\374pp\\377\\374" + #"pp\\377\\0\\0\\0\\377\\0\\0\\0\\37" + #"7\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0" + #"\\0\\377\\0\\0\\0\\377\\0\\0\\0\\37" + #"7\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0" + #"\\0\\377\\0\\0\\0\\377\\0\\0\\0\\37" + #"7\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0\" 16 16) 0 1 1 " + #"#hash()))) #(struct:bb 80 80 80) #f)" +) 0 0 24 3 1 #" " +0 6 4 21 3322 +( + #"(#(struct:scale 5 5 #(struct:translate 8 8 #(struct:bitmap #(#\"\\37" + #"7\\332Xd\\377\\332Xd\\377\\327Ua\\377\\333Ye\\377\\331Wc\\377\\333Ye" + #"\\377\\333Ye\\377\\332Xd\\377\\333Ye\\377\\331Wc\\377\\330Vb\\377\\3" + #"30Vb\\377\\331Wc\\377\\331Wc\\377\\331Wc\\377\\327Ua\\377\\327Ua\\37" + #"7\\330Vb\\377\\331Wc\\377\\327Ua\\377\\333Ye\\377\\327Ua\\377\\331Wc" + #"\\377\\330Vb\\377\\330Vb\\377\\327Ua\\377\\333Ye\\377\\331Wc\\377\\3" + #"27Ua\\377\\332Xd\\377\\327Ua\\377\\327Ua\\377\\333Ye\\377\\331Wc\\37" + #"7\\327Ua\\377\\330Vb\\377\\333Ye\\377\\327Ua\\377\\333Ye\\377\\330Vb" + #"\\377\\333Ye\\377\\332Xd\\377\\327Ua\\377\\330Vb\\377\\327Ua\\377\\3" + #"30Vb\\377\\327Ua\\377\\333Ye\\377\\333Ye\\377\\330Vb\\377\\331Wc\\37" + #"7\\330Vb\\377\\332Xd\\377\\333Ye\\377\\330Vb\\377\\331Wc\\377\\327Ua" + #"\\377\\333Ye\\377\\331Wc\\377\\327Ua\\377\\333Ye\\377\\327Ua\\377\\3" + #"31Wc\\377\\331Wc\\377\\327Ua\\377\\333Ye\\377\\331Wc\\377\\330Vb\\37" + #"7\\333Ye\\377\\327Ua\\377\\333Ye\\377\\333Ye\\377\\327Ua\\377\\333Ye" + #"\\377\\333Ye\\377\\332Xd\\377\\330Vb\\377\\333Ye\\377\\327Ua\\377\\3" + #"31Wc\\377\\333Ye\\377\\330Vb\\377\\327Ua\\377\\332Xd\\377\\330Vb\\37" + #"7\\331Wc\\377\\330Vb\\377\\333Ye\\377\\330Vb\\377\\327Ua\\377\\331Wc" + #"\\377\\327Ua\\377\\333Ye\\377\\333Ye\\377\\333Ye\\377\\331Wc\\377\\3" + #"77\\201\\201\\377\\375\\177\\177\\" + #"377\\377\\202\\202\\377\\377\\202\\202\\377\\377\\201\\201\\377\\377" + #"\\201\\201\\377\\377\\204\\204\\377\\377\\204\\204\\377\\377\\202\\2" + #"02\\377\\377\\202\\202\\377\\375\\" + #"177\\177\\377\\376\\200\\200\\377\\377\\204\\204\\377\\377\\203\\203" + #"\\377\\377\\202\\202\\377\\333Ye\\377\\377\\201\\201\\377\\374~~\\37" + #"7\\377\\201\\201\\377\\374~~\\377\\374~~\\377\\377\\204\\204\\377\\3" + #"77\\201\\201\\377\\377\\202\\202\\" + #"377\\377\\204\\204\\377\\377\\201\\201\\377\\377\\204\\204\\377\\376" + #"\\200\\200\\377\\377\\201\\201\\377\\377\\204\\204\\377\\377\\201\\2" + #"01\\377\\377^^\\377\\377\\201\\201\\377\\377\\203\\203\\377\\377\\20" + #"1\\201\\377\\374~~\\377\\374~~\\37" + #"7\\377\\204\\204\\377\\374~~\\377\\375\\177\\177\\377\\375\\177\\177" + #"\\377\\377\\201\\201\\377\\376\\200\\200\\377\\377\\201\\201\\377\\3" + #"77\\201\\201\\377\\377\\202\\202\\377\\377\\201\\201\\377\\377^^\\37" + #"7\\374pp\\377\\374pp\\377\\377\\203\\203\\377\\377\\203\\203\\377\\3" + #"76\\200\\200\\377\\377\\201\\201\\" + #"377\\377\\201\\201\\377\\377\\201\\201\\377\\374~~\\377\\377\\203\\2" + #"03\\377\\377\\202\\202\\377\\377\\" + #"203\\203\\377\\377\\204\\204\\377\\377\\201\\201\\377\\377\\203\\203" + #"\\377\\377^^\\377\\374pp\\377\\374pp\\377\\377\\204\\204\\377\\375\\" + #"177\\177\\377\\376\\200\\200\\377\\375\\177\\177\\377\\377\\203\\203" + #"\\377\\377\\204\\204\\377\\377\\201\\201\\377\\377\\204\\204\\377\\3" + #"74~~\\377\\374~~\\377\\377\\201\\201\\377\\375\\177\\177\\377\\377\\" + #"201\\201\\377\\377^^\\377\\374pp\\377\\374pp\\377\\375\\177\\177\\37" + #"7\\377\\201\\201\\377\\377\\203\\203\\377\\377\\203\\203\\377\\377\\" + #"201\\201\\377\\374~~\\377\\377\\203\\203\\377\\375\\177\\177\\377\\3" + #"77\\201\\201\\377\\375\\177\\177\\" + #"377\\376\\200\\200\\377\\377\\201\\201\\377\\375\\177\\177\\377\\327" + #"Ua\\377\\374pp\\377\\374pp\\377\\377\\203\\203\\377\\375\\177\\177\\" + #"377\\377\\201\\201\\377\\377\\201\\201\\377\\377\\203\\203\\377\\377" + #"\\201\\201\\377\\377\\203\\203\\377\\376\\200\\200\\377\\377\\201\\2" + #"01\\377\\377\\201\\201\\377\\375\\" + #"177\\177\\377\\377\\201\\201\\377\\377\\203\\203\\377\\331Wc\\377\\3" + #"74pp\\377\\374pp\\377\\376\\200\\200\\377\\376\\200\\200\\377\\377\\" + #"201\\201\\377\\374~~\\377\\377\\202\\202\\377\\376\\200\\200\\377\\3" + #"77\\204\\204\\377\\377\\204\\204\\377\\374~~\\377\\374~~\\377\\377\\" + #"202\\202\\377\\375\\177\\177\\377\\376\\200\\200\\377\\333Ye\\377\\3" + #"74pp\\377\\374pp\\377\\375\\177\\177\\377\\377\\203\\203\\377\\377\\" + #"202\\202\\377\\377\\202\\202\\377\\377\\203\\203\\377\\374~~\\377\\3" + #"77\\202\\202\\377\\377\\202\\202\\377\\376\\200\\200\\377\\374~~\\37" + #"7\\377\\202\\202\\377\\377\\202\\202\\377\\376\\200\\200\\377\\332Xd" + #"\\377\\0\\0\\0\\377\\0\\0\\0\\377\\" + #"0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0" + #"\\377\\0\\0\\0\\377\\0\\0\\0\\377\\" + #"0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0" + #"\\377\\0\\0\\0\\377\\0\\0\\0\\377\\" + #"0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0\" 16 16) 0 1 1 #ha" + #"sh()))) #(struct:bb 80 80 80) #f)" +) 0 0 24 3 1 #" " +0 6 4 21 3102 +( + #"(#(struct:scale 5 5 #(struct:translate 8 8 #(struct:bitmap #(#\"\\37" + #"7\\333Ye\\377\\334Zf\\377\\331Wc\\377\\333Ye\\377\\332Xd\\377\\333Ye" + #"\\377\\331Wc\\377\\333Ye\\377\\330Vb\\377\\332Xd\\377\\330Vb\\377\\3" + #"30Vb\\377\\332Xd\\377\\333Ye\\377\\332Xd\\377\\333Ye\\377\\333Ye\\37" + #"7\\331Wc\\377\\333Ye\\377\\331Wc\\377\\331Wc\\377\\331Wc\\377\\331Wc" + #"\\377\\330Vb\\377\\334Zf\\377\\331Wc\\377\\334Zf\\377\\331Wc\\377\\3" + #"34Zf\\377\\330Vb\\377\\334Zf\\377\\334Zf\\377\\333Ye\\377\\331Wc\\37" + #"7\\331Wc\\377\\333Ye\\377\\331Wc\\377\\331Wc\\377\\332Xd\\377\\330Vb" + #"\\377\\331Wc\\377\\331Wc\\377\\330Vb\\377\\332Xd\\377\\332Xd\\377\\3" + #"32Xd\\377\\332Xd\\377\\332Xd\\377\\332Xd\\377\\334Zf\\377\\330Vb\\37" + #"7\\332Xd\\377\\330Vb\\377\\331Wc\\377\\333Ye\\377\\332Xd\\377\\330Vb" + #"\\377\\333Ye\\377\\330Vb\\377\\332Xd\\377\\331Wc\\377\\331Wc\\377\\3" + #"32Xd\\377\\331Wc\\377\\331Wc\\377\\333Ye\\377\\330Vb\\377\\333Ye\\37" + #"7\\330Vb\\377\\334Zf\\377\\331Wc\\377\\334Zf\\377\\333Ye\\377\\331Wc" + #"\\377\\332Xd\\377\\332Xd\\377\\334Zf\\377\\332Xd\\377\\334Zf\\377\\3" + #"32Xd\\377\\333Ye\\377\\334Zf\\377\\334Zf\\377\\330Vb\\377\\331Wc\\37" + #"7\\331Wc\\377\\332Xd\\377\\330Vb\\377\\332Xd\\377\\333Ye\\377\\331Wc" + #"\\377\\334Zf\\377\\333Ye\\377\\330Vb\\377\\332Xd\\377\\334Zf\\377\\3" + #"34Zf\\377\\333Ye\\377\\330Vb\\377\\376\\201\\201\\377\\374\\177\\177" + #"\\377\\377\\205\\205\\377\\374\\177\\177\\377\\374\\177\\177\\377\\3" + #"77\\202\\202\\377\\375\\200\\200\\" + #"377\\376\\201\\201\\377\\377\\204\\204\\377\\377\\205\\205\\377\\331" + #"Wc\\377\\333Ye\\377\\331Wc\\377\\332Xd\\377\\377\\202\\202\\377\\376" + #"\\201\\201\\377\\377\\205\\205\\377\\375\\200\\200\\377\\377\\377\\3" + #"77\\377\\377\\377\\377\\377\\377\\" + #"204\\204\\377\\375\\200\\200\\377\\377\\377\\377\\377\\377\\377\\377" + #"\\377\\375\\200\\200\\377\\375\\200\\200\\377\\377\\202\\202\\377\\3" + #"76\\201\\201\\377\\332Xd\\377\\330Vb\\377\\377\\205\\205\\377\\375\\" + #"200\\200\\377\\377\\205\\205\\377\\377\\203\\203\\377\\0\\306\\0\\37" + #"7\\0\\306\\0\\377\\377\\205\\205\\377\\375\\200\\200\\377\\0\\306\\0" + #"\\377\\0\\306\\0\\377\\377\\202\\202\\377\\374\\177\\177\\377\\377\\" + #"205\\205\\377\\375\\200\\200\\377\\333Ye\\377\\331Wc\\377\\332Xd\\37" + #"7\\334Zf\\377\\377\\202\\202\\377\\376\\201\\201\\377\\374gg\\377\\3" + #"74gg\\377\\374gg\\377\\374gg\\377" + #"\\374gg\\377\\374gg\\377\\375\\200\\200\\377\\377\\203\\203\\377\\33" + #"0Vb\\377\\331Wc\\377\\331Wc\\377\\331Wc\\377\\331Wc\\377\\334Zf\\377" + #"\\377\\205\\205\\377\\375\\200\\200\\377\\374gg\\377\\0\\0\\0\\377\\" + #"374gg\\377\\374gg\\377\\0\\0\\0\\377\\374gg\\377\\376\\201\\201\\377" + #"\\377\\203\\203\\377\\330Vb\\377\\330Vb\\377\\330Vb\\377\\332Xd\\377" + #"\\331Wc\\377\\330Vb\\377\\377\\202\\202\\377\\374\\177\\177\\377\\37" + #"4gg\\377\\0\\0\\0\\377\\374gg\\377" + #"\\374gg\\377\\0\\0\\0\\377\\374gg\\377\\377\\205\\205\\377\\377\\205" + #"\\205\\377\\331Wc\\377\\331Wc\\377\\332Xd\\377\\334Zf\\377\\331Wc\\3" + #"77\\332Xd\\377\\375\\200\\200\\377\\376\\201\\201\\377\\374gg\\377\\" + #"374gg\\377\\374gg\\377\\374gg\\377\\374gg\\377\\374gg\\377\\375\\200" + #"\\200\\377\\377\\204\\204\\377\\330Vb\\377\\334Zf\\377\\334Zf\\377\\" + #"330Vb\\377\\330Vb\\377\\334Zf\\377\\377\\204\\204\\377\\374\\177\\17" + #"7\\377\\374\\177\\177\\377\\377\\204\\204\\377\\374\\177\\177\\377\\" + #"377\\204\\204\\377\\377\\202\\202\\377\\374\\177\\177\\377\\377\\204" + #"\\204\\377\\377\\203\\203\\377\\334Zf\\377\\330Vb\\377\\334Zf\\377\\" + #"332Xd\\377\\331Wc\\377\\332Xd\\377\\377\\203\\203\\377\\376\\201\\20" + #"1\\377\\377\\205\\205\\377\\377\\205\\205\\377\\376\\201\\201\\377\\" + #"374\\177\\177\\377\\375\\200\\200\\377\\377\\203\\203\\377\\377\\203" + #"\\203\\377\\376\\201\\201\\377\\330Vb\\377\\333Ye\\377\\333Ye\\377\\" + #"334Zf\\377\\332Xd\\377\\331Wc\\377\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0" + #"\\0\\377\\0\\0\\0\\377\\0\\0\\0\\37" + #"7\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0" + #"\\0\\377\\0\\0\\0\\377\\0\\0\\0\\377" + #"\\333Ye\\377\\333Ye\\377\\333Ye\" 16 16) 0 1 1 #hash()))) #(struct:b" + #"b 80 80 80) #f)" +) 0 0 24 3 1 #" " +0 6 4 21 3232 +( + #"(#(struct:scale 5 5 #(struct:translate 8 8 #(struct:bitmap #(#\"\\37" + #"7\\333Ye\\377\\332Xd\\377\\333Ye\\377\\332Xd\\377\\330Vb\\377\\330Vb" + #"\\377\\332Xd\\377\\330Vb\\377\\333Ye\\377\\331Wc\\377\\333Ye\\377\\3" + #"32Xd\\377\\333Ye\\377\\331Wc\\377\\334Zf\\377\\333Ye\\377\\334Zf\\37" + #"7\\334Zf\\377\\330Vb\\377\\334Zf\\377\\331Wc\\377\\334Zf\\377\\331Wc" + #"\\377\\334Zf\\377\\330Vb\\377\\331Wc\\377\\331Wc\\377\\331Wc\\377\\3" + #"31Wc\\377\\333Ye\\377\\331Wc\\377\\333Ye\\377\\332Xd\\377\\332Xd\\37" + #"7\\332Xd\\377\\332Xd\\377\\332Xd\\377\\330Vb\\377\\331Wc\\377\\331Wc" + #"\\377\\330Vb\\377\\332Xd\\377\\331Wc\\377\\331Wc\\377\\333Ye\\377\\3" + #"31Wc\\377\\331Wc\\377\\333Ye\\377\\331Wc\\377\\332Xd\\377\\331Wc\\37" + #"7\\331Wc\\377\\332Xd\\377\\330Vb\\377\\333Ye\\377\\330Vb\\377\\332Xd" + #"\\377\\333Ye\\377\\331Wc\\377\\330Vb\\377\\332Xd\\377\\330Vb\\377\\3" + #"34Zf\\377\\332Xd\\377\\332Xd\\377\\334Zf\\377\\332Xd\\377\\334Zf\\37" + #"7\\332Xd\\377\\332Xd\\377\\331Wc\\377\\333Ye\\377\\334Zf\\377\\331Wc" + #"\\377\\334Zf\\377\\330Vb\\377\\333Ye\\377\\330Vb\\377\\333Ye\\377\\3" + #"31Wc\\377\\334Zf\\377\\332Xd\\377\\330Vb\\377\\333Ye\\377\\334Zf\\37" + #"7\\331Wc\\377\\333Ye\\377\\332Xd\\377\\330Vb\\377\\332Xd\\377\\331Wc" + #"\\377\\331Wc\\377\\330Vb\\377\\334Zf\\377\\334Zf\\377\\333Ye\\377\\3" + #"31Wc\\377\\333Ye\\377\\331Wc\\377\\374\\177\\177\\377\\377\\205\\205" + #"\\377\\377\\203\\203\\377\\377\\203\\203\\377\\377\\205\\205\\377\\3" + #"77\\202\\202\\377\\377\\205\\205\\" + #"377\\377\\205\\205\\377\\376\\201\\201\\377\\375\\200\\200\\377\\330" + #"Vb\\377\\333Ye\\377\\334Zf\\377\\332Xd\\377\\377\\202\\202\\377\\376" + #"\\201\\201\\377\\377\\202\\202\\377\\377\\202\\202\\377\\374\\177\\1" + #"77\\377\\376\\201\\201\\377\\377vv\\377\\377vv\\377\\377\\205\\205\\" + #"377\\376\\201\\201\\377\\376\\201\\201\\377\\376\\201\\201\\377\\377" + #"\\202\\202\\377\\376\\201\\201\\377\\332Xd\\377\\333Ye\\377\\377\\20" + #"5\\205\\377\\375\\200\\200\\377\\377\\204\\204\\377\\377\\205\\205\\" + #"377\\377\\202\\202\\377\\377\\204\\204\\377\\377\\205\\205\\377\\377" + #"\\202\\202\\377\\377vv\\377\\377\\" + #"202\\202\\377\\375\\200\\200\\377\\377\\202\\202\\377\\377\\205\\205" + #"\\377\\375\\200\\200\\377\\330Vb\\377\\331Wc\\377\\331Wc\\377\\330Vb" + #"\\377\\375\\200\\200\\377\\374\\177\\177\\377\\375\\200\\200\\377\\3" + #"75\\200\\200\\377\\376\\201\\201\\377\\377\\202\\202\\377\\377vv\\37" + #"7\\375\\200\\200\\377\\376\\201\\201\\377\\376\\201\\201\\377\\334Zf" + #"\\377\\332Xd\\377\\331Wc\\377\\330Vb\\377\\330Vb\\377\\330Vb\\377\\3" + #"77\\203\\203\\377\\377\\202\\202\\" + #"377\\375\\200\\200\\377\\377\\203\\203\\377\\377\\203\\203\\377\\377" + #"vv\\377\\377\\203\\203\\377\\375\\" + #"200\\200\\377\\377\\205\\205\\377\\377\\204\\204\\377\\334Zf\\377\\3" + #"31Wc\\377\\331Wc\\377\\332Xd\\377" + #"\\331Wc\\377\\331Wc\\377\\376\\201\\201\\377\\376\\201\\201\\377\\37" + #"4\\177\\177\\377\\374\\177\\177\\377\\377\\203\\203\\377\\377\\205\\" + #"205\\377\\377\\202\\202\\377\\377\\204\\204\\377\\375\\200\\200\\377" + #"\\377\\204\\204\\377\\330Vb\\377\\331Wc\\377\\332Xd\\377\\334Zf\\377" + #"\\334Zf\\377\\330Vb\\377\\374\\177\\177\\377\\376\\201\\201\\377\\37" + #"7\\205\\205\\377\\377\\202\\202\\377\\377\\203\\203\\377\\377\\202\\" + #"202\\377\\377\\204\\204\\377\\374\\177\\177\\377\\375\\200\\200\\377" + #"\\375\\200\\200\\377\\332Xd\\377\\331Wc\\377\\334Zf\\377\\334Zf\\377" + #"\\330Vb\\377\\334Zf\\377\\375\\200\\200\\377\\377\\203\\203\\377\\37" + #"6\\201\\201\\377\\377\\202\\202\\377\\375\\200\\200\\377\\377\\202\\" + #"202\\377\\376\\201\\201\\377\\377\\203\\203\\377\\374\\177\\177\\377" + #"\\377\\205\\205\\377\\334Zf\\377\\330Vb\\377\\330Vb\\377\\333Ye\\377" + #"\\333Ye\\377\\330Vb\\377\\377\\202\\202\\377\\374\\177\\177\\377\\37" + #"4\\177\\177\\377\\375\\200\\200\\377\\375\\200\\200\\377\\375\\200\\" + #"200\\377\\377\\202\\202\\377\\377\\204\\204\\377\\374\\177\\177\\377" + #"\\374\\177\\177\\377\\332Xd\\377\\331Wc\\377\\332Xd\\377\\333Ye\\377" + #"\\333Ye\\377\\333Ye\\377\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0\\377\\" + #"0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0" + #"\\377\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0\\377\\0\\0\\0\\377\\331Wc" + #"\\377\\332Xd\\377\\334Zf\" 16 16) 0 1 1 #hash()))) #(struct:bb 80 80" + #" 80) #f)" +) 0 0 24 3 4 #"))))" +0 0 24 29 1 #"\n" +0 0 24 29 1 #"\n" +0 0 24 3 1 #"(" +0 0 15 3 13 #"define-entity" +0 0 24 3 1 #" " +0 0 14 3 7 #"yellow-" +0 0 14 3 3 #"pig" +0 0 24 29 1 #"\n" +0 0 24 3 2 #" " +0 0 19 3 7 #"\"Piggy\"" +0 0 24 29 1 #"\n" +0 0 24 3 3 #" (" +0 0 14 3 12 #"pig-textures" +0 0 24 3 1 #" " +0 0 19 3 8 #"\"yellow\"" +0 0 24 3 2 #"))" +0 0 24 29 1 #"\n" +0 0 24 29 1 #"\n" +0 0 24 3 1 #"(" +0 0 15 3 13 #"define-entity" +0 0 24 3 1 #" " +0 0 14 3 4 #"red-" +0 0 14 3 3 #"pig" +0 0 24 29 1 #"\n" +0 0 24 3 2 #" " +0 0 19 3 7 #"\"Piggy\"" +0 0 24 29 1 #"\n" +0 0 24 3 3 #" (" +0 0 14 3 12 #"pig-textures" +0 0 24 3 1 #" " +0 0 19 3 5 #"\"red\"" +0 0 24 3 2 #"))" +0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 24 3 1 #"(" 0 0 14 3 16 #"add-behaviour-to" 0 0 24 3 1 #" " -0 0 14 3 12 #"yellow_block" +0 0 14 3 7 #"yellow-" +0 0 14 3 5 #"block" 0 0 24 29 1 #"\n" 0 0 24 3 19 #" (" -0 0 14 3 8 #"on_punch" -0 0 24 3 2 #" (" -0 0 14 3 8 #"call-lua" +0 0 14 3 3 #"on-" +0 0 14 3 5 #"punch" +0 0 24 29 1 #"\n" +0 0 24 3 20 #" (" +0 0 14 3 17 #"on-punch-sequence" +0 0 24 29 1 #"\n" +0 0 24 3 22 #" (" +0 0 14 3 14 #"star-particles" 0 0 24 3 1 #" " -0 0 14 3 8 #"testtest" -0 0 24 3 3 #")))" +0 0 19 3 8 #"\"yellow\"" +0 0 24 3 1 #")" +0 0 24 29 1 #"\n" +0 0 24 3 22 #" (" +0 0 14 3 5 #"spawn" +0 0 24 3 1 #" " +0 0 14 3 7 #"yellow-" +0 0 14 3 3 #"pig" +0 0 24 3 4 #"))))" +0 0 24 29 1 #"\n" +0 0 24 29 1 #"\n" +0 0 24 3 1 #"(" +0 0 14 3 16 #"add-behaviour-to" +0 0 24 3 1 #" " +0 0 14 3 4 #"red-" +0 0 14 3 5 #"block" +0 0 24 29 1 #"\n" +0 0 24 3 19 #" (" +0 0 14 3 3 #"on-" +0 0 14 3 5 #"punch" +0 0 24 29 1 #"\n" +0 0 24 3 20 #" (" +0 0 14 3 17 #"on-punch-sequence" +0 0 24 29 1 #"\n" +0 0 24 3 22 #" (" +0 0 14 3 14 #"star-particles" +0 0 24 3 1 #" " +0 0 19 3 5 #"\"red\"" +0 0 24 3 1 #")" +0 0 24 29 1 #"\n" +0 0 24 3 22 #" (" +0 0 14 3 5 #"spawn" +0 0 24 3 1 #" " +0 0 14 3 7 #"red-pig" +0 0 24 3 4 #"))))" 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" 0 0 24 29 1 #"\n" diff --git a/lua.rkt b/lua.rkt index efeadee..5c3393f 100644 --- a/lua.rkt +++ b/lua.rkt @@ -1,23 +1,45 @@ #lang racket +(provide define-lua-raw) (provide define-lua) -(provide call-lua) +(provide ref-lua) +(provide sequence) (require "core.rkt") (require (for-syntax racket/syntax)) -;Basically a thunk in lua + + (define (lua-def id code m) (asset-struct id "" - (++ "function " id "()\n" - code - "\nend\n") + (++ (variableify id) " = " + code) m)) -(define (call-lua ref) +(define (lua-raw id code m) + (asset-struct id "" + code + m)) + +(define (sequence . refs) (special-compile (thunk - (format "~a()" (asset-struct-name ref))))) + (format "function()\n ~a \nend" + (string-join + (map (curryr ++ "()") (map compile-v refs)) + "\n")) + ))) + +(define (ref-lua ref . args) + (special-compile + (thunk + (let ([base (format "~a" (variableify (asset-struct-name ref)))]) + (if (empty? args) + base + (format "~a(~a)" base + (string-join + (map compile-v args) + ","))))))) (define-syntax (define-lua stx) @@ -29,3 +51,80 @@ (set-my-mod! (add-lua-def my-mod id)) ) ) ])) +(define-syntax (define-lua-raw stx) + (syntax-case stx () + [(_ id body-string) + (with-syntax* ([name (symbol->string (format-symbol "~a" #'id))]) + #`(begin + (define id (lua-raw name body-string my-mod) ) + (set-my-mod! (add-lua-def my-mod id)) + ) ) ])) + + + +;Some default code snippets + +(define-lua particles-def +" +function(file,num,vx,vy,vz,size) + return function(pos, node, player, pointed_thing) + for i=1,num do + minetest.add_particle({ + pos = pos, + velocity = {x=vx*(math.random()-.5), y=vy*(math.random()-.5), z=vz*(math.random()-.5)}, + acceleration = {x=0, y=0, z=0}, + expirationtime = 1, + size = size, + collisiondetection = false, + vertical = false, + texture = file, + playername = 'singleplayer' + }) + end + end +end +") + +(provide particles) +(define (particles img (num 30) (vx 2) (vy 2) (vz 2) (size 5)) + (ref-lua particles-def img num vx vy vz size)) + + + +(define-lua spawn-def +" +function(entity) + return function(pos, node, player, pointed_thing) + local new_pos = { + x=pos.x, + y=pos.y + 1, + z=pos.z + } + minetest.add_entity(new_pos, entity) + end +end +") + + +(provide spawn) +(define (spawn entity) + (ref-lua spawn-def entity)) + + + + + + +(define-lua on-punch-sequence-def +" +function(fs) + return function(pos, node, player, pointed_thing) + for i,f in ipairs(fs) do f(pos,node,player,pointed_thing) end + end +end +") + +(provide on-punch-sequence) +(define (on-punch-sequence . fs) + (ref-lua on-punch-sequence-def fs)) + diff --git a/mob-api-raw.rkt b/mob-api-raw.rkt new file mode 100644 index 0000000..d3d3ea7 --- /dev/null +++ b/mob-api-raw.rkt @@ -0,0 +1,559 @@ +#lang racket + +(provide mob-api-raw) +(define mob-api-raw + " +mobs = {} +function mobs:register_mob(name, def) + minetest.register_entity(name, { + hp_max = def.hp_max, + physical = true, + collisionbox = def.collisionbox, + visual = def.visual, + visual_size = def.visual_size, + mesh = def.mesh, + textures = def.textures, + makes_footstep_sound = def.makes_footstep_sound, + view_range = def.view_range, + walk_velocity = def.walk_velocity, + run_velocity = def.run_velocity, + damage = def.damage, + light_damage = def.light_damage, + water_damage = def.water_damage, + lava_damage = def.lava_damage, + disable_fall_damage = def.disable_fall_damage, + drops = def.drops, + armor = def.armor, + drawtype = def.drawtype, + on_rightclick = def.on_rightclick, + type = def.type, + attack_type = def.attack_type, + arrow = def.arrow, + shoot_interval = def.shoot_interval, + sounds = def.sounds, + animation = def.animation, + follow = def.follow, + jump = def.jump or true, + + timer = 0, + env_damage_timer = 0, -- only if state = 'attack' + attack = {player=nil, dist=nil}, + state = 'stand', + v_start = false, + old_y = nil, + lifetimer = 600, + tamed = false, + + set_velocity = function(self, v) + local yaw = self.object:getyaw() + if self.drawtype == 'side' then + yaw = yaw+(math.pi/2) + end + local x = math.sin(yaw) * -v + local z = math.cos(yaw) * v + self.object:setvelocity({x=x, y=self.object:getvelocity().y, z=z}) + end, + + get_velocity = function(self) + local v = self.object:getvelocity() + return (v.x^2 + v.z^2)^(0.5) + end, + + set_animation = function(self, type) + if not self.animation then + return + end + if not self.animation.current then + self.animation.current = '' + end + if type == 'stand' and self.animation.current ~~= 'stand' then + if + self.animation.stand_start + and self.animation.stand_end + and self.animation.speed_normal + then + self.object:set_animation( + {x=self.animation.stand_start,y=self.animation.stand_end}, + self.animation.speed_normal, 0 + ) + self.animation.current = 'stand' + end + elseif type == 'walk' and self.animation.current ~~= 'walk' then + if + self.animation.walk_start + and self.animation.walk_end + and self.animation.speed_normal + then + self.object:set_animation( + {x=self.animation.walk_start,y=self.animation.walk_end}, + self.animation.speed_normal, 0 + ) + self.animation.current = 'walk' + end + elseif type == 'run' and self.animation.current ~~= 'run' then + if + self.animation.run_start + and self.animation.run_end + and self.animation.speed_run + then + self.object:set_animation( + {x=self.animation.run_start,y=self.animation.run_end}, + self.animation.speed_run, 0 + ) + self.animation.current = 'run' + end + elseif type == 'punch' and self.animation.current ~~= 'punch' then + if + self.animation.punch_start + and self.animation.punch_end + and self.animation.speed_normal + then + self.object:set_animation( + {x=self.animation.punch_start,y=self.animation.punch_end}, + self.animation.speed_normal, 0 + ) + self.animation.current = 'punch' + end + end + end, + + on_step = function(self, dtime) + if self.type == 'monster' and minetest.setting_getbool('only_peaceful_mobs') then + self.object:remove() + end + + self.lifetimer = self.lifetimer - dtime + if self.lifetimer <= 0 and not self.tamed then + local player_count = 0 + for _,obj in ipairs(minetest.env:get_objects_inside_radius(self.object:getpos(), 20)) do + if obj:is_player() then + player_count = player_count+1 + end + end + if player_count == 0 and self.state ~~= 'attack' then + self.object:remove() + return + end + end + + if self.object:getvelocity().y > 0.1 then + local yaw = self.object:getyaw() + if self.drawtype == 'side' then + yaw = yaw+(math.pi/2) + end + local x = math.sin(yaw) * -2 + local z = math.cos(yaw) * 2 + self.object:setacceleration({x=x, y=-10, z=z}) + else + self.object:setacceleration({x=0, y=-10, z=0}) + end + + if self.disable_fall_damage and self.object:getvelocity().y == 0 then + if not self.old_y then + self.old_y = self.object:getpos().y + else + local d = self.old_y - self.object:getpos().y + if d > 5 then + local damage = d-5 + self.object:set_hp(self.object:get_hp()-damage) + if self.object:get_hp() == 0 then + self.object:remove() + end + end + self.old_y = self.object:getpos().y + end + end + + self.timer = self.timer+dtime + if self.state ~~= 'attack' then + if self.timer < 1 then + return + end + self.timer = 0 + end + + if self.sounds and self.sounds.random and math.random(1, 100) <= 1 then + minetest.sound_play(self.sounds.random, {object = self.object}) + end + + local do_env_damage = function(self) + local pos = self.object:getpos() + local n = minetest.env:get_node(pos) + + if self.light_damage and self.light_damage ~~= 0 + and pos.y>0 + and minetest.env:get_node_light(pos) + and minetest.env:get_node_light(pos) > 4 + and minetest.env:get_timeofday() > 0.2 + and minetest.env:get_timeofday() < 0.8 + then + self.object:set_hp(self.object:get_hp()-self.light_damage) + if self.object:get_hp() == 0 then + self.object:remove() + end + end + + if self.water_damage and self.water_damage ~~= 0 and + minetest.get_item_group(n.name, 'water') ~~= 0 + then + self.object:set_hp(self.object:get_hp()-self.water_damage) + if self.object:get_hp() == 0 then + self.object:remove() + end + end + + if self.lava_damage and self.lava_damage ~~= 0 and + minetest.get_item_group(n.name, 'lava') ~~= 0 + then + self.object:set_hp(self.object:get_hp()-self.lava_damage) + if self.object:get_hp() == 0 then + self.object:remove() + end + end + end + + self.env_damage_timer = self.env_damage_timer + dtime + if self.state == 'attack' and self.env_damage_timer > 1 then + self.env_damage_timer = 0 + do_env_damage(self) + elseif self.state ~~= 'attack' then + do_env_damage(self) + end + + if self.type == 'monster' and minetest.setting_getbool('enable_damage') then + for _,player in pairs(minetest.get_connected_players()) do + local s = self.object:getpos() + local p = player:getpos() + local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 + if dist < self.view_range then + if self.attack.dist then + if self.attack.dist < dist then + self.state = 'attack' + self.attack.player = player + self.attack.dist = dist + end + else + self.state = 'attack' + self.attack.player = player + self.attack.dist = dist + end + end + end + end + + if self.follow ~~= '' and not self.following then + for _,player in pairs(minetest.get_connected_players()) do + local s = self.object:getpos() + local p = player:getpos() + local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 + if self.view_range and dist < self.view_range then + self.following = player + end + end + end + + if self.following and self.following:is_player() then + if self.following:get_wielded_item():get_name() ~~= self.follow then + self.following = nil + self.v_start = false + else + local s = self.object:getpos() + local p = self.following:getpos() + local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 + if dist > self.view_range then + self.following = nil + self.v_start = false + else + local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z} + local yaw = math.atan(vec.z/vec.x)+math.pi/2 + if self.drawtype == 'side' then + yaw = yaw+(math.pi/2) + end + if p.x > s.x then + yaw = yaw+math.pi + end + self.object:setyaw(yaw) + if dist > 2 then + if not self.v_start then + self.v_start = true + self.set_velocity(self, self.walk_velocity) + else + if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then + local v = self.object:getvelocity() + v.y = 5 + self.object:setvelocity(v) + end + self.set_velocity(self, self.walk_velocity) + end + self:set_animation('walk') + else + self.v_start = false + self.set_velocity(self, 0) + self:set_animation('stand') + end + return + end + end + end + + if self.state == 'stand' then + if math.random(1, 4) == 1 then + self.object:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi)) + end + self.set_velocity(self, 0) + self.set_animation(self, 'stand') + if math.random(1, 100) <= 50 then + self.set_velocity(self, self.walk_velocity) + self.state = 'walk' + self.set_animation(self, 'walk') + end + elseif self.state == 'walk' then + if math.random(1, 100) <= 30 then + self.object:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi)) + end + if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then + local v = self.object:getvelocity() + v.y = 5 + self.object:setvelocity(v) + end + self:set_animation('walk') + self.set_velocity(self, self.walk_velocity) + if math.random(1, 100) <= 10 then + self.set_velocity(self, 0) + self.state = 'stand' + self:set_animation('stand') + end + elseif self.state == 'attack' and self.attack_type == 'dogfight' then + if not self.attack.player or not self.attack.player:is_player() then + self.state = 'stand' + self:set_animation('stand') + return + end + local s = self.object:getpos() + local p = self.attack.player:getpos() + local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 + if dist > self.view_range or self.attack.player:get_hp() <= 0 then + self.state = 'stand' + self.v_start = false + self.set_velocity(self, 0) + self.attack = {player=nil, dist=nil} + self:set_animation('stand') + return + else + self.attack.dist = dist + end + + local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z} + local yaw = math.atan(vec.z/vec.x)+math.pi/2 + if self.drawtype == 'side' then + yaw = yaw+(math.pi/2) + end + if p.x > s.x then + yaw = yaw+math.pi + end + self.object:setyaw(yaw) + if self.attack.dist > 2 then + if not self.v_start then + self.v_start = true + self.set_velocity(self, self.run_velocity) + else + if self.jump and self.get_velocity(self) <= 0.5 and self.object:getvelocity().y == 0 then + local v = self.object:getvelocity() + v.y = 5 + self.object:setvelocity(v) + end + self.set_velocity(self, self.run_velocity) + end + self:set_animation('run') + else + self.set_velocity(self, 0) + self:set_animation('punch') + self.v_start = false + if self.timer > 1 then + self.timer = 0 + if self.sounds and self.sounds.attack then + minetest.sound_play(self.sounds.attack, {object = self.object}) + end + self.attack.player:punch(self.object, 1.0, { + full_punch_interval=1.0, + damage_groups = {fleshy=self.damage} + }, vec) + end + end + elseif self.state == 'attack' and self.attack_type == 'shoot' then + if not self.attack.player or not self.attack.player:is_player() then + self.state = 'stand' + self:set_animation('stand') + return + end + local s = self.object:getpos() + local p = self.attack.player:getpos() + local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 + if dist > self.view_range or self.attack.player:get_hp() <= 0 then + self.state = 'stand' + self.v_start = false + self.set_velocity(self, 0) + self.attack = {player=nil, dist=nil} + self:set_animation('stand') + return + else + self.attack.dist = dist + end + + local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z} + local yaw = math.atan(vec.z/vec.x)+math.pi/2 + if self.drawtype == 'side' then + yaw = yaw+(math.pi/2) + end + if p.x > s.x then + yaw = yaw+math.pi + end + self.object:setyaw(yaw) + self.set_velocity(self, 0) + + if self.timer > self.shoot_interval and math.random(1, 100) <= 60 then + self.timer = 0 + + self:set_animation('punch') + + if self.sounds and self.sounds.attack then + minetest.sound_play(self.sounds.attack, {object = self.object}) + end + + local p = self.object:getpos() + p.y = p.y + (self.collisionbox[2]+self.collisionbox[5])/2 + local obj = minetest.env:add_entity(p, self.arrow) + local amount = (vec.x^2+vec.y^2+vec.z^2)^0.5 + local v = obj:get_luaentity().velocity + vec.y = vec.y+1 + vec.x = vec.x*v/amount + vec.y = vec.y*v/amount + vec.z = vec.z*v/amount + obj:setvelocity(vec) + end + end + end, + + on_activate = function(self, staticdata, dtime_s) + self.object:set_armor_groups({fleshy=self.armor}) + self.object:setacceleration({x=0, y=-10, z=0}) + self.state = 'stand' + self.object:setvelocity({x=0, y=self.object:getvelocity().y, z=0}) + self.object:setyaw(math.random(1, 360)/180*math.pi) + if self.type == 'monster' and minetest.setting_getbool('only_peaceful_mobs') then + self.object:remove() + end + self.lifetimer = 600 - dtime_s + if staticdata then + local tmp = minetest.deserialize(staticdata) + if tmp and tmp.lifetimer then + self.lifetimer = tmp.lifetimer - dtime_s + end + if tmp and tmp.tamed then + self.tamed = tmp.tamed + end + end + if self.lifetimer <= 0 and not self.tamed then + self.object:remove() + end + end, + + get_staticdata = function(self) + local tmp = { + lifetimer = self.lifetimer, + tamed = self.tamed, + } + return minetest.serialize(tmp) + end, + + on_punch = function(self, hitter) + if self.object:get_hp() <= 0 then + if hitter and hitter:is_player() and hitter:get_inventory() then + for _,drop in ipairs(self.drops) do + if math.random(1, drop.chance) == 1 then + hitter:get_inventory():add_item('main', ItemStack(drop.name..' '..math.random(drop.min, drop.max))) + end + end + end + end + end, + + }) +end + +mobs.spawning_mobs = {} +function mobs:register_spawn(name, nodes, max_light, min_light, chance, active_object_count, max_height, spawn_func) + mobs.spawning_mobs[name] = true + minetest.register_abm({ + nodenames = nodes, + neighbors = {'air'}, + interval = 30, + chance = chance, + action = function(pos, node, _, active_object_count_wider) + if active_object_count_wider > active_object_count then + return + end + if not mobs.spawning_mobs[name] then + return + end + pos.y = pos.y+1 + if not minetest.env:get_node_light(pos) then + return + end + if minetest.env:get_node_light(pos) > max_light then + return + end + if minetest.env:get_node_light(pos) < min_light then + return + end + if pos.y > max_height then + return + end + if minetest.env:get_node(pos).name ~~= 'air' then + return + end + pos.y = pos.y+1 + if minetest.env:get_node(pos).name ~~= 'air' then + return + end + if spawn_func and not spawn_func(pos, node) then + return + end + + if minetest.setting_getbool('display_mob_spawn') then + minetest.chat_send_all('[mobs] Add '..name..' at '..minetest.pos_to_string(pos)) + end + minetest.env:add_entity(pos, name) + end + }) +end + +function mobs:register_arrow(name, def) + minetest.register_entity(name, { + physical = false, + visual = def.visual, + visual_size = def.visual_size, + textures = def.textures, + velocity = def.velocity, + hit_player = def.hit_player, + hit_node = def.hit_node, + + on_step = function(self, dtime) + local pos = self.object:getpos() + if minetest.env:get_node(self.object:getpos()).name ~~= 'air' then + self.hit_node(self, pos, node) + self.object:remove() + return + end + pos.y = pos.y-1 + for _,player in pairs(minetest.env:get_objects_inside_radius(pos, 1)) do + if player:is_player() then + self.hit_player(self, player) + self.object:remove() + return + end + end + end + }) +end +") \ No newline at end of file