diff --git a/cmd/game/main.go b/cmd/game/main.go index d01e179..9642f4a 100644 --- a/cmd/game/main.go +++ b/cmd/game/main.go @@ -1,26 +1,26 @@ package main import ( - "context" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "lab.zaar.be/thefish/alchemyst-go/engine/ecs" - "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" - "lab.zaar.be/thefish/alchemyst-go/engine/gamemap/mapgens" - "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" - "lab.zaar.be/thefish/alchemyst-go/engine/items" - "lab.zaar.be/thefish/alchemyst-go/engine/mob" - "lab.zaar.be/thefish/alchemyst-go/engine/mob/movement" - "lab.zaar.be/thefish/alchemyst-go/engine/screens" - "lab.zaar.be/thefish/alchemyst-go/engine/types" - "lab.zaar.be/thefish/alchemyst-go/ui" - "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" - "lab.zaar.be/thefish/alchemyst-go/util" - "lab.zaar.be/thefish/alchemyst-go/util/appctx" - blt "lab.zaar.be/thefish/bearlibterminal" - "os" - "runtime" - "time" + "context" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "lab.zaar.be/thefish/alchemyst-go/engine/ecs" + "lab.zaar.be/thefish/alchemyst-go/engine/gamemap" + "lab.zaar.be/thefish/alchemyst-go/engine/gamemap/mapgens" + "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" + "lab.zaar.be/thefish/alchemyst-go/engine/items" + "lab.zaar.be/thefish/alchemyst-go/engine/mob" + "lab.zaar.be/thefish/alchemyst-go/engine/mob/movement" + "lab.zaar.be/thefish/alchemyst-go/engine/screens" + "lab.zaar.be/thefish/alchemyst-go/engine/types" + "lab.zaar.be/thefish/alchemyst-go/ui" + "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" + "lab.zaar.be/thefish/alchemyst-go/util" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" + blt "lab.zaar.be/thefish/bearlibterminal" + "os" + "runtime" + "time" ) var modifiers = []int{blt.TK_SHIFT, blt.TK_ALT, blt.TK_CONTROL} @@ -28,7 +28,7 @@ var modifiers = []int{blt.TK_SHIFT, blt.TK_ALT, blt.TK_CONTROL} // Рецепт чтобы убежать от [fatal] 'refresh' was not called from the main thread // https://github.com/golang/go/wiki/LockOSThread func init() { - runtime.LockOSThread() + runtime.LockOSThread() } //we can run logic in separate goroutines @@ -45,252 +45,252 @@ func init() { // } var State = gamestate.GameState{ - Mainfunc: make(chan func()), - Exit: make(chan struct{}, 1), - Input: make(chan string, 1), - RawInput: make(chan int, 1), - FovRecompute: make(chan struct{}, 1), - Redraw: make(chan struct{}, 1), + Mainfunc: make(chan func()), + Exit: make(chan struct{}, 1), + Input: make(chan string, 1), + RawInput: make(chan int, 1), + FovRecompute: make(chan struct{}, 1), + Redraw: make(chan struct{}, 1), } func main() { - config := util.LoadConfig() - var logLevels = map[string]zerolog.Level{"debug": zerolog.DebugLevel, "info": zerolog.InfoLevel, "warn": zerolog.WarnLevel} - var logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}).Level(logLevels[config.Verbosity]) + config := util.LoadConfig() + var logLevels = map[string]zerolog.Level{"debug": zerolog.DebugLevel, "info": zerolog.InfoLevel, "warn": zerolog.WarnLevel} + var logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}).Level(logLevels[config.Verbosity]) - // set up context - mainCtx := appctx.NewClientContext(config, &logger) + // set up context + mainCtx := appctx.NewClientContext(config, &logger) - //set up main window - mw := mainwindow.Init(mainCtx) - defer mw.Close() + //set up main window + mw := mainwindow.Init(mainCtx) + defer mw.Close() - setupLayers(mw) + setupLayers(mw) - //set up input decoder - go decodeInput(mainCtx, mw.GetLayer("base")) + //set up input decoder + go decodeInput(mainCtx, mw.GetLayer("base")) - //fixme set up (load / generate) level - move to game / enter or title / exit - //level, rooms := _default.DefaultGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) - //level, rooms := mapgens.DelaunayMstGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) - level, rooms := mapgens.DelaunayMstExtGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) - //level, rooms := mapgens.DelaunayPureGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) - State.Level = level + //fixme set up (load / generate) level - move to game / enter or title / exit + //level, rooms := _default.DefaultGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) + //level, rooms := mapgens.DelaunayMstGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) + level, rooms := mapgens.DelaunayMstExtGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) + //level, rooms := mapgens.DelaunayPureGen(mainCtx, gamemap.NewLevel(mainCtx, "test", 1)) + State.Level = level - sidebarWidth := 0 + sidebarWidth := 0 - //Set up viewport - vp := mainwindow.NewViewPort(sidebarWidth, 0, (mw.W - sidebarWidth), (mw.H - 0)) + //Set up viewport + vp := mainwindow.NewViewPort(sidebarWidth, 0, (mw.W - sidebarWidth), (mw.H - 0)) - //set up controller + //set up controller - controller := ecs.NewController(mainCtx) + controller := ecs.NewController(mainCtx) - controller.MapComponentClass(ecs.CoordsComponent, types.Coords{}) - controller.MapComponentClass(ecs.AppearanceComponent, types.Appearance{}) - controller.MapComponentClass(ecs.MobComponent, mob.Mob{}) - controller.MapComponentClass(ecs.MoveableComponent, movement.Moveable{}) - controller.MapComponentClass(ecs.CarriedComponent, movement.Moveable{}) - controller.MapComponentClass(ecs.UsableComponent, movement.Moveable{}) - controller.MapComponentClass(ecs.BackpackComponent, items.Backpack{}) + controller.MapComponentClass(ecs.CoordsComponent, types.Coords{}) + controller.MapComponentClass(ecs.AppearanceComponent, types.Appearance{}) + controller.MapComponentClass(ecs.MobComponent, mob.Mob{}) + controller.MapComponentClass(ecs.MoveableComponent, movement.Moveable{}) + controller.MapComponentClass(ecs.CarriedComponent, movement.Moveable{}) + controller.MapComponentClass(ecs.UsableComponent, movement.Moveable{}) + controller.MapComponentClass(ecs.BackpackComponent, items.Backpack{}) - moveable := movement.Moveable{ - Controller: controller, - Level: level, - } + moveable := movement.Moveable{ + Controller: controller, + Level: level, + } - items.Init(controller) + items.Init(controller) - bp := items.Backpack{MaxMass:100, MaxBulk:100} + bp := items.Backpack{MaxMass: 100, MaxBulk: 100} - //Set up Screen Manager - screenMgr := types.NewScreenManager(mainCtx) - screenMgr.AddScreen("title", screens.NewTitleScreen(mw, screenMgr)) - screenMgr.AddScreen("game", screens.NewGameScreen(mainCtx, mw, &State, vp, controller, screenMgr)) - screenMgr.AddScreen("help", screens.NewMenuScreen( - mw, - screenMgr, - "Help", - "Keybindings:", - //"[color=yellow]Note[/color]: Many of these are not implemented yet", - "[color=yellow]Note[/color]: Many of these are not implemented yet", - types.NewCenteredRect(mw.Rect, 50, 15), - true, ). - SetBgColor("#ef1d494f"). - SetFgColor("white"). - SetItems([]interface{}{ - "hjklyubn, NumPad 12346789, arrow keys - move", - "s or . - pass turn", - "g or , - pick up item", - "i - inventory", - "? - this screen", - "Ctrl+q - exit", - "f or F - fire or throw weapon", - "z or Z - cast a spell", - "p - pray", - "Ctrl+p - message log", - }).MakeList(), - ) + //Set up Screen Manager + screenMgr := types.NewScreenManager(mainCtx) + screenMgr.AddScreen("title", screens.NewTitleScreen(mw, screenMgr)) + screenMgr.AddScreen("game", screens.NewGameScreen(mainCtx, mw, &State, vp, controller, screenMgr)) + screenMgr.AddScreen("help", screens.NewMenuScreen( + mw, + screenMgr, + "Help", + "Keybindings:", + //"[color=yellow]Note[/color]: Many of these are not implemented yet", + "[color=yellow]Note[/color]: Many of these are not implemented yet", + types.NewCenteredRect(mw.Rect, 50, 15), + true). + SetBgColor("#ef1d494f"). + SetFgColor("white"). + SetItems([]interface{}{ + "hjklyubn, NumPad 12346789, arrow keys - move", + "s or . - pass turn", + "g or , - pick up item", + "i - inventory", + "? - this screen", + "Ctrl+q - exit", + "f or F - fire or throw weapon", + "z or Z - cast a spell", + "p - pray", + "Ctrl+p - message log", + }).MakeList(), + ) - inv := screens.InventoryScreen{ - MenuScreen: screens.NewMenuScreen( - mw, - screenMgr, - "Inventory", - "Items in your backpack:", - //"[color=yellow]Note[/color]: Many of these are not implemented yet", - "", - types.NewCenteredRect(mw.Rect, 70, 25), - true, ). - SetBgColor("#ef305c70"). - SetFgColor("white"), - } + inv := screens.InventoryScreen{ + MenuScreen: screens.NewMenuScreen( + mw, + screenMgr, + "Inventory", + "Items in your backpack:", + //"[color=yellow]Note[/color]: Many of these are not implemented yet", + "", + types.NewCenteredRect(mw.Rect, 70, 25), + true). + SetBgColor("#ef305c70"). + SetFgColor("white"), + } - screenMgr.AddScreen("devmenu", screens.NewDevmenuScreen( - mw, - controller, - screenMgr, - &State, - types.NewCenteredRect(mw.Rect, 70, 25), - true, - ).SetBgColor("#ef6d559d"). - SetFgColor("white"), - ) + screenMgr.AddScreen("devmenu", screens.NewDevmenuScreen( + mainCtx, + mw, + controller, + screenMgr, + &State, + types.NewCenteredRect(mw.Rect, 70, 25), + true, + ).SetBgColor("#ef6d559d"). + SetFgColor("white"), + ) - screenMgr.SetScreenByName("title") + screenMgr.SetScreenByName("title") - //fixme set up (load / generate) player - move to game / enter or title / exit - player := controller.CreateEntity([]ecs.Component{}) + //fixme set up (load / generate) player - move to game / enter or title / exit + player := controller.CreateEntity([]ecs.Component{}) - controller.AddComponent(player, types.Appearance{ - Glyph: types.PlainGlyphHolder{"@"}, - ColorSet: types.TileColorSet{ - Fg: types.PlainColorHolder{255, 255, 255, 255}, - }, - }) + controller.AddComponent(player, types.Appearance{ + Glyph: types.PlainGlyphHolder{"@"}, + ColorSet: types.TileColorSet{ + Fg: types.PlainColorHolder{255, 255, 255, 255}, + }, + }) - controller.AddComponent(player, rooms[0].Center) //implicit Coords - controller.AddComponent(player, moveable) - controller.AddComponent(player, bp) + controller.AddComponent(player, rooms[0].Center) //implicit Coords + controller.AddComponent(player, moveable) + controller.AddComponent(player, bp) - //fixme adding items - potion := controller.CreateEntity([]ecs.Component{}) - controller.AddComponent(potion, types.Appearance{ - Glyph: types.PlainGlyphHolder{"!"}, - ColorSet: types.TileColorSet{ - Fg: types.PlainColorHolder{255, 55, 255, 222}, - }, - }) - controller.AddComponent(potion, rooms[0].Center) //implicit Coords - controller.AddComponent(potion, items.Carried{Mass:5, Bulk:3}) - controller.AddComponent(potion, items.Usable{}) - controller.AddComponent(potion, items.Consumable{}) - controller.AddComponent(potion, ecs.Named{Name:"first potion"}) + //fixme adding items + potion := controller.CreateEntity([]ecs.Component{}) + controller.AddComponent(potion, types.Appearance{ + Glyph: types.PlainGlyphHolder{"!"}, + ColorSet: types.TileColorSet{ + Fg: types.PlainColorHolder{255, 55, 255, 222}, + }, + }) + controller.AddComponent(potion, rooms[0].Center) //implicit Coords + controller.AddComponent(potion, items.Carried{Mass: 5, Bulk: 3}) + controller.AddComponent(potion, items.Usable{}) + controller.AddComponent(potion, items.Consumable{}) + controller.AddComponent(potion, ecs.Named{Name: "first potion"}) - potion2 := controller.CreateEntity([]ecs.Component{}) - controller.AddComponent(potion2, types.Appearance{ - Glyph: types.PlainGlyphHolder{"!"}, - ColorSet: types.TileColorSet{ - Fg: types.PlainColorHolder{255, 222, 255, 55}, - }, - }) - controller.AddComponent(potion2, rooms[1].Center) //implicit Coords - controller.AddComponent(potion2, items.Carried{Mass:5, Bulk:3}) - controller.AddComponent(potion2, items.Usable{}) - controller.AddComponent(potion2, items.Consumable{}) - controller.AddComponent(potion2, ecs.Named{Name:"second potion"}) - //fixme end setting up items + potion2 := controller.CreateEntity([]ecs.Component{}) + controller.AddComponent(potion2, types.Appearance{ + Glyph: types.PlainGlyphHolder{"!"}, + ColorSet: types.TileColorSet{ + Fg: types.PlainColorHolder{255, 222, 255, 55}, + }, + }) + controller.AddComponent(potion2, rooms[1].Center) //implicit Coords + controller.AddComponent(potion2, items.Carried{Mass: 5, Bulk: 3}) + controller.AddComponent(potion2, items.Usable{}) + controller.AddComponent(potion2, items.Consumable{}) + controller.AddComponent(potion2, ecs.Named{Name: "second potion"}) + //fixme end setting up items - State.Player = player - State.Controller = controller + State.Player = player + State.Controller = controller - screenMgr.AddScreen("inventory", inv.MakeInverntory(player)) + screenMgr.AddScreen("inventory", inv.MakeInverntory(player)) + //but every call to bearlibterminal must be wrapped to closure and passed to mainfunc + var exit = false + for !exit { - //but every call to bearlibterminal must be wrapped to closure and passed to mainfunc - var exit = false - for !exit { + select { + case State.RawInput <- ui.ReadKeyCode(): + break + case pressed := <-State.Input: + screenMgr.CurrentScreen.HandleInput(pressed) + break + //case f := <-State.mainfunc: + // f() + // break + case <-State.Exit: + appctx.Logger(mainCtx).Warn().Msg("quitting NOW") + exit = true + break + // не оставляйте default в бесконечном select {} - сожрет всё CPU + default: + screenMgr.CurrentScreen.Render() + blt.Layer(0) //return to base layer + blt.Refresh() + } - select { - case State.RawInput <- ui.ReadKeyCode(): - break - case pressed := <-State.Input: - screenMgr.CurrentScreen.HandleInput(pressed) - break - //case f := <-State.mainfunc: - // f() - // break - case <-State.Exit: - appctx.Logger(mainCtx).Warn().Msg("quitting NOW") - exit = true - break - // не оставляйте default в бесконечном select {} - сожрет всё CPU - default: - screenMgr.CurrentScreen.Render() - blt.Layer(0) //return to base layer - blt.Refresh() - } - - } - appctx.Logger(mainCtx).Info().Msg("pre-shutdown sequence") + } + appctx.Logger(mainCtx).Info().Msg("pre-shutdown sequence") } func setupLayers(mainwindow *mainwindow.MainWindow) { - mainwindow.AddLayer("base", 0, "white") - mainwindow.AddLayer("overlay", 1, "white") - mainwindow.AddLayer("menubg", 2, "white") - mainwindow.AddLayer("menu", 3, "white") + mainwindow.AddLayer("base", 0, "white") + mainwindow.AddLayer("overlay", 1, "white") + mainwindow.AddLayer("menubg", 2, "white") + mainwindow.AddLayer("menu", 3, "white") } func decodeInput(ctx context.Context, baseLayer *mainwindow.Layer) { - var exit = false - var waitForWCspam = true - for !exit { - select { - case keycode := <-State.RawInput: - if keycode == blt.TK_NONE { - continue - } - if keycode == blt.TK_CLOSE && !waitForWCspam { - appctx.Logger(ctx).Warn().Msg("exiting on window close...") - State.Exit <- struct{}{} - appctx.Logger(ctx).Warn().Msg("...done") - return - } - var pressed = "" - var isModifier, _ = util.IntInSlice(keycode, modifiers) - if !isModifier { + var exit = false + var waitForWCspam = true + for !exit { + select { + case keycode := <-State.RawInput: + if keycode == blt.TK_NONE { + continue + } + if keycode == blt.TK_CLOSE && !waitForWCspam { + appctx.Logger(ctx).Warn().Msg("exiting on window close...") + State.Exit <- struct{}{} + appctx.Logger(ctx).Warn().Msg("...done") + return + } + var pressed = "" + var isModifier, _ = util.IntInSlice(keycode, modifiers) + if !isModifier { - pressed = ui.Scancodemap[keycode] + pressed = ui.Scancodemap[keycode] - if blt.Check(blt.TK_SHIFT) != 0 { - pressed = "Shift+" + pressed - } - if blt.Check(blt.TK_ALT) != 0 { - pressed = "Alt+" + pressed - } - if blt.Check(blt.TK_CONTROL) != 0 { - pressed = "Ctrl+" + pressed - } + if blt.Check(blt.TK_SHIFT) != 0 { + pressed = "Shift+" + pressed + } + if blt.Check(blt.TK_ALT) != 0 { + pressed = "Alt+" + pressed + } + if blt.Check(blt.TK_CONTROL) != 0 { + pressed = "Ctrl+" + pressed + } - //global hotkeys - switch pressed { - case "Ctrl+q": - //fallthrough - //case "Escape": - appctx.Logger(ctx).Info().Msg("exiting on quit command...") - State.Exit <- struct{}{} - appctx.Logger(ctx).Info().Msg("...done") - exit = true - return - default: - if pressed != "" { - waitForWCspam = false; + //global hotkeys + switch pressed { + case "Ctrl+q": + //fallthrough + //case "Escape": + appctx.Logger(ctx).Info().Msg("exiting on quit command...") + State.Exit <- struct{}{} + appctx.Logger(ctx).Info().Msg("...done") + exit = true + return + default: + if pressed != "" { + waitForWCspam = false State.Input <- pressed - } - } - } - } - } + } + } + } + } + } } diff --git a/delaunay_test.go b/delaunay_test.go index 42864bb..094de35 100644 --- a/delaunay_test.go +++ b/delaunay_test.go @@ -1,37 +1,37 @@ package alchemyst_go import ( - "lab.zaar.be/thefish/alchemyst-go/engine/types" - "lab.zaar.be/thefish/alchemyst-go/util/delaunay" - "testing" + "lab.zaar.be/thefish/alchemyst-go/engine/types" + "lab.zaar.be/thefish/alchemyst-go/util/delaunay" + "testing" ) func TestDelaunay(t *testing.T) { - coords := []types.Coords{ - {10,10}, - {10,60}, - {30,10}, - {40,20}, - {60,10}, - {40,60}, - } + coords := []types.Coords{ + {10, 10}, + {10, 60}, + {30, 10}, + {40, 20}, + {60, 10}, + {40, 60}, + } - expected := []types.Edge{ - {types.Coords{10, 60}, types.Coords{10, 10}}, - {types.Coords{30, 10}, types.Coords{40, 20}}, - {types.Coords{60, 10}, types.Coords{40, 60}}, - {types.Coords{40, 20}, types.Coords{40, 60}}, - {types.Coords{10, 10,}, types.Coords{30, 10}}, - } + expected := []types.Edge{ + {types.Coords{10, 60}, types.Coords{10, 10}}, + {types.Coords{30, 10}, types.Coords{40, 20}}, + {types.Coords{60, 10}, types.Coords{40, 60}}, + {types.Coords{40, 20}, types.Coords{40, 60}}, + {types.Coords{10, 10}, types.Coords{30, 10}}, + } - result := delaunay.GetMst(coords, 100, 100) + result := delaunay.GetMst(coords, 100, 100, 0) - for idx, _ := range result { - if result[idx] != expected[idx] { - t.Errorf("Failed, expected %v. got %v", result[idx], expected[idx]) - } + for idx, _ := range result { + if result[idx] != expected[idx] { + t.Errorf("Failed, expected %v. got %v", result[idx], expected[idx]) + } - } - t.Log("output: ", result) + } + t.Log("output: ", result) } diff --git a/engine/items/itemprops/armor.go b/engine/items/itemprops/armor.go new file mode 100644 index 0000000..b882cb4 --- /dev/null +++ b/engine/items/itemprops/armor.go @@ -0,0 +1,21 @@ +package itemprops + +import "github.com/shopspring/decimal" + +type ArmorProfile struct { + LayerExtra Armored + LayerOuter Armored + LayerMiddle Armored + LayerInner Armored +} + +type Armored struct { + ItemPhysics + Coverage Coverage +} + +//Coverage is set of partial coverage from 0 to 1 (0 to 100%) +type Coverage struct { + Frontal decimal.Decimal + Rear decimal.Decimal +} diff --git a/engine/items/itemprops/body.go b/engine/items/itemprops/body.go new file mode 100644 index 0000000..42a23dd --- /dev/null +++ b/engine/items/itemprops/body.go @@ -0,0 +1,148 @@ +package itemprops + +//MedicalSystem организм +// Humanoid +// Circuits +// Intake +// +// Breathe: Vessel: Air intake >> mouth/nose -> trachea -> lungs +// Vessel: Blood >> heart -> lungs -> brain -> heart +// Eat: +// Vessel: food >> mouth -> jaws +// Vessel: pulp >> esophagus -> stomach +// Congestion: +// Vessel: Blood >> heart -> guts -> system -> liver -> heart +// Vessel: pulp >> stomach -> guts -> output +// Vessel: bile >> liver -> stomach -> guts +// Fast Congestion +// Vessel: liquid >> stomach -> guts -> kidney -> bladder -> pulp output +// Vessel: Blood >> heart -> guts -> system -> kidney -> heart +// Blood сirculation: +// Vessel: blood >> heart -> system -> spleen -> heart +// -> brain -> heart +// Vision: +// Vessel: Nerve signal >> eye -> brain +// Smell: +// Vessel: Air intake >> nose +// Vessel: Nerve signal >> nose -> brain +// Hearing: +// Vessel: Air pressure >> ear +// Vessel: Nerve signal >> ear -> brain +// Touching: +// Vessel: Phys pressure/Temperature/Solvent >> skin -> nerve tissue -> brain +// Motion Sense: +// Vessel: Air pressure >> ear/nose -> inner ear -> brain [feeling fast-moving items] +// Motion: +// Vessel: Gravity >> inner ear -> brain [equilibrium] +// Vessel: Nerve signal >> brain -> major nerve -> [...muscle -> tendon -> bone/joint] -> nerve tissue -> brain +// Structural: +// Vessel: Nerve signal >> brain -> spinal brain -> [...muscle] -> nerve tissue -> brain +// Psychic: +// Vessel: Nerve signal >> brain -> spinal brain -> brain +// Consciousness: +// Vessel: Nerve signal >> brain -> brain +// Misc +// Hand Grip ???: +// Vessel: Nerve signal >> palm -> fingers with off-thumb +// Stance +// Body structure: +// BasePart -> chest -> spine -> joint -> head +// -> spine -> lowerbody +// -> [left] joint -> shoulder -> joint -> arm -> joint -> palm -> 5 x finger +// -> [right] joint -> shoulder -> joint -> arm -> joint -> palm -> 5 x finger +// -> lowerbody +// -> [left] joint -> leg -> joint -> hip -> joint -> foot -> 5 x finger +// -> [right] joint -> leg -> joint -> hip -> joint -> foot -> 5 x finger +// -> head -> joint -> jaw + +//MedicalSystem Организм +type MedicalSystem struct { + BasePart BodyPart +} + +//MedicalCircuit Система обращения +type MedicalCircuit struct { + Provides MedicalAbility + DependsOn Organ + Vessel MedicalVessel + Contains []Organ +} + +//MedicalVessel кровь, желчь, пульпа, воздух, еда +type MedicalVessel struct { + Name string + Material + Pressure DimensionItemDensity +} + +//BodyPart часть тела +type BodyPart struct { + LayerExtra MedicalMaterial + LayerOuter MedicalMaterial + LayerMiddle MedicalMaterial + LayerInner MedicalMaterial + + Joints []Joint + Contains []InnerOrgan + Exposes []OuterOrgan +} + +//Joint суставы, к чему и что крепится +type Joint struct { + Name string + ConnectsFrom BodyPart + ConnectsTo BodyPart +} + +type Organ struct { + Name string + Material +} + +//InnerOrgan ливер, селезёнка, сердце, кишки итп +type InnerOrgan struct { + Organ + DependsOn MedicalCircuit + BelongsTo MedicalCircuit +} + +//OuterOrgan глаза, уши, волосы, когти итп +type OuterOrgan struct { + Organ + DependsOn MedicalCircuit + BelongsTo MedicalCircuit +} + +//слой части тела - кожа/чешуя/роговые пластины/хитиновый панцирь, жир, мускулы, кости +type MedicalMaterial struct { + Name string + Material + MedicalSystemFlags +} + +//@todo заменить на Medical Circuit +type MedicalSystemFlags struct { + //Structural является ли опорным аппаратом + Structural bool + //Содежит ли кровь/ихор/ + MajorVeins bool //вход на мотор, сломаешь - быстро выйдет из строя если будет двигаться + MajorArteria bool //выход, то же самое + высокое давление + + Veins bool //вход на мотор + Arteria bool //выход из мотора, высокое давление + + MajorNerve bool //повредишь - ниже по суставам не работает + NerveTissue bool //повредишь - ниже по суставамс болит + + OxygenTube bool //трахея + OxygenPump bool //лёгкое + + BloodPump bool //мотор + + ContainsCongestionLiquid bool + + IsMainCongestionPump bool +} + +//MedicalAbility спсобность есть, стоять, не терять равновесие, дышать, выздоравливать, лечить свои органы, видеть итп +type MedicalAbility string diff --git a/engine/items/itemprops/item_physics.go b/engine/items/itemprops/item_physics.go new file mode 100644 index 0000000..2e32042 --- /dev/null +++ b/engine/items/itemprops/item_physics.go @@ -0,0 +1,37 @@ +package itemprops + +import "github.com/shopspring/decimal" + +type ItemPhysics struct { + Material Material + Rigidity DimensionItemRigidity + Size DimensionItemSize + Temperature DimensionItemTemperature +} + +//DimensionItemSize length in m (1 mm = 1/1000 of 1m) +type DimensionItemSize struct { + Width decimal.Decimal + Height decimal.Decimal + // if item is solid - depth in m (1mm = 1/1000 of m) + Depth decimal.NullDecimal + //Thickness if item is hollow - thickness of outer item shell, ie for armor, in m (1 mm = 1/1000 of m) + Thickness decimal.NullDecimal +} + +//Area is frontal area +func (d *DimensionItemSize) Area() decimal.Decimal { + return d.Width.Mul(d.Height) +} + +//DimensionItemDensity density in kg/m3 +type DimensionItemDensity decimal.Decimal + +//DimensionItemRigidity rigidity жёсткость, способность твёрдого тела, конструкции или её элементов сопротивляться деформации in N/m +type DimensionItemRigidity decimal.Decimal + +//NotchFractureToughness ударная вязкость по Шарпи, Дж (надо ли?) +type NotchFractureToughness decimal.Decimal + +//DimensionItemTemperature in celsius, -273 to 10000 +type DimensionItemTemperature decimal.Decimal diff --git a/engine/items/itemprops/material.go b/engine/items/itemprops/material.go new file mode 100644 index 0000000..2cc4100 --- /dev/null +++ b/engine/items/itemprops/material.go @@ -0,0 +1,20 @@ +package itemprops + +type Material struct { + Name string + Flags MaterialFlags + Density DimensionItemDensity + FractureToughness NotchFractureToughness + MeltingPoint DimensionItemTemperature + BoilingPoint DimensionItemTemperature +} + +type MaterialFlags struct { + ConductsElictricity bool + BlocksLiquid bool + AcidResistant bool + BlocksGas bool + Flammable bool + ConductsHeat bool + Radiates bool +} diff --git a/engine/screens/devmenu.go b/engine/screens/devmenu.go index edbcca8..8ceecc2 100644 --- a/engine/screens/devmenu.go +++ b/engine/screens/devmenu.go @@ -1,48 +1,52 @@ package screens import ( - "fmt" - "lab.zaar.be/thefish/alchemyst-go/effects" - "lab.zaar.be/thefish/alchemyst-go/engine/ecs" - "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" - "lab.zaar.be/thefish/alchemyst-go/engine/types" - "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" - "strings" + "context" + "fmt" + "lab.zaar.be/thefish/alchemyst-go/effects" + "lab.zaar.be/thefish/alchemyst-go/engine/ecs" + "lab.zaar.be/thefish/alchemyst-go/engine/gamestate" + "lab.zaar.be/thefish/alchemyst-go/engine/types" + "lab.zaar.be/thefish/alchemyst-go/ui/mainwindow" + "lab.zaar.be/thefish/alchemyst-go/util/appctx" + "strings" ) type DevmenuScreen struct { - mw *mainwindow.MainWindow - controller *ecs.Controller - scm *types.ScreenManager - state *gamestate.GameState - types.Rect + ctx context.Context + mw *mainwindow.MainWindow + controller *ecs.Controller + scm *types.ScreenManager + state *gamestate.GameState + types.Rect - renderParent bool + renderParent bool - bgColor string - fgColor string + bgColor string + fgColor string } -func NewDevmenuScreen(mw *mainwindow.MainWindow, controller *ecs.Controller, scm *types.ScreenManager, state *gamestate.GameState, rect types.Rect, renderParent bool) *DevmenuScreen { - return &DevmenuScreen{ - mw: mw, - controller: controller, - scm: scm, - state: state, +func NewDevmenuScreen(ctx context.Context, mw *mainwindow.MainWindow, controller *ecs.Controller, scm *types.ScreenManager, state *gamestate.GameState, rect types.Rect, renderParent bool) *DevmenuScreen { + return &DevmenuScreen{ + ctx: ctx, + mw: mw, + controller: controller, + scm: scm, + state: state, - Rect: rect, - renderParent: renderParent, - } + Rect: rect, + renderParent: renderParent, + } } func (devm *DevmenuScreen) SetBgColor(color string) *DevmenuScreen { - devm.bgColor = color - return devm + devm.bgColor = color + return devm } func (devm *DevmenuScreen) SetFgColor(color string) *DevmenuScreen { - devm.fgColor = color - return devm + devm.fgColor = color + return devm } func (devm *DevmenuScreen) UseEcs() bool { return false } @@ -50,66 +54,66 @@ func (devm *DevmenuScreen) Enter() { } func (devm *DevmenuScreen) HandleInput(input string) { - switch input { - case "i": - level := devm.state.Level - for idx, _ := range level.Tiles { - level.Tiles[idx].Visible = false - level.Tiles[idx].Explored = false - } - devm.scm.SetScreen(devm.scm.PreviousScreen) - break - case "v": - level := devm.state.Level - for idx, _ := range level.Tiles { - level.Tiles[idx].Visible = true - level.Tiles[idx].Explored = true - } - fmt.Printf("making everything visible!") - devm.scm.SetScreen(devm.scm.PreviousScreen) - break - case "p": - if devm.controller.HasComponent(devm.state.Player, effects.BuffPassWall) { - devm.controller.RemoveComponent(devm.state.Player, effects.BuffPassWall) - } else { - devm.controller.AddComponent(devm.state.Player, effects.PassWall{}) - } - case "Escape": - fallthrough - case "Space": - devm.scm.SetScreen(devm.scm.PreviousScreen) - break - } + switch input { + case "i": + level := devm.state.Level + for idx, _ := range level.Tiles { + level.Tiles[idx].Visible = false + level.Tiles[idx].Explored = false + } + devm.scm.SetScreen(devm.scm.PreviousScreen) + break + case "v": + level := devm.state.Level + for idx, _ := range level.Tiles { + level.Tiles[idx].Visible = true + level.Tiles[idx].Explored = true + } + appctx.Logger(devm.ctx).Warn().Msg("making everything visible!") + devm.scm.SetScreen(devm.scm.PreviousScreen) + break + case "p": + if devm.controller.HasComponent(devm.state.Player, effects.BuffPassWall) { + devm.controller.RemoveComponent(devm.state.Player, effects.BuffPassWall) + } else { + devm.controller.AddComponent(devm.state.Player, effects.PassWall{}) + } + case "Escape": + fallthrough + case "Space": + devm.scm.SetScreen(devm.scm.PreviousScreen) + break + } } func (devm *DevmenuScreen) Exit() { - if devm.renderParent { - devm.scm.PreviousScreen.Render() - } - menuLayer := devm.mw.GetLayer("menu") - menuLayer.ClearRect(devm.Rect) - bgLayer := devm.mw.GetLayer("menubg") - bgLayer.ClearRect(devm.Rect) + if devm.renderParent { + devm.scm.PreviousScreen.Render() + } + menuLayer := devm.mw.GetLayer("menu") + menuLayer.ClearRect(devm.Rect) + bgLayer := devm.mw.GetLayer("menubg") + bgLayer.ClearRect(devm.Rect) } func (devm *DevmenuScreen) Render() { - menuLayer := devm.mw.GetLayer("menu") - menuLayer.ClearRect(devm.Rect) - bgLayer := devm.mw.GetLayer("menubg") - bgLayer.ClearRect(devm.Rect) - bgLayer.WithColor(devm.bgColor).NewWindow(devm.Rect).NoBorder() + menuLayer := devm.mw.GetLayer("menu") + menuLayer.ClearRect(devm.Rect) + bgLayer := devm.mw.GetLayer("menubg") + bgLayer.ClearRect(devm.Rect) + bgLayer.WithColor(devm.bgColor).NewWindow(devm.Rect).NoBorder() - menuLayer.WithColor(devm.fgColor).PrintInside( - devm.Rect, - strings.Join([]string{ - "Действия для разработчика:", - "[color=green]v[/color] - set all tiles visible", - "[color=green]i[/color] - set all tiles invisible", - fmt.Sprintf("[color=green]p[/color] - toggle passwall: %v", - devm.controller.HasComponent(devm.state.Player, effects.BuffPassWall), - ), - }, "\n"), - 1, - ) - menuLayer.Print(devm.X+2, devm.Y+devm.H-1, "[color=green]Space[/color] to close") + menuLayer.WithColor(devm.fgColor).PrintInside( + devm.Rect, + strings.Join([]string{ + "Действия для разработчика:", + "[color=green]v[/color] - set all tiles visible", + "[color=green]i[/color] - set all tiles invisible", + fmt.Sprintf("[color=green]p[/color] - toggle passwall: %v", + devm.controller.HasComponent(devm.state.Player, effects.BuffPassWall), + ), + }, "\n"), + 1, + ) + menuLayer.Print(devm.X+2, devm.Y+devm.H-1, "[color=green]Space[/color] to close") } diff --git a/go.mod b/go.mod index bedfbfa..a97aca6 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.12 require ( github.com/gammazero/deque v0.0.0-20190521012701-46e4ffb7a622 github.com/rs/zerolog v1.15.0 + github.com/shopspring/decimal v1.3.1 lab.zaar.be/thefish/bearlibterminal v0.0.0-20191018101635-dd37bbc90d77 ) diff --git a/go.sum b/go.sum index 3789a34..21e95a5 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.15.0 h1:uPRuwkWF4J6fGsJ2R0Gn2jB1EQiav9k3S6CSdygQJXY= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=