diff options
author | jacopo grandi <jak.sk8@hotmail.it> | 2021-02-18 14:14:23 +0100 |
---|---|---|
committer | jacopo grandi <jak.sk8@hotmail.it> | 2021-02-18 14:14:23 +0100 |
commit | 5f0fce4191309e9526b7109a0d87c092ce6a4193 (patch) | |
tree | 105257f876551814aa74a0760ec116bd1bf307a5 | |
parent | ead78d51e662057467b79d3a65b20c4ba83cbf07 (diff) |
main
56 files changed, 4972 insertions, 1 deletions
@@ -1 +1,8 @@ -# arena
\ No newline at end of file +# hello + +in order to compile +* have the sdl2 library at C:\MinGW_libs\include +* have the pylibsys library at C:\MinGW_libs\include +* have .a files in C:\MinGW_libs\libs + +run lcb (link compile build), build will be in build folder diff --git a/build/SDL2.dll b/build/SDL2.dll Binary files differnew file mode 100644 index 0000000..3131862 --- /dev/null +++ b/build/SDL2.dll diff --git a/build/SDL2_mixer.dll b/build/SDL2_mixer.dll Binary files differnew file mode 100644 index 0000000..40bb1c1 --- /dev/null +++ b/build/SDL2_mixer.dll diff --git a/build/army/army.txt b/build/army/army.txt Binary files differnew file mode 100644 index 0000000..ae1c3b5 --- /dev/null +++ b/build/army/army.txt diff --git a/build/army/army2.txt b/build/army/army2.txt Binary files differnew file mode 100644 index 0000000..ae1c3b5 --- /dev/null +++ b/build/army/army2.txt diff --git a/build/content/armor.txt b/build/content/armor.txt new file mode 100644 index 0000000..f418779 --- /dev/null +++ b/build/content/armor.txt @@ -0,0 +1,57 @@ +[ + { + "name": "metal plating", + "weight": "50", + "pierce": "5", "spread": "8" + }, + { + "name": "heavy metal plating", + "weight": "80", + "pierce": "7", "spread": "10", "impact": "5" + }, + { + "name": "reflective plating", + "weight": "40", + "laser": "10" + }, + { + "name": "heat resistent plating", + "weight": "50", + "fusion": "8" + }, + { + "name": "padding", + "weight": "20", + "spread": "5", "impact": "8" + }, + { + "name": "reactive armor", + "weight": "75", + "explosive": "12" + }, + { + "name": "energy shields", + "weight": "25", + "pierce": "3", "spread": "3", "fusion": "3", "explosive": "3", "laser": "3" + }, + { + "name": "composite armor", + "weight": "30", + "pierce": "6", "spread": "4", "impact": "3" + }, + { + "name": "plastic armor", + "weight": "10", + "pierce": "4" + }, + { + "name": "sloped steel armor", + "weight": "45", + "pierce": "10", "spread": "8" + }, + { + "name": "charged armor", + "weight": "100", + "explosive": "25" + }, +]
\ No newline at end of file diff --git a/build/content/augments.txt b/build/content/augments.txt new file mode 100644 index 0000000..c98e1d1 --- /dev/null +++ b/build/content/augments.txt @@ -0,0 +1,97 @@ +[ + { + "name": "charged ammo", + "weight": "10", + "damage_emp": "5" + }, + { + "name": "fusion ammo", + "weight": "10", + "damage_fusion": "4" + }, + { + "name": "explosive ammo", + "weight": "30", + "armor_explosive": "8" + }, + { + "name": "radiator", + "weight": "10", + "armor_fusion": "2" + }, + { + "name": "priority module", + "weight": "0" + }, + { + "name": "communication array", + "weight": "50", + "armor_pierce": "1", + "armor_impact": "1", + "armor_fusion": "1", + "aoe": "2" + }, + { + "name": "long range targeting", + "weight": "0", + "add_range": "1" + }, + { + "name": "long range targeting", + "weight": "0", + "range": "1" + }, + { + "name": "fast target acquisition", + "weight": "5", + "add_cooldown": "-0.1" + }, + { + "name": "overcharger", + "weight": "10", + "damage_laser": "8", + "recharge": "-5" + }, + { + "name": "focus lens", + "weight": "3", + "damage_laser": "3" + }, + { + "name": "amplifier", + "weight": "30", + "damage_laser": "3", + "damage_fusion": "5" + }, + { + "name": "shrapnel", + "weight": "5", + "damage_explosive": "5" + }, + { + "name": "reloader", + "weight": "40", + "add_cooldown": "-0.1" + }, + { + "name": "anti jamming device", + "weight": "2", + "armor_emp": "5" + }, + { + "name": "weight stripping", + "weight": "-10", + "add_hp": "-10" + }, + { + "name": "barebone weapon setup", + "weight": "-30", + "damage_pierce": "-25", + "damage_laser": "-25", + "damage_impact": "-25", + "damage_fusion": "-25", + "damage_explosive": "-25", + "damage_emp": "-25", + "damage_spread": "-25" + } +]
\ No newline at end of file diff --git a/build/content/batteries.txt b/build/content/batteries.txt new file mode 100644 index 0000000..fe5da27 --- /dev/null +++ b/build/content/batteries.txt @@ -0,0 +1,34 @@ +[ + { + "name": "small alkaline pack", + "weight": "0", "capacity": "50" + }, + { + "name": "big alkaline pack", + "weight": "2", "capacity": "200" + }, + { + "name": "small lithium pack", + "weight": "5", "capacity": "150", "recharge": "1" + }, + { + "name": "big lithium pack", + "weight": "15", "capacity": "500", "recharge": "1" + }, + { + "name": "lead battery", + "weight": "20", "capacity": "800", "recharge": "1" + }, + { + "name": "small molten salt battery", + "weight": "40", "capacity": "1500", "recharge": "1" + }, + { + "name": "big molten salt battery", + "weight": "70", "capacity": "2000", "recharge": "1" + }, + { + "name": "atomic battery", + "weight": "150", "capacity": "10000" + } +]
\ No newline at end of file diff --git a/build/content/brains.txt b/build/content/brains.txt new file mode 100644 index 0000000..c9bb4b5 --- /dev/null +++ b/build/content/brains.txt @@ -0,0 +1,20 @@ +[ + { + "name": "search and destroy" + }, + { + "name": "follower" + }, + { + "name": "defensive" + }, + { + "name": "kamikaze" + }, + { + "name": "run and gun" + }, + { + "name": "flank" + } +]
\ No newline at end of file diff --git a/build/content/chassis.txt b/build/content/chassis.txt new file mode 100644 index 0000000..e4643c2 --- /dev/null +++ b/build/content/chassis.txt @@ -0,0 +1,180 @@ +[ + { + "name": "light two legged bot", + "slot_weapon": "1", + "slot_armor": "0", + "slot_aug": "1", + "weight_max": "20", + "hp": "100", + "speed": "1.5" + }, + { + "name": "heavy two legged bot", + "slot_weapon": "1", + "slot_armor": "1", + "slot_aug": "3", + "weight_max": "45", + "hp": "350", + "speed": "1" + }, + { + "name": "light four legged bot", + "slot_weapon": "2", + "slot_armor": "1", + "slot_aug": "2", + "weight_max": "50", + "hp": "400", + "speed": "1" + }, + { + "name": "heavy four legged bot", + "slot_weapon": "2", + "slot_armor": "2", + "slot_aug": "5", + "weight_max": "150", + "hp": "1200", + "speed": "0.67" + }, + { + "name": "light six legged bot", + "slot_weapon": "2", + "slot_armor": "2", + "slot_aug": "3", + "weight_max": "210", + "hp": "640", + "speed": "1" + }, + { + "name": "heavy six legged bot", + "slot_weapon": "2", + "slot_armor": "4", + "slot_aug": "6", + "weight_max": "300", + "hp": "1500", + "speed": "1" + }, + { + "name": "light buggy", + "slot_weapon": "1", + "slot_armor": "1", + "slot_aug": "1", + "weight_max": "50", + "hp": "200", + "speed": "1" + }, + { + "name": "buggy", + "slot_weapon": "2", + "slot_armor": "2", + "slot_aug": "2", + "weight_max": "150", + "hp": "400", + "speed": "1" + }, + { + "name": "light wheeled vehicle", + "slot_weapon": "1", + "slot_armor": "0", + "slot_aug": "2", + "weight_max": "60", + "hp": "320", + "speed": "1", + "recharge": "0.3" + }, + { + "name": "medium wheeled vehicle", + "slot_weapon": "2", + "slot_armor": "2", + "slot_aug": "3", + "weight_max": "200", + "hp": "720", + "speed": "1", + "recharge": "0.2" + }, + { + "name": "heavy wheeled vehicle", + "slot_weapon": "2", + "slot_armor": "4", + "slot_aug": "4", + "weight_max": "270", + "hp": "950", + "speed": "1", + "recharge": "0.2" + }, + { + "name": "light tank", + "slot_weapon": "1", + "slot_armor": "3", + "slot_aug": "2", + "weight_max": "300", + "hp": "700", + "speed": "1", + "recharge": "0.4" + }, + { + "name": "medium tank", + "slot_weapon": "1", + "slot_armor": "4", + "slot_aug": "4", + "weight_max": "400", + "hp": "1250", + "speed": "1", + "recharge": "0.5" + }, + { + "name": "heavy tank", + "slot_weapon": "2", + "slot_armor": "5", + "slot_aug": "5", + "weight_max": "450", + "hp": "1600", + "speed": "1" + }, + { + "name": "super heavy tank", + "slot_weapon": "3", + "slot_armor": "6", + "slot_aug": "6", + "weight_max": "500", + "hp": "2000", + "speed": "1" + }, + { + "name": "hovercraft", + "slot_weapon": "2", + "slot_armor": "0", + "slot_aug": "3", + "weight_max": "40", + "hp": "300", + "speed": "1", + "recharge": "-0.2" + }, + { + "name": "jet floater", + "slot_weapon": "1", + "slot_armor": "0", + "slot_aug": "2", + "weight_max": "30", + "hp": "60", + "speed": "1" + }, + { + "name": "one wheeler", + "slot_weapon": "1", + "slot_armor": "0", + "slot_aug": "4", + "weight_max": "15", + "hp": "40", + "speed": "1" + }, + { + "name": "armored crawler", + "slot_weapon": "1", + "slot_armor": "4", + "slot_aug": "2", + "weight_max": "200", + "hp": "750", + "speed": "1", + "recharge": "-0.4" + } +]
\ No newline at end of file diff --git a/build/content/gf.bmp b/build/content/gf.bmp Binary files differnew file mode 100644 index 0000000..85cd3e2 --- /dev/null +++ b/build/content/gf.bmp diff --git a/build/content/sounds/mouse_click_0.wav b/build/content/sounds/mouse_click_0.wav Binary files differnew file mode 100644 index 0000000..1dd4ab1 --- /dev/null +++ b/build/content/sounds/mouse_click_0.wav diff --git a/build/content/sounds/mouse_over.wav b/build/content/sounds/mouse_over.wav Binary files differnew file mode 100644 index 0000000..93114d2 --- /dev/null +++ b/build/content/sounds/mouse_over.wav diff --git a/build/content/sounds/mouse_wheel.wav b/build/content/sounds/mouse_wheel.wav Binary files differnew file mode 100644 index 0000000..1bca54d --- /dev/null +++ b/build/content/sounds/mouse_wheel.wav diff --git a/build/content/sounds/success.wav b/build/content/sounds/success.wav Binary files differnew file mode 100644 index 0000000..409fe49 --- /dev/null +++ b/build/content/sounds/success.wav diff --git a/build/content/sprites.bmp b/build/content/sprites.bmp Binary files differnew file mode 100644 index 0000000..509189f --- /dev/null +++ b/build/content/sprites.bmp diff --git a/build/content/sprites.pdn b/build/content/sprites.pdn Binary files differnew file mode 100644 index 0000000..1775674 --- /dev/null +++ b/build/content/sprites.pdn diff --git a/build/content/templates/default - Copy.txt b/build/content/templates/default - Copy.txt new file mode 100644 index 0000000..15a5c57 --- /dev/null +++ b/build/content/templates/default - Copy.txt @@ -0,0 +1,52 @@ +[ + { + "name": "tank", + "chassis": "5", + "brain": "1", + "battery": "1", + "weapons": [ 1, 1, 4, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "tank2", + "chassis": "14", + "brain": "2", + "battery": "2", + "weapons": [ 1, 1, 4, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "14", + "brain": "5", + "battery": "1", + "weapons": [ 36, 12, 10, -1, -1, -1, -1, -1 ], + "armor": [ 10, 7, 10, 4, 3, 4, -1, -1 ], + "augs": [ 3, 4, 3, 2, 1, 3, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "13", + "brain": "1", + "battery": "4", + "weapons": [ 3, 35, -1, -1, -1, -1, -1, -1 ], + "armor": [ 3, 2, 1, 4, 4, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "3", + "brain": "3", + "battery": "3", + "weapons": [ 2, 2, -1, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + } +]
\ No newline at end of file diff --git a/build/content/templates/default.txt b/build/content/templates/default.txt new file mode 100644 index 0000000..7ec433c --- /dev/null +++ b/build/content/templates/default.txt @@ -0,0 +1,72 @@ +[ + { + "name": "tank", + "chassis": "5", + "brain": "1", + "battery": "1", + "weapons": [ 1, 1, 4, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "tank2", + "chassis": "14", + "brain": "2", + "battery": "2", + "weapons": [ 1, 1, 4, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "14", + "brain": "5", + "battery": "1", + "weapons": [ 36, 12, 10, -1, -1, -1, -1, -1 ], + "armor": [ 10, 7, 10, 4, 3, 4, -1, -1 ], + "augs": [ 3, 4, 3, 2, 1, 3, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "13", + "brain": "1", + "battery": "4", + "weapons": [ 3, 35, -1, -1, -1, -1, -1, -1 ], + "armor": [ 3, 2, 1, 4, 4, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "3", + "brain": "3", + "battery": "3", + "weapons": [ 2, 2, -1, -1, -1, -1, -1, -1 ], + "armor": [ 9, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "11", + "brain": "1", + "battery": "1", + "weapons": [ 0, -1, -1, -1, -1, -1, -1, -1 ], + "armor": [ 9, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "17", + "brain": "0", + "battery": "0", + "weapons": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ 16, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + } +]
\ No newline at end of file diff --git a/build/content/weapons.txt b/build/content/weapons.txt new file mode 100644 index 0000000..f4b3b2b --- /dev/null +++ b/build/content/weapons.txt @@ -0,0 +1,192 @@ +[ + { + "name": "smg", + "damage_type": "pierce", "weight": "10", "cooldown": "1", + "damage": "10", "range": "4" + }, + { + "name": "machinegun", + "damage_type": "pierce", "weight": "25", "cooldown": "1", + "damage": "15", "range": "5" + }, + { + "name": "heavy machinegun", + "damage_type": "pierce", "weight": "40", "cooldown": "1", + "damage": "20", "range": "5" + }, + { + "name": "semi autocannon", + "damage_type": "pierce", "weight": "70", "cooldown": "2", + "damage": "32", "range": "6" + }, + { + "name": "autocannon", + "damage_type": "pierce", "weight": "100", "cooldown": "1", + "damage": "40", "range": "6" + }, + { + "name": "high velocity cannon", + "damage_type": "pierce", "weight": "120", "cooldown": "4", + "damage": "250", "range": "7" + }, + { + "name": "scrap gun", + "damage_type": "spread", "weight": "5", "cooldown": "2", + "damage": "8", "range": "3" + }, + { + "name": "burst cannon", + "damage_type": "spread", "weight": "15", "cooldown": "2", + "damage": "25", "range": "4" + }, + { + "name": "heavy burst cannon", + "damage_type": "spread", "weight": "30", "cooldown": "2", + "damage": "40", "range": "5" + }, + { + "name": "maul", + "damage_type": "impact", "weight": "200", "cooldown": "3", + "damage": "400", "range": "1", "knockback": "2" + }, + { + "name": "slam", + "damage_type": "impact", "weight": "0", "cooldown": "1", + "damage": "6", "range": "1" + }, + { + "name": "warhammer", + "damage_type": "impact", "weight": "40", "cooldown": "1", + "damage": "60", "range": "1", "knockback": "1" + }, + { + "name": "rocket", + "damage_type": "explosive", "weight": "60", "cooldown": "3", + "damage": "100", "range": "8" + }, + { + "name": "rocket swarm", + "damage_type": "explosive", "weight": "120", "cooldown": "3", + "damage": "60", "range": "7", "aoe": "2" + }, + { + "name": "tactical rocket", + "damage_type": "explosive", "weight": "160", "cooldown": "1", + "damage": "100", "range": "8", "aoe": "1" + }, + { + "name": "nuclear rocket", + "damage_type": "explosive", "weight": "200", "cooldown": "6", + "damage": "300", "range": "9", "aoe": "3" + }, + { + "name": "light laser", + "damage_type": "laser", "weight": "20", "cooldown": "1", + "damage": "8", "range": "5" + }, + { + "name": "combined light laser", + "damage_type": "laser", "weight": "50", "cooldown": "1", + "damage": "20", "range": "6" + }, + { + "name": "heavy laser", + "damage_type": "laser", "weight": "130", "cooldown": "1", + "damage": "45", "range": "6" + }, + { + "name": "combined heavy laser", + "damage_type": "laser", "weight": "300", "cooldown": "1", + "damage": "150", "range": "7" + }, + { + "name": "plasma cannon", + "damage_type": "fusion", "weight": "80", "cooldown": "2", + "damage": "125", "range": "5" + }, + { + "name": "plasma autocannon", + "damage_type": "fusion", "weight": "170", "cooldown": "1", + "damage": "110", "range": "5" + }, + { + "name": "plasma artillery", + "damage_type": "fusion", "weight": "200", "cooldown": "3", + "damage": "100", "range": "7", "aoe": "2" + }, + { + "name": "fusion blade", + "damage_type": "fusion", "weight": "15", "cooldown": "1", + "damage": "15", "range": "1" + }, + { + "name": "fusion lance", + "damage_type": "fusion", "weight": "50", "cooldown": "1", + "damage": "45", "range": "2" + }, + { + "name": "light railgun", + "damage_type": "impact", "weight": "50", "cooldown": "2", + "damage": "90", "range": "6" + }, + { + "name": "heavy railgun", + "damage_type": "impact", "weight": "190", "cooldown": "3", + "damage": "450", "range": "7" + }, + { + "name": "supercharged railgun", + "damage_type": "impact", "weight": "240", "cooldown": "4", + "damage": "1000", "range": "8" + }, + { + "name": "discharge beam", + "damage_type": "emp", "weight": "40", "cooldown": "2", + "damage_battery": "3", "range": "4" + }, + { + "name": "haywire beam", + "damage_type": "emp", "weight": "50", "cooldown": "5", + "damage": "80", "damage_battery": "5", "range": "6" + }, + { + "name": "stun beam", + "damage_type": "emp", "weight": "80", "cooldown": "5", + "stun": "1", "range": "4" + }, + { + "name": "amplified discharge impulse", + "damage_type": "emp", "weight": "150", "cooldown": "3", + "damage_battery": "10", "range": "5", "aoe": "1" + }, + { + "name": "amplified haywire beam", + "damage_type": "emp", "weight": "120", "cooldown": "5", + "damage": "200", "damage_battery": "12", "range": "6" + }, + { + "name": "amplified stun beam", + "damage_type": "emp", "weight": "200", "cooldown": "6", + "stun": "1", "range": "4" + }, + { + "name": "ion cannon", + "damage_type": "emp", "weight": "75", "cooldown": "2", + "reduce_fusion": "1", "reduce_laser": "1", "range": "5" + }, + { + "name": "heavy ion cannon", + "damage_type": "emp", "weight": "150", "cooldown": "1", + "reduce_fusion": "1", "reduce_laser": "1", "range": "6" + }, + { + "name": "explosive charges", + "damage_type": "explosive", "weight": "5", "cooldown": "10", + "damage": "100", "range": "0", "aoe": "2" + }, + { + "name": "javelin", + "damage_type": "explosive", "weight": "60", "cooldown": "2", + "damage": "40", "range": "7" + } +]
\ No newline at end of file diff --git a/build/libplibsys.dll b/build/libplibsys.dll Binary files differnew file mode 100644 index 0000000..2d3f0d9 --- /dev/null +++ b/build/libplibsys.dll diff --git a/build/player.txt b/build/player.txt new file mode 100644 index 0000000..a0fa615 --- /dev/null +++ b/build/player.txt @@ -0,0 +1 @@ +The Nameless One
\ No newline at end of file diff --git a/build/test.exe b/build/test.exe Binary files differnew file mode 100644 index 0000000..ebb5f5e --- /dev/null +++ b/build/test.exe diff --git a/design/components.txt b/design/components.txt new file mode 100644 index 0000000..650da5a --- /dev/null +++ b/design/components.txt @@ -0,0 +1,130 @@ +components have levels (maxelevel field, log stats or exp stats or logistic stats?) + +brain: (bonus augments slots only for brain augs) +state machine +weak supervised learner +strong supervised learner +weak self learner +strong self learner +general ai + +.chassis: (slots for weapon, battery, armor, augments), max weight, *hp +light two legged bot (1, 0, 1), 20 +heavy two legged bot (1, 1, 3), 45 +light four legged bot (2, 1, 2), 50 +heavy four legged bot (2, 2, 5), 150 +light six legged bot (2, 2, 3), 210 +heavy six legged bot (2, 4, 6), 300 +light buggy (1, 1, 1), 50 +buggy (2, 2, 2), 150 +light wheeled vehicle (1, 0, 2), 60 +medium wheeled vehicle (2, 2, 3), 200 +heavy wheeled vehicle (2, 4, 4), 270 +light tank (1, 3, 2), 300 +medium tank (1, 4, 4), 400 +heavy tank (2, 5, 5), 450 +super heavy tank (3, 6, 6), 500 +hovercraft (2, 0, 3), 40 +jet floater (1, 0, 2), 30 +one wheeler (1, 0, 4), 15 +armored crawler (1, 4, 2), 200 +motorcycle bot (1, 1, 1), 30 + +.batteries: weight +small alkaline pack (not rech), 3 +big alkaline pack (not rech), 10 +small lithium pack, 5 +big lithium pack, 15 +lead battery, 20 +small molten salt battery (military use), 40 +big molten salt battery (military use), 70 +atomic battery (not rech), 150 + +.weapons: (type), weight, damage, range, cooldown, knockback, aoe +smg (pierce), 10 +machinegun (pierce), 25 +heavy machinegun (pierce), 40 +semi autocannon (pierce), 70 +autocannon (pierce), 100 +high velocity cannon (pierce), 120 +scrap gun (spread), 5 +burst cannon (spread), 15 +heavy burst cannon (spread), 30 +maul (impact), 200 +slam (impact), 0 +warhammer (impact), 40 +rocket (explosive), 60 +rocket swarm (explosive), 120 +tactical rocket (explosive), 160 +nuclear rocket (explosive), 200 +light laser (laser), 20 +combined light laser (laser), 50 +heavy laser (laser), 130 +combined heavy laser (laser), 300 +plasma cannon (fusion), 80 +plasma autocannon (fusion), 170 +plasma artillery (fusion), 200 +fusion blade (fusion), 15 +fusion lance (fusion), 50 +light railgun (impact), 50 +heavy railgun (impact), 190 +supercharged railgun (impact), 240 +discharge beam (battery dmg), 40 +haywire beam (battery dmg and damage), 50 +stun beam (disables target), 80 +amplified haywire beam, 120 +amplified discharge impulse (aoe on target), 150 +amplified stun beam, 200 +ion cannon (reduces fusion and laser armor), 75 +heavy ion cannon (reduces fusion and laser armor), 150 +body explosives (explosive), 5 + +.armor: +metal plating (pierce and spread armor), 50 +heavy metal plating (pierce, spread and impact armor), 80 +reflective plating (laser armor), 40 +heat resistent plating (fusion armor), 50 +padding (spread and impact armor), 20 +reactive armor (explosive armor), 75 +energy shields (overall armor but kinetic), 25 +composite armor (pierce, spread and impact armor), 30 +plastic armor (pierce armor), 10 +sloped armor (pierce, spread armor), 45 +charged armor (explosive armor), 100 + +augments: +charged ammo (% emp damage) +extra radiator (better fusion armor), 10 +priority module (attacks the most costly), 2 +communication array (improves armor of adjacent units), 5 +long range targeting (better range), 1 +fast target acquisition (better cooldown), 3 +overcharger (better laser damage, more battery use), 10 +focus lens (better laser damage), 3 +amplifier (better fusion and laser damage), 30 +shrapnel (better explosive damage), 5 +reloader (better cooldown), 40 +antijammer (stun resistance %), 5 +fusion ammo (% damage is fusion), 10 +stability module (if bot, faster), 20 +torque boost (if wheeled vehicle or tank, +speed), 50 +weight stripping (additional weight +base%10, less hp), 0 +barebone gadgets (additional weight +base%15, less damage), 0 + +--engines (actuators): +servos, 5 +brushless, 10 +hydraulics, 30 +diesel engine (vehicles), 60 +hydrogen engine (vehicles), 100 + +--powergens: +small diesel engine, 20 +medium diesel engine, 50 +big diesel engine, 120 +small hydrogen engine, 2 +medium hydrogen engine, 25 +big hydrogen engine, 60 +solar panels, 10 +nuclear power core, 100 +critical nuclear power core, 200
\ No newline at end of file diff --git a/design/design.txt b/design/design.txt new file mode 100644 index 0000000..b4ee2fc --- /dev/null +++ b/design/design.txt @@ -0,0 +1,58 @@ +descript: arena clone + autochess + +turn: move+attack + + +unit design space: +dps ranged +dps melee +tanks +knockback +snipers +aoe +healers +slowers +stunners +kamikazes +attrition (battery damage) +commanders + + +units composition: +component robots, they are made of components +basic bot: brain, chassis, weapon, batteries. +.brain +.chassis + .locomotion + --motors (what are they needed for? actuators, meeeeh) meeeeeeeh + weapons slots + battery slots + augments slots + armor slots +.batteries +.powergens +.armor (set of floats for every damage type) +.weapons +.augments (sensors, ai enhancers (priority targeting, tactics)) + + +units stats: +damage (float) +damage type + pierce bullet + impact + spread + explosive + laser + fusion + emp +armor (set of floats derived from chassis and armor slots and augments) +reload (turns in between shots) +speed (turn in between movement) + + +further expansion: +roguelike (1-3 hrs runs, build an army along the way and fight 50 times to win) +rpg (5-30 hrs, long game with map and npcs a story and whatnot) +long rogue (1-10 hrs, open ended roguelike, infinite battles, map) +^ those but multiplayer (yikes for devtime but nice for lols) up to 8 ppl tcp diff --git a/design/notes.txt b/design/notes.txt new file mode 100644 index 0000000..bace25c --- /dev/null +++ b/design/notes.txt @@ -0,0 +1,79 @@ +tasks: (commit number) + +[x] implement rm unit (issued on 6, done on 6) +[x] implement armor calculation (issued on 6, done on 6) +[x] implement augment calculations (issued on 6, done on 6) +[x] implement augment hud view (issued on 6, done on 6) +[ ] implement sound (issued on 6) +[ ] implement stats hud view (issued on 6) +[ ] implement battery calculation (issued on 6) +[ ] implement brain behaviour (issued on 6) +[ ] implement component levels (issued on 6) +[ ] implement persistent settings (issued on 6) +[ ] implement net hud and minilobby (issued on 6) +[ ] implement army hud view (issued on 6) +[ ] implement cost function (issued on 6) +[ ] implement lobby cost constraints (issued on 6) +[ ] implement edit unit directly (issued on 6) +[ ] implement naming template and army (issued on 6) +[ ] implement move animation (issued on 6) +[ ] implement fire animation (issued on 6) +[ ] implement explosions (issued on 6) +[ ] design 3d units (issued on 6) +[ ] design 3d map tiles (issued on 6) +[ ] implement 3d units (issued on 6) +[ ] design component sprites (issued on 6) + + +bugs: + +[ ] symmetric integration (found on 6) + (on army movement and fire, equal armies should fair equally) + + +testing: + +[ ] armor calculations (issued on 6) + + +balance: + +[ ] balance components (issued on 6) + + +view from 6 to the end: + game is make templates, assemble for army, fight other army + multiplayer up to 2 ppl + armies, templates and settings are persistent + + + +details: + +implement rm unit: -> done, paper note solution + +implement armor calculation: + consider bonuses for damage reduction + aggregate them and spit out a percentage + editor remove units funct to make it possible to have a test case + army has to rebuild grid ref on load +-> done, barely tested + +implement augment calculation: + there are a lot of bonuses to keep track. do one at a time. + ok add_armor as a malus % + ok add_damage (only if same damage type weapon) as a bonus % + ok add_range as a fixed sum + ok add_cooldown + ok add_hp + ok add_speed +-> done, not tested + +implement stats hud view: +? stats have to include individual weapon cooldowns and damage, what to do + either put all as lines in stats (clean, but ugly) + or modify the components directly (messy) +! put them in stats later + +implement sound: + partially done, need sound design
\ No newline at end of file diff --git a/gst/gst.c b/gst/gst.c new file mode 100644 index 0000000..56db22f --- /dev/null +++ b/gst/gst.c @@ -0,0 +1,82 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <float.h> + +#include <gst.h> + +void gst_init (gamestate *gst) { + map_init(&gst->map_editor, MAXMAP, MAXMAP, 32); + army_init(gst->army_bp, &gst->map_editor); + gst->playernum = 1; + gst->state = 0; + gst->starttime = FLT_MAX; + gst->turn = 0; + gst->coveredtime = 0; + gst->turnspeed = 0.35f; +} + +void gst_destroy (gamestate *gst) { + army_destory(gst->army_bp+0); + map_destroy(&gst->map_editor); +} + +void gst_get_maparmy(gamestate *gst, map **m, army **ar) { + if (gst->state == 0) { + *m = &gst->map_editor; + *ar = gst->army_bp+0; + } + if (gst->state == 1) { + *m = &gst->map_battle; + *ar = &gst->ar; + } +} + +void gst_tobattle (gamestate *gst) { + if (gst->playernum == 1) { + //info_load_army(gst->army_bp+1, "army"); + gst->army_bp[1] = gst->army_bp[0]; + gst->playernum = 2; + } + gst->state = 1; + int maxx = MAXMAP, maxy = MAXMAP; + int dx = 5, dy = 10; + int sx = dx*2+maxx, sy = dy+maxy*2; + map_init(&gst->map_battle, sx, sy, 32); + army_init(&gst->ar, &gst->map_battle); + unit u; + for (int i=0; i<gst->playernum; i++) { + for (int j=0; j<gst->army_bp[i].uslen; j++) { + u = gst->army_bp[i].us[j]; + u.owner = i; + if (i==0) { + u.gridpos[0] += dx; + u.gridpos[1] += dy+maxy; + } + if (i==1) { + u.gridpos[0] = maxx-u.gridpos[0]+dx; + u.gridpos[1] = maxy-u.gridpos[1]; + } + u.pos[0] = u.gridpos[0]*gst->map_battle.ts; + u.pos[1] = u.gridpos[1]*gst->map_battle.ts; + army_spawn(&gst->ar, &gst->map_battle, u); + gst->ar.us[gst->ar.uslen].owner = i; + } + } + gst->starttime = FLT_MAX; + gst->turn = 0; + gst->coveredtime = 0; +} + +void gst_process (gamestate *gst, infos *info, float t) { + if (gst->starttime > t) gst->starttime = t; + float t_elapsed = t-gst->starttime; + if (t_elapsed > gst->coveredtime) { + gst->coveredtime += gst->turnspeed; + gst->turn ++; + map *m; army *ar; + gst_get_maparmy(gst, &m, &ar); + army_move(info, ar, m); + army_fire(info, ar, m); + } +}
\ No newline at end of file diff --git a/gst/gst.h b/gst/gst.h new file mode 100644 index 0000000..8acb699 --- /dev/null +++ b/gst/gst.h @@ -0,0 +1,30 @@ +#ifndef GST_H +#define GST_H + +#include <info.h> +#include <units.h> +#include <map.h> + +#define MAXMAP 10 + +typedef struct { + map map_editor; + army army_bp[8]; + int playernum; + map map_battle; + army ar; + int state; + float cam[2]; + float starttime; + float coveredtime; + int turn; + float turnspeed; +} gamestate; + +void gst_init (gamestate *gst); +void gst_destroy (gamestate *gst); +void gst_get_maparmy(gamestate *gst, map **m, army **ar); +void gst_tobattle (gamestate *gst); +void gst_process (gamestate *gst, infos *info, float t); + +#endif
\ No newline at end of file diff --git a/gst/info.c b/gst/info.c new file mode 100644 index 0000000..82f1550 --- /dev/null +++ b/gst/info.c @@ -0,0 +1,754 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include <units.h> +#include <info.h> + +#include <vec.h> +#include <jsmn.h> +#include <jsonparse.h> + +int type_damage_map (char strdmg[][32]) { + strcpy(strdmg[0], "pierce"); + strcpy(strdmg[1], "laser"); + strcpy(strdmg[2], "impact"); + strcpy(strdmg[3], "fusion"); + strcpy(strdmg[4], "explosive"); + strcpy(strdmg[5], "emp"); + strcpy(strdmg[6], "spread"); +} + +int damage_type_map (char *strdmg) { + if (strcmp(strdmg, "pierce") == 0) return 0; + if (strcmp(strdmg, "laser") == 0) return 1; + if (strcmp(strdmg, "impact") == 0) return 2; + if (strcmp(strdmg, "fusion") == 0) return 3; + if (strcmp(strdmg, "explosive") == 0) return 4; + if (strcmp(strdmg, "emp") == 0) return 5; + if (strcmp(strdmg, "spread") == 0) return 6; + printf("info: damage type unknown\n"); return -1; +} + + +void info_unit_init (info_unit *u) { + strcpy(u->name, "nameless"); + u->chassis = -1; + u->battery = -1; + u->brain = -1; + for(int i=0; i<8; u->weapons[i] = -1, u->armor[i] = -1, i++); + for(int i=0; i<16; u->augs[i] = -1, i++); + for(int i=0; i<34; u->levels[i] = 0, i++); +} + +float info_unit_get_weight (infos *info, info_unit *u) { + float sum = 0; + if (u->battery != -1) { + sum += info->batteries[u->battery].weight; + } + for(int i=0; i<8; i++) { + if (u->weapons[i] != -1 && i<info->chassis[u->chassis].slot_weapon) { + sum += info->weapons[u->weapons[i]].weight; + } + if (u->armor[i] != -1 && i<info->chassis[u->chassis].slot_armor) { + sum += info->armors[u->armor[i]].weight; + } + } + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug) { + sum += info->augs[u->augs[i]].weight; + } + } + return sum; +} + +float info_unit_get_dps (infos *info, info_unit *u) { + float sum = 0; + for(int i=0; i<8; i++) { + if (u->weapons[i] != -1 && i<info->chassis[u->chassis].slot_weapon) { + info_weapon *w = info->weapons+u->weapons[i]; + float damage = info_unit_get_damage(info, u, i); + sum += damage/w->cooldown; + } + } + return sum; +} + +float info_unit_get_health(infos *info, info_unit *u) { + float sum = 0; + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug) { + sum += info->augs[u->augs[i]].add_hp; + } + } + sum += info->chassis[u->chassis].hp; + return sum; +} + +float info_unit_get_speed(infos *info, info_unit *u) { + float sum = 0; + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug) { + sum += info->augs[u->augs[i]].add_speed; + } + } + sum += info->chassis[u->chassis].speed; + return sum; +} + +float info_unit_get_damage (infos *info, info_unit *u, int w) { + int damage_type = info->weapons[u->weapons[w]].damage_type; + float sum = 0; + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug) { + sum += info->augs[u->augs[i]].add_damage[damage_type]; + } + } + float mult = (1 + sum/100.0f); + if (mult < 0) mult = 0; + float dam = info->weapons[u->weapons[w]].damage * mult; + return dam; +} + +float info_unit_get_damage_target (infos *info, info_unit *u, int w, + info_unit *t) +{ + // u shoots at t with w, which is lol + int damage_type = info->weapons[u->weapons[w]].damage_type; + float reduction_perc = info_unit_get_armor(info, t, damage_type); + float damage = info_unit_get_damage(info, u, w); + float mult = (1 - reduction_perc / 100.0f); + return damage * mult; +} + +float info_unit_get_cooldown(infos *info, info_unit *u, int w) { + float sum = 0; + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug) { + sum += info->augs[u->augs[i]].add_cooldown; + } + } + sum += info->weapons[u->weapons[w]].cooldown; + return sum; +} + +float info_unit_get_range(infos *info, info_unit *u, int w) { + float sum = 0; + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug) { + sum += info->augs[u->augs[i]].add_range; + } + } + sum += info->weapons[u->weapons[w]].range; + return sum; +} + +float info_unit_get_armor(infos *info, info_unit *u, int d) { + float sum = 0; + for(int i=0; i<8; i++) { + if (u->armor[i] != -1 && i<info->chassis[u->chassis].slot_armor) { + sum += info->armors[u->armor[i]].armor[d]; + } + } + for(int i=0; i<16; i++) { + if (u->augs[i] != -1 && info->chassis[u->chassis].slot_aug) { + sum += info->augs[u->augs[i]].add_armor[d]; + } + } + return sum; +} + + +void weapon_init (info_weapon *w) { + strcpy(w->name, "nameless"); + w->damage_type = 0; + w->weight = 0; w->cooldown = 1; + w->damage = 0; w->range = 0; w->aoe = 0; + w->knockback = 0; w->stun = 0; + for (int i=0; i<7; i++) { w->reduce_armor[i]=0; } +} + +void chassis_init (info_chassis *c) { + strcpy(c->name, "nameless"); + c->slot_weapon = 0; c->slot_armor = 0; c->slot_aug = 0; + c->weight_max = 0; c->hp = 0; +} + +void battery_init (info_battery *b) { + strcpy(b->name, "nameless"); + b->weight = 0; b->capacity = 0; b->recharge = 0; +} + +void armor_init (info_armor *a) { + strcpy(a->name, "nameless"); + a->weight = 0; + for (int i=0; i<7; i++) { a->armor[i]=0; } +} + +void aug_init (info_aug *a) { + strcpy(a->name, "nameless"); + a->weight = 0; + for (int i=0; i<7; i++) { a->add_damage[i]=0; } + for (int i=0; i<7; i++) { a->add_armor[i]=0; } + a->add_range = 0; + a->add_cooldown = 0; + a->add_speed = 0; + a->add_hp = 0; +} + +void brain_init (info_brain *a) { + strcpy(a->name, "nameless"); +} + + +void info_unit_parse (char *json, info_unit *u, jsmntok_t *t, int r) { + info_unit_init(u); + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i+=2) { + if (t[i].type == JSMN_STRING) { + char key[32]; substr_token(json, key, t+i); + if (strcmp(key, "name") == 0) { + substr_token(json, u->name, t+i+1); + } + if (strcmp(key, "chassis") == 0) { + char val[32]; substr_token(json, val, t+i+1); + u->chassis = atoi(val); + } + if (strcmp(key, "brain") == 0) { + char val[32]; substr_token(json, val, t+i+1); + u->brain = atoi(val); + } + if (strcmp(key, "battery") == 0) { + char val[32]; substr_token(json, val, t+i+1); + u->battery = atoi(val); + } + if (strcmp(key, "weapons") == 0) { + int rt = json_parse_subtokens(json, t, r, i+1); + json_parse_array(json, u->weapons, t+i+2, rt-1, 'c'); + } + if (strcmp(key, "armor") == 0) { + int rt = json_parse_subtokens(json, t, r, i+1); + json_parse_array(json, u->armor, t+i+2, rt-1, 'c'); + } + if (strcmp(key, "augs") == 0) { + int rt = json_parse_subtokens(json, t, r, i+1); + json_parse_array(json, u->augs, t+i+2, rt-1, 'c'); + } + if (strcmp(key, "levels") == 0) { + int rt = json_parse_subtokens(json, t, r, i+1); + json_parse_array(json, u->levels, t+i+2, rt-1, 'c'); + } + } + } +} + +void info_weapon_parse (char *json, info_weapon *w, jsmntok_t *t, int r) { + weapon_init(w); + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i+=2) { + if (t[i].type == JSMN_STRING) { + char key[32]; substr_token(json, key, t+i); + if (strcmp(key, "name") == 0) { + substr_token(json, w->name, t+i+1); + } + if (strcmp(key, "damage_type") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->damage_type = damage_type_map(val); + } + if (strcmp(key, "weight") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->weight = atof(val); + } + if (strcmp(key, "cooldown") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->cooldown = atof(val); + } + if (strcmp(key, "damage") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->damage = atof(val); + } + if (strcmp(key, "range") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->range = atof(val); + } + if (strcmp(key, "aoe") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->aoe = atof(val); + } + if (strcmp(key, "knockback") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->knockback = atoi(val); + } + if (strcmp(key, "damage_battery") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->damage_battery = atof(val); + } + if (strcmp(key, "stun") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->stun = atoi(val); + } + if (strcmp(key, "reduce_pierce") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->reduce_armor[0] = atof(val); + } + if (strcmp(key, "reduce_laser") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->reduce_armor[1] = atof(val); + } + if (strcmp(key, "reduce_impact") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->reduce_armor[2] = atof(val); + } + if (strcmp(key, "reduce_fusion") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->reduce_armor[3] = atof(val); + } + if (strcmp(key, "reduce_explosive") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->reduce_armor[4] = atof(val); + } + if (strcmp(key, "reduce_emp") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->reduce_armor[5] = atof(val); + } + if (strcmp(key, "reduce_spread") == 0) { + char val[32]; substr_token(json, val, t+i+1); + w->reduce_armor[6] = atof(val); + } + } + } +} + +void info_chassis_parse (char *json, info_chassis *c, jsmntok_t *t, int r) { + chassis_init(c); + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i+=2) { + if (t[i].type == JSMN_STRING) { + char key[32]; substr_token(json, key, t+i); + if (strcmp(key, "name") == 0) { + substr_token(json, c->name, t+i+1); + } + if (strcmp(key, "slot_weapon") == 0) { + char val[32]; substr_token(json, val, t+i+1); + c->slot_weapon = atoi(val); + } + if (strcmp(key, "slot_armor") == 0) { + char val[32]; substr_token(json, val, t+i+1); + c->slot_armor = atoi(val); + } + if (strcmp(key, "slot_aug") == 0) { + char val[32]; substr_token(json, val, t+i+1); + c->slot_aug = atoi(val); + } + if (strcmp(key, "weight_max") == 0) { + char val[32]; substr_token(json, val, t+i+1); + c->weight_max = atof(val); + } + if (strcmp(key, "hp") == 0) { + char val[32]; substr_token(json, val, t+i+1); + c->hp = atof(val); + } + if (strcmp(key, "speed") == 0) { + char val[32]; substr_token(json, val, t+i+1); + c->speed = atof(val); + } + } + } +} + +void info_battery_parse (char *json, info_battery *b, jsmntok_t *t, int r) { + battery_init(b); + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i+=2) { + if (t[i].type == JSMN_STRING) { + char key[32]; substr_token(json, key, t+i); + if (strcmp(key, "name") == 0) { + substr_token(json, b->name, t+i+1); + } + if (strcmp(key, "weight") == 0) { + char val[32]; substr_token(json, val, t+i+1); + b->weight = atof(val); + } + if (strcmp(key, "capacity") == 0) { + char val[32]; substr_token(json, val, t+i+1); + b->capacity = atof(val); + } + if (strcmp(key, "recharge") == 0) { + char val[32]; substr_token(json, val, t+i+1); + b->recharge = atoi(val); + } + } + } +} + +void info_armor_parse (char *json, info_armor *a, jsmntok_t *t, int r) { + armor_init(a); + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i+=2) { + if (t[i].type == JSMN_STRING) { + char key[32]; substr_token(json, key, t+i); + if (strcmp(key, "name") == 0) { + substr_token(json, a->name, t+i+1); + } + if (strcmp(key, "weight") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->weight = atof(val); + } + if (strcmp(key, "pierce") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->armor[0] = atof(val); + } + if (strcmp(key, "laser") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->armor[1] = atof(val); + } + if (strcmp(key, "impact") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->armor[2] = atof(val); + } + if (strcmp(key, "fusion") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->armor[3] = atof(val); + } + if (strcmp(key, "explosive") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->armor[4] = atof(val); + } + if (strcmp(key, "emp") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->armor[5] = atof(val); + } + if (strcmp(key, "spread") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->armor[6] = atof(val); + } + } + } +} + +void info_aug_parse (char *json, info_aug *a, jsmntok_t *t, int r) { + aug_init(a); + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i+=2) { + if (t[i].type == JSMN_STRING) { + char key[32]; substr_token(json, key, t+i); + if (strcmp(key, "name") == 0) { + substr_token(json, a->name, t+i+1); + } + if (strcmp(key, "weight") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->weight = atof(val); + } + if (strcmp(key, "damage_pierce") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_damage[0] = atof(val); + } + if (strcmp(key, "damage_laser") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_damage[1] = atof(val); + } + if (strcmp(key, "damage_impact") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_damage[2] = atof(val); + } + if (strcmp(key, "damage_fusion") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_damage[3] = atof(val); + } + if (strcmp(key, "damage_explosive") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_damage[4] = atof(val); + } + if (strcmp(key, "damage_emp") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_damage[5] = atof(val); + } + if (strcmp(key, "add_spread") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_damage[6] = atof(val); + } + if (strcmp(key, "armor_pierce") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_armor[0] = atof(val); + } + if (strcmp(key, "armor_laser") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_armor[1] = atof(val); + } + if (strcmp(key, "armor_impact") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_armor[2] = atof(val); + } + if (strcmp(key, "armor_fusion") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_armor[3] = atof(val); + } + if (strcmp(key, "armor_explosive") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_armor[4] = atof(val); + } + if (strcmp(key, "armor_emp") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_armor[5] = atof(val); + } + if (strcmp(key, "armor_spread") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_armor[6] = atof(val); + } + if (strcmp(key, "add_range") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_range = atof(val); + } + if (strcmp(key, "add_cooldown") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_cooldown = atof(val); + } + if (strcmp(key, "add_hp") == 0) { + char val[32]; substr_token(json, val, t+i+1); + a->add_hp = atof(val); + } + } + } +} + +void info_brain_parse (char *json, info_brain *a, jsmntok_t *t, int r) { + brain_init(a); + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i+=2) { + if (t[i].type == JSMN_STRING) { + char key[32]; substr_token(json, key, t+i); + if (strcmp(key, "name") == 0) { + substr_token(json, a->name, t+i+1); + } + } + } +} + +void info_parse_json (infos *info, char *json, char *obj) { + jsmn_parser p; jsmn_init(&p); + jsmntok_t t[MAXTOKENS]; + int r = jsmn_parse(&p, json, strlen(json), t, MAXTOKENS); + int index = 0; + for (int i=1; i<r; i++) { // i=1: ignore outer [] + if (t[i].type == JSMN_OBJECT) { + int rt = json_parse_subtokens(json, t, r, i); + if (strcmp(obj, "template") == 0) { + info_unit_parse(json, info->templates+index, t+i+1, rt); + info->templateslen = index+1; + } + if (strcmp(obj, "weapon") == 0) { + info_weapon_parse(json, info->weapons+index, t+i+1, rt); + info->weaponslen = index+1; + } + if (strcmp(obj, "chassis") == 0) { + info_chassis_parse(json, info->chassis+index, t+i+1, rt); + info->chassislen = index+1; + } + if (strcmp(obj, "battery") == 0) { + info_battery_parse(json, info->batteries+index, t+i+1, rt); + info->batterieslen = index+1; + } + if (strcmp(obj, "armor") == 0) { + info_armor_parse(json, info->armors+index, t+i+1, rt); + info->armorslen = index+1; + } + if (strcmp(obj, "aug") == 0) { + info_aug_parse(json, info->augs+index, t+i+1, rt); + info->augslen = index+1; + } + if (strcmp(obj, "brain") == 0) { + info_brain_parse(json, info->brains+index, t+i+1, rt); + info->brainslen = index+1; + } + index ++; + i += rt-1; + } + } +} + +int info_read_file (char *dst, char *name, int size) { + memset(dst, 0, size*sizeof(char)); + FILE *f = fopen(name, "rb"); + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + fread(dst, 1, fsize, f); + fclose(f); + dst[fsize] = '\0'; + return fsize; +} + +void info_load (infos *info) { + int size = 1024*64; + char json[size]; + type_damage_map(info->damage_types); + info->augslen = 0; + info_read_file(json, "content/weapons.txt", size); + info_parse_json(info, json, "weapon"); + info_read_file(json, "content/chassis.txt", size); + info_parse_json(info, json, "chassis"); + info_read_file(json, "content/batteries.txt", size); + info_parse_json(info, json, "battery"); + info_read_file(json, "content/armor.txt", size); + info_parse_json(info, json, "armor"); + info_read_file(json, "content/augments.txt", size); + info_parse_json(info, json, "aug"); + info_read_file(json, "content/brains.txt", size); + info_parse_json(info, json, "brain"); + + info_read_file(json, "content/templates/default.txt", size); + info_parse_json(info, json, "template"); + /* + for (int i=0; i<info->unitslen; i++) { + printf("name: %s\n", info->units[i].name); + printf(" hp: %f\n", info->units[i].hp); + printf(" damage: %f\n", info->units[i].damage); + printf(" range: %f\n", info->units[i].range); + }*/ + /* + for (int i=0; i<info->weaponslen; i++) { + printf("name: %s\n", info->weapons[i].name); + printf(" damage_type: %d\n", info->weapons[i].damage_type); + printf(" weight: %f\n", info->weapons[i].weight); + printf(" cooldown: %f\n", info->weapons[i].cooldown); + printf(" damage: %f\n", info->weapons[i].damage); + printf(" range: %f\n", info->weapons[i].range); + printf(" aoe: %f\n", info->weapons[i].aoe); + printf(" knockback: %d\n", info->weapons[i].knockback); + printf(" damage_battery: %f\n", info->weapons[i].damage_battery); + printf(" stun: %d\n", info->weapons[i].stun); + float sum = 0; for (int j=0; j<7; j++) { + sum += info->weapons[i].reduce_armor[j]; + } + if (sum > 0) { + printf(" red pierce: %f\n", info->weapons[i].reduce_armor[0]); + printf(" red laser: %f\n", info->weapons[i].reduce_armor[1]); + printf(" red impact: %f\n", info->weapons[i].reduce_armor[2]); + printf(" red fusion: %f\n", info->weapons[i].reduce_armor[3]); + printf(" red explosive: %f\n", info->weapons[i].reduce_armor[4]); + printf(" red emp: %f\n", info->weapons[i].reduce_armor[5]); + printf(" red spread: %f\n", info->weapons[i].reduce_armor[6]); + } + }*/ + /* + for (int i=0; i<info->chassislen; i++) { + printf("name: %s\n", info->chassis[i].name); + printf(" slot_weapon: %d\n", info->chassis[i].slot_weapon); + printf(" slot_armor: %d\n", info->chassis[i].slot_armor); + printf(" slot_aug: %d\n", info->chassis[i].slot_aug); + printf(" weight_max: %f\n", info->chassis[i].weight_max); + printf(" hp: %f\n", info->chassis[i].hp); + }*/ + /* + for (int i=0; i<info->batterieslen; i++) { + printf("name: %s\n", info->batteries[i].name); + printf(" weight: %f\n", info->batteries[i].weight); + printf(" capacity: %f\n", info->batteries[i].capacity); + printf(" recharge: %d\n", info->batteries[i].recharge); + }*/ + /* + for (int i=0; i<info->armorslen; i++) { + printf("name: %s\n", info->armors[i].name); + printf(" weight: %f\n", info->armors[i].weight); + printf(" pierce: %f\n", info->armors[i].armor[0]); + printf(" laser: %f\n", info->armors[i].armor[1]); + printf(" impact: %f\n", info->armors[i].armor[2]); + printf(" fusion: %f\n", info->armors[i].armor[3]); + printf(" explosive: %f\n", info->armors[i].armor[4]); + printf(" emp: %f\n", info->armors[i].armor[5]); + printf(" spread: %f\n", info->armors[i].armor[6]); + }*/ +} + +void info_dump_json_templates (infos *info, char *str) { + int len = 0; + sprintf(str+len, "[ \n"); len = strlen(str); + for (int i=0; i<info->templateslen; i++) { + info_unit *u = info->templates+i; + sprintf(str+len, " { \n \"name\": \"%s\",\n", u->name); + len = strlen(str); + sprintf(str+len, " \"chassis\": \"%d\",\n", u->chassis); + len = strlen(str); + sprintf(str+len, " \"brain\": \"%d\",\n", u->brain); + len = strlen(str); + sprintf(str+len, " \"battery\": \"%d\",\n", u->battery); + len = strlen(str); + char w0[64]; json_dump_array(w0, u->weapons, 8, 'c'); + sprintf(str+len, " \"weapons\": %s,\n", w0); + len = strlen(str); + char w1[64]; json_dump_array(w1, u->armor, 8, 'c'); + sprintf(str+len, " \"armor\": %s,\n", w1); + len = strlen(str); + char w2[64]; json_dump_array(w2, u->augs, 8, 'c'); + sprintf(str+len, " \"augs\": %s,\n", w2); + len = strlen(str); + char w3[128]; json_dump_array(w3, u->levels, 34, 'c'); + sprintf(str+len, " \"levels\": %s\n", w3); + len = strlen(str); + char comma = ','; if(i==info->templateslen-1) comma = ' '; + sprintf(str+len, " }%c\n", comma); + len = strlen(str); + } + sprintf(str+len, "]"); len = strlen(str); +} + +void info_save_templates (infos *info, char *filename) { + char src[1024*64]; + info_dump_json_templates(info, src); + char pathname[64]; sprintf(pathname, "content/templates/%s.txt", filename); + FILE *f = fopen(pathname, "wb"); + fwrite(src, 1, strlen(src)*sizeof(char), f); + fclose(f); +} + +void info_template_add (infos *info, info_unit *temp) { + if (info->templateslen < MAXTEMPLATES) { + info->templates[info->templateslen] = *temp; + info->templateslen++; + } +} + +void info_load_army(struct army_ *ar, char *filename) { + char buf[1024*64]; + char pathname[64]; sprintf(pathname, "army/%s.txt", filename); + int len = info_read_file(buf, pathname, 1024*64); + memcpy(ar, buf, len-1); + ar->grid = NULL; + army_grid_init(ar); +} + +void info_save_army(struct army_ *ar, char *filename) { + char pathname[64]; sprintf(pathname, "army/%s.txt", filename); + FILE *f = fopen(pathname, "wb"); + fwrite(ar, 1, sizeof(army), f); + fclose(f); +} + + +void info_load_playername(char n[]) { + char buf[1024]; + int len = info_read_file(buf, "player.txt", 1024); + memcpy(n, buf, sizeof(char)*len); +} + +void info_save_playername(char n[]) { + FILE *f = fopen("player.txt", "wb"); + fwrite(n, 1, strlen(n)*sizeof(char), f); fclose(f); +} + + +#include <plibsys.h> +int info_army_get_list (char l[][32]) { + int len = 0; + PDirEntry *entry; + PDir *dir = p_dir_new ("army/", NULL); + while ((entry = p_dir_get_next_entry (dir, NULL)) != NULL) { + if (entry->type == P_DIR_ENTRY_TYPE_FILE) { + strcpy(l[len], entry->name); + l[len][strlen(l[len])-4] = '\0'; // del .txt + len++; + } + } + return len; +} diff --git a/gst/info.h b/gst/info.h new file mode 100644 index 0000000..3ec17f9 --- /dev/null +++ b/gst/info.h @@ -0,0 +1,116 @@ +#ifndef INFO_H +#define INFO_H + +#define MAXTEMPLATES 128 + +#include <stdint.h> + +typedef struct { + char name[32]; + // indexes of info.* + int8_t chassis; + int8_t brain; + int8_t weapons[8]; + int8_t armor[8]; + int8_t augs[16]; + int8_t battery; + int8_t levels[34]; +} info_unit; + +typedef struct { + char name[32]; + int damage_type; + float weight; + float cooldown; + float damage; + float range; + float aoe; + int knockback; + float damage_battery; + int stun; + float reduce_armor[7]; +} info_weapon; + +typedef struct { + char name[32]; + int slot_weapon; + int slot_armor; + int slot_aug; + float weight_max; + float hp; + float speed; +} info_chassis; + +typedef struct { + char name[32]; + float weight; + float capacity; + int recharge; +} info_battery; + +typedef struct { + char name[32]; + float weight; + float armor[7]; +} info_armor; + +typedef struct { + char name[32]; + float weight; + float add_damage[7]; + float add_armor[7]; + float add_range; + float add_cooldown; + float add_speed; + float add_hp; +} info_aug; + +typedef struct { + char name[32]; +} info_brain; + +typedef struct { + char damage_types[7][32]; + info_unit templates[MAXTEMPLATES]; + int templateslen; + info_weapon weapons[64]; + int weaponslen; + info_chassis chassis[32]; + int chassislen; + info_battery batteries[32]; + int batterieslen; + info_armor armors[32]; + int armorslen; + info_aug augs[32]; + int augslen; + info_brain brains[32]; + int brainslen; +} infos; + +void info_unit_init (info_unit *u); +float info_unit_get_weight (infos *info, info_unit *u); +float info_unit_get_dps (infos *info, info_unit *u); +float info_unit_get_health(infos *info, info_unit *u); +float info_unit_get_speed(infos *info, info_unit *u); +float info_unit_get_damage(infos *info, info_unit *u, int w); +float info_unit_get_damage_target(infos *info, info_unit *u, int w, + info_unit *t); +float info_unit_get_cooldown(infos *info, info_unit *u, int w); +float info_unit_get_range(infos *info, info_unit *u, int w); +float info_unit_get_armor(infos *info, info_unit *u, int d); + +void info_load (infos *info); + +void info_save_templates (infos *info, char *filename); +void info_template_add (infos *info, info_unit *temp); + + +void info_load_army(struct army_ *ar, char *filename); +void info_save_army(struct army_ *ar, char *filename); + +int info_army_get_list(char l[][32]); + +void info_load_playername(char n[]); +void info_save_playername(char n[]); + +#endif
\ No newline at end of file diff --git a/gst/map.c b/gst/map.c new file mode 100644 index 0000000..59d1ad1 --- /dev/null +++ b/gst/map.c @@ -0,0 +1,19 @@ +#include <stdlib.h> +#include <stdio.h> +#include <units.h> +#include <string.h> + +#include <map.h> + +int ptoi (map *m, int *p) { return p[0]+p[1]*m->sx; } +int xytoi (map *m, int x, int y) { return x+y*m->sx; } + +void map_init (map *m, int sx, int sy, int ts) { + m->t = (int*)malloc(sizeof(int)*sx*sy); + m->sx = sx; m->sy = sy; m->ts = ts; + memset(m->t, 0, sizeof(int)*sx*sy); +} + +void map_destroy (map *m) { + free(m->t); +}
\ No newline at end of file diff --git a/gst/map.h b/gst/map.h new file mode 100644 index 0000000..415281a --- /dev/null +++ b/gst/map.h @@ -0,0 +1,16 @@ +#ifndef MAP_H +#define MAP_H + +typedef struct { + int *t; + int sx; + int sy; + int ts; +} map; + +int ptoi (map *m, int *p); +int xytoi (map *m, int x, int y); +void map_init (map *m, int sx, int sy, int ts); +void map_destroy (map *m); + +#endif
\ No newline at end of file diff --git a/gst/units.c b/gst/units.c new file mode 100644 index 0000000..72089f2 --- /dev/null +++ b/gst/units.c @@ -0,0 +1,212 @@ +#include <stdlib.h> +#include <stdio.h> +#include <units.h> +#include <string.h> + +#include <vec.h> +#include <jsonparse.h> + +void army_grid_init(army *ar) { + if (ar->grid != NULL) free(ar->grid); + ar->grid = (unit**)malloc(sizeof(unit*)*ar->sx*ar->sy); + memset(ar->grid, NULL, sizeof(unit*)*ar->sx*ar->sy); + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + // not using ptoi, don't have map, why have map anyway? + ar->grid[ar->sx*u->gridpos[1]+u->gridpos[0]] = u; + } +} + +void army_init (army *ar, map *m) { + ar->uslen = 0; + ar->sx = m->sx; ar->sy = m->sy; + army_grid_init(ar); +} + +void army_destory(army *ar) { + free(ar->grid); +} + +void unit_init (infos *info, army *ar, map *m, + int x, int y, info_unit *iu, int owner, unit *u) +{ + u->pos[0] = x*m->ts; u->pos[1] = y*m->ts; + u->gridpos[0] = x; u->gridpos[1] = y; + u->info = *iu; + u->owner = owner; + u->hp = info_unit_get_health(info, iu); + u->move_points = 0; + for (int i=0; i<8; u->cooldown[i] = 1, i++); +} + +void army_spawn (army *ar, map *m, unit u) { + ar->us[ar->uslen] = u; + ar->grid[ptoi(m, u.gridpos)] = ar->us+ar->uslen; + ar->uslen++; +} + +void unit_move (army *ar, map *m, unit *u, int *dest) { + ar->grid[ptoi(m, u->gridpos)] = NULL; + u->gridpos[0] = dest[0]; + u->gridpos[1] = dest[1]; + ar->grid[ptoi(m, u->gridpos)] = u; + u->pos[0] = dest[0]*m->ts; + u->pos[1] = dest[1]*m->ts; +} + +void unit_remove (army *ar, map *m, unit *u) { + unit *t = ar->us+ar->uslen-1; + int ux = u->gridpos[0], uy = u->gridpos[1]; + int tx = t->gridpos[0], ty = t->gridpos[1]; + *u = *t; + ar->uslen--; + ar->grid[xytoi(m, tx, ty)] = u; + ar->grid[xytoi(m, ux, uy)] = NULL; + printf("ar->uslen: %d\n", ar->uslen); +} + +void unit_dead (army *ar, map *m, unit *u) { + ar->grid[ptoi(m, u->gridpos)] = NULL; +} + +void unit_search (infos *info, army *ar, map *m, unit *u, + unit **t, float range) +{ + for (int f=0; f<32; t[f] = NULL, f++); + int mult[4][2] = { {1, 1},{1,-1},{-1,-1},{-1,1} }, x, y, dx, dy, tmp; + *t = NULL; + for (int r=1; r<range*1.42 && *t==NULL; r++) { + for (int k=0; k<4 && *t==NULL; k++) { + for (int j=0; j<r && *t==NULL; j++) { + if (k%2==1) { // invert them if k=1 || k=3 + dx = (j)*mult[k][0]; dy = (r-j)*mult[k][1]; + } else { + dx = (r-j)*mult[k][0]; dy = (j)*mult[k][1]; + } + x = u->gridpos[0]+dx; y = u->gridpos[1]+dy; + //printf(" (%d, %d) -> (%d, %d), %d, %d, %d\n", u->gridpos[0], u->gridpos[1], x, y, r, k, j); + if (!(x>=0 && y>=0 && x<m->sx && y<m->sy)) continue; // oob + *t = ar->grid[xytoi(m, x, y)]; + if (*t!=NULL && (*t)->owner == u->owner) *t = NULL; // owner check + if (*t!=NULL && (*t)->hp <= 0) *t = NULL; // owner check + if (*t!=NULL) { + // range check + float diff[2] = { + u->gridpos[0] - (*t)->gridpos[0], + u->gridpos[1] - (*t)->gridpos[1] + }; float mag = vec2_mag(diff); + if (mag > range) *t = NULL; + } + }}} +} + + +typedef struct { unit *u; int *dir; int done; } mcom; +int army_move_step (infos *info, army *ar, map *m) { + int dirs[4][2] = { {1, 0},{0, 1},{-1,0},{0,-1} }; + mcom mcs[ar->uslen]; + int mclen = 0; + float diff[2]; + int orders = 0; + // planning + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + if (u->move_points <= 0) continue; + if (u->hp <= 0) continue; + // search target + unit *t[32]; + unit_search(info, ar, m, u, t, 100); + if (t[0] != NULL) { + // in range to shoot + diff[0] = u->gridpos[0] - t[0]->gridpos[0]; + diff[1] = u->gridpos[1] - t[0]->gridpos[1]; + if (vec2_mag(diff) > /*info->units[u->who].range*/1) { + // movement command issued + float dist[4] = { 9999, 9999, 9999, 9999 }; + for (int j=0; j<4; j++) { + diff[0] = u->gridpos[0]+dirs[j][0] + - t[0]->gridpos[0]; + diff[1] = u->gridpos[1]+dirs[j][1] + - t[0]->gridpos[1]; + dist[j] = vec2_mag(diff); + } + float min = dist[0]; int minj = 0; + for (int j=1; j<4; j++) { + if (dist[j] < min) { min = dist[j]; minj = j; } + } + mcs[mclen].u = u; + mcs[mclen].dir = dirs[minj]; + mcs[mclen].done = 0; + mclen++; + } + } + } + // execution + int sum = 0, lastsum = -1, step = 0; + for (; step<MAXSOLVESTEPS; step++) { + if (sum == lastsum) { break; } + lastsum = sum; + sum = 0; + for (int i=0; i<mclen; i++) { + int dest[2] = { + mcs[i].u->gridpos[0]+mcs[i].dir[0], + mcs[i].u->gridpos[1]+mcs[i].dir[1] + }; + if (!mcs[i].done && ar->grid[ptoi(m, dest)] == NULL) { + unit_move(ar, m, mcs[i].u, dest); + mcs[i].done = 1; + mcs[i].u->move_points -= 1; + orders++; + } + sum += mcs[i].done; + } + } + if (step == MAXSOLVESTEPS) { printf("army: max steps reached\n"); } + if (orders > 0) return 0; + else return 1; +} + +void army_move (infos *info, army *ar, map *m) { + for (int i=0; i<ar->uslen; i++) { + ar->us[i].move_points += info_unit_get_speed(info, &ar->us[i].info); + } + int iter = 0, finished = 0; + for (; iter<5 && !finished; iter++) { + finished = army_move_step(info, ar, m); + } + //printf("stepped %d %d\n", iter, finished); +} + +void army_fire (infos *info, army *ar, map *m) { + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + for (int j=0; j<info->chassis[u->info.chassis].slot_weapon; j++) { + u->cooldown[j] += 1; + } + } + struct dmg { unit *u; float dam; } dmgs[1024*8]; int dmgslen = 0; + unit *t[32]; + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + if (u->hp <= 0) continue; + for (int j=0; j<info->chassis[u->info.chassis].slot_weapon; j++) { + if (u->info.weapons[j] == -1) continue; + if (u->cooldown[j] <= 0) continue; + float range = info_unit_get_range(info, &u->info, j); + unit_search(info, ar, m, u, t, range); + if (t[0]!=NULL) { + dmgs[dmgslen].u = t[0]; + dmgs[dmgslen].dam = info_unit_get_damage_target( + info, &u->info, j, &t[0]->info); + dmgslen++; + u->cooldown[j] -= info_unit_get_cooldown(info, &u->info, j); + } + } + } + for (int i=0; i<dmgslen; i++) { + dmgs[i].u->hp -= dmgs[i].dam; + if (dmgs[i].u->hp <= 0) { + unit_dead(ar, m, dmgs[i].u); + } + } +}
\ No newline at end of file diff --git a/gst/units.h b/gst/units.h new file mode 100644 index 0000000..86f7fd7 --- /dev/null +++ b/gst/units.h @@ -0,0 +1,40 @@ +#ifndef UNITS_H +#define UNITS_H + +#define MAXUNITS 128 +#define MAXSOLVESTEPS 128 + +#include <info.h> + +typedef struct unit_ { + float pos[2]; + int gridpos[2]; + info_unit info; + int owner; + float hp; + float move_points; + float cooldown[8]; + float charge; +} unit; + +typedef struct army_ { + unit us[MAXUNITS]; + unit **grid; + int uslen; + int sx, sy; +} army; + + +#include <map.h> + +void unit_init (infos *info, army *ar, map *m, + int x, int y, info_unit *iu, int owner, unit *u); +void unit_remove (army *ar, map *m, unit *u); +void army_grid_init(army *ar); +void army_init (army *ar, map *m); +void army_destory(army *ar); +void army_spawn (army *ar, map *m, unit u); +void army_move (infos *info, army *ar, map *m); +void army_fire (infos *info, army *ar, map *m); + +#endif
\ No newline at end of file diff --git a/hud/hud.c b/hud/hud.c new file mode 100644 index 0000000..383cb01 --- /dev/null +++ b/hud/hud.c @@ -0,0 +1,788 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <hud.h> +#include <hud_views.h> + +#include <intersect.h> + +// TODO: make sound module mabye? +#define SOUND_MOUSE_OVER 0 +#define SOUND_MOUSE_CLICK_0 1 +#define SOUND_MOUSE_WHEEL 2 +#define SOUND_SUCCESS 3 + + +// INIT +void init_sel_chassis (graphic_settings *gs, hud_sel *sc, txtd *t, + SDL_Rect back, float start) +{ + sc->start = start; + sc->nav = 0; + sc->rect_back = back; +} + +void init_form_new_unit (graphic_settings *gs, form_new_unit *fnu, txtd *t) { + int w = 290+200+300+20*2+10*4 + 30*3 + 200, h = 145+300+20*2+10*1 + 30*2; + int x = gs->resx/2-w/2, y = gs->resy/2-h/2; + fnu->rect_back = { x, y, w, h }; + + fnu->rect_chassis = { x+20, y+20+145+10+30, 300, 300 }; + fnu->rect_brain = { x+20, y+20+30, 145, 145 }; + fnu->rect_battery = { x+150+25, y+20+30, 145, 145 }; + for (int i=0; i<8; i++) { + fnu->rect_weapons[i] = { x+20+300+10+30, y+20+120*i +30, 200, 110 }; + } + for (int i=0; i<8; i++) { + fnu->rect_armor[i] = { x+20+500+20+30*2, y+20+60*i +30, 150, 50 }; + } + for (int i=0; i<8; i++) { + fnu->rect_augs[i] = { x+20+500+20+160+30*2, y+20+60*i +30, 150, 50 }; + } + + fnu->rect_stats = { x+w-20-200, y+20, 200, h-70 }; + + int width = get_text_width("save", t); + button bdone = { "save", 4, { x+w-4*2-width-20, y+h-4*2-11-20 } }; + fnu->done = bdone; +} + +void init_overlay_game (graphic_settings *gs, overlay_game *og, txtd *t) { + int w = 250, h = gs->resy-20; + og->rect_templates = { 10, gs->resy-10-h, w, h }; + + float wnu = get_text_width("new template", t); + button b = { "new template", 4, { w-wnu-4*2, 20 } }; + og->new_template = b; + + float wst = get_text_width("save templates", t); + button b2 = { "save templates", 4, { w-wst-4*2, gs->resy-20-4*2-10 } }; + og->save_templates = b2; + + int warmy = 250, harmy = gs->resy-20; + og->rect_army = { gs->resx-warmy-10, gs->resy-harmy-10, warmy, harmy }; + button b3 = { "save army", 4, { gs->resx-warmy, gs->resy-20-4*2-10 } }; + og->save_army = b3; + + int wbattle = 400, hbattle = 100; + og->rect_battle = { gs->resx/2-wbattle/2, 10, wbattle, hbattle }; + + float wsb = get_text_width("start battle", t); + button b1 = { "start battle", 4, + { og->rect_battle.x+wbattle-wsb-4*2-5, hbattle-4*2-5 } }; + og->start_battle = b1; + + button b4 = { "host game", 4, + { og->rect_battle.x+5, hbattle-4*2-5 } }; + og->host_game = b4; + + button b5 = { "join game", 4, + { og->rect_battle.x+5, hbattle-4*2-5-25 } }; + og->join_game = b5; +} + +void hud_reset (graphic_settings *gs, hud *h, txtd *t) { + init_form_new_unit(gs, &h->fnu, t); + init_overlay_game(gs, &h->og, t); + SDL_Rect clip = { h->fnu.rect_back.x, h->sc.ref->y, + h->fnu.rect_back.w, 300 }; + float start = h->sc.ref->x - h->fnu.rect_back.x; + init_sel_chassis(gs, &h->sc, t, clip, start); +} + +void hud_init (graphic_settings *gs, hud *h, txtd *t) { + h->fnu.sel = 0; h->fnu.ind = 0; + h->sc.ref = &h->fnu.rect_chassis; + h->og.temp_place = -1; + info_unit_init(&h->fnu.uinfo); + strcpy(h->og.army_listcur, "army"); + strcpy(h->og.playername, ""); + h->nameedit = NULL; + h->og.battle_state = 0; + h->og.edit_playername = 0; + hud_reset(gs, h, t); +} + +void hud_resize (graphic_settings *gs, hud *h, txtd *t) { + hud_reset(gs, h, t); +} + + +// PROCESS +int hud_fnu_check (info_unit *u, infos *info) { + if (u->chassis == -1) return 1; + if (u->battery == -1) return 2; + if (u->brain == -1) return 3; + float curweight = info_unit_get_weight(info, u); + float maxweight = info->chassis[u->chassis].weight_max; + if (curweight > maxweight) { return 4; } + return 0; +} + +void hud_map_sel (info_unit *u, infos *info, int sel, int ind, + int8_t **n, int *bound, int size[]) +{ + if (sel == 0) { + *n = &u->chassis; + *bound = info->chassislen; + size[0] = 300; size[1] = 300; + } + if (sel == 1) { + *n = &u->battery; + *bound = info->batterieslen; + size[0] = 145; size[1] = 145; + } + if (sel == 2) { + *n = &u->armor[ind]; + *bound = info->armorslen; + size[0] = 150; size[1] = 250; + } + if (sel == 3) { + *n = &u->weapons[ind]; + *bound = info->weaponslen; + size[0] = 200; size[1] = 110; + } + if (sel == 4) { + *n = &u->augs[ind]; + *bound = info->augslen; + size[0] = 150; size[1] = 200; + } + if (sel == 5) { + *n = &u->brain; + *bound = info->brainslen; + size[0] = 145; size[1] = 145; + } +} + +void hud_process_sel (graphic_settings *gs, hud *h, MKb *mkb, + infos *info, army *ar, map *m, txtd *t, Mix_Chunk *sounds[]) +{ + if (mkb->mwheeldelta != 0) { + Mix_PlayChannel( -1, sounds[SOUND_MOUSE_WHEEL], 0 ); + } + int8_t *n = NULL; int bound = 0; int size[2]; + hud_map_sel(&h->fnu.uinfo, info, h->fnu.sel, h->fnu.ind, &n, &bound, size); + h->sc.nav += mkb->mwheeldelta*size[0]; + if (h->sc.nav > (*n+1)*size[0]) { + h->sc.nav = (*n+1)*size[0]; + } + if (h->sc.nav < (*n-bound+1)*size[0]) { + h->sc.nav = (*n-bound+1)*size[0]; + } + float mousepos[2] = { mkb->mx, mkb->my }; + if (mkb->mheld[0] == 1) { + float possc[2] = { h->sc.rect_back.x, h->sc.rect_back.y }; + float sizesc[2] = { h->sc.rect_back.w, h->sc.rect_back.h }; + if (!pt_rect(mousepos, possc, sizesc)) { + h->state = 1; + } else { + int i, inav = (int)h->sc.nav/size[0]; + for (int j=-7;j<h->sc.rect_back.w/size[0]+1; j++) { + i = *n+j-inav; + if (i<-1) continue; + if (i>=bound) break; + float x = h->sc.rect_back.x+size[0]*j + +(int)h->sc.nav%size[0]+h->sc.start; + float y = h->sc.rect_back.y; + float pos[2] = {x, y}, s[2] = { size[0], size[1] }; + if (pt_rect(mousepos, pos, s)) { + *n = i; + h->state = 1; + Mix_PlayChannel( -1, sounds[SOUND_MOUSE_CLICK_0], 0 ); + break; + } + } + } + } +} + + +void hud_edit_close(hud *h) { + h->nameedit = NULL; + h->og.edit_playername = 0; +} + +void hud_open_fnu (hud *h, info_unit *u, int i) { + h->state = 1; + h->fnu.uinfo = *u; + h->og.temp_modify = i; + hud_edit_close(h); +} + +void hud_close_fnu (hud *h, infos *info) { + if (hud_fnu_check(&h->fnu.uinfo, info) > 0) return; + if (h->og.temp_modify == -1) { + info_template_add(info, &h->fnu.uinfo); + } else { + info->templates[h->og.temp_modify] = h->fnu.uinfo; + } + h->state = 0; +} + + +void hud_og_place(hud *h, int i) { + h->og.temp_place = i; +} + + +void hud_open_sel (graphic_settings *gs, hud *h, + txtd *t, infos *info, SDL_Rect *ref) +{ + int8_t *n = NULL; int bound = 0; int size[2]; + hud_map_sel(&h->fnu.uinfo, info, h->fnu.sel, + h->fnu.ind, &n, &bound, size); + h->sc.nav = 0; if (*n == -1) h->sc.nav -= size[0]; + h->sc.ref = ref; + hud_resize(gs, h, t); + h->sc.rect_back.h = size[1]; +} + +void hud_process_form_new_unit (graphic_settings *gs, hud *h, MKb *mkb, + infos *info, army *ar, map *m, txtd *t, Mix_Chunk *sounds[]) +{ + float mousepos[2] = { mkb->mx, mkb->my }; + if (mkb->mheld[0] == 1) { + if (mouse_in_button(mousepos, t, &h->fnu.done)) { + hud_close_fnu(h, info); + Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); + /* + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + unit_init(info, ar, m, u->gridpos[0], u->gridpos[1], + &u->info, 0, u); + }*/ + } + float possc[2] = { h->fnu.rect_chassis.x, h->fnu.rect_chassis.y }; + float sizesc[2] = { h->fnu.rect_chassis.w, h->fnu.rect_chassis.h }; + if (pt_rect(mousepos, possc, sizesc)) { + h->fnu.sel = 0; h->state = 2; + hud_open_sel(gs, h, t, info, &h->fnu.rect_chassis); + } + float possb[2] = { h->fnu.rect_battery.x, h->fnu.rect_battery.y }; + float sizesb[2] = { h->fnu.rect_battery.w, h->fnu.rect_battery.h }; + if (pt_rect(mousepos, possb, sizesb)) { + h->fnu.sel = 1; h->state = 2; + hud_open_sel(gs, h, t, info, &h->fnu.rect_battery); + } + float possbr[2] = { h->fnu.rect_brain.x, h->fnu.rect_brain.y }; + float sizesbr[2] = { h->fnu.rect_brain.w, h->fnu.rect_brain.h }; + if (pt_rect(mousepos, possbr, sizesbr)) { + h->fnu.sel = 5; h->state = 2; + hud_open_sel(gs, h, t, info, &h->fnu.rect_brain); + } + if (h->fnu.uinfo.chassis != -1) { + for (int i=0; + i<info->chassis[h->fnu.uinfo.chassis].slot_armor; i++) + { + float possa[2] = { + h->fnu.rect_armor[i].x, h->fnu.rect_armor[i].y }; + float sizesa[2] = { + h->fnu.rect_armor[i].w, h->fnu.rect_armor[i].h }; + if (pt_rect(mousepos, possa, sizesa)) { + h->fnu.sel = 2; h->fnu.ind = i; h->state = 2; + hud_open_sel(gs, h, t, info, &h->fnu.rect_armor[i]); + } + } + for (int i=0; + i<info->chassis[h->fnu.uinfo.chassis].slot_weapon; i++) + { + float possa[2] = { + h->fnu.rect_weapons[i].x, h->fnu.rect_weapons[i].y }; + float sizesa[2] = { + h->fnu.rect_weapons[i].w, h->fnu.rect_weapons[i].h }; + if (pt_rect(mousepos, possa, sizesa)) { + h->fnu.sel = 3; h->fnu.ind = i; h->state = 2; + hud_open_sel(gs, h, t, info, &h->fnu.rect_weapons[i]); + } + } + for (int i=0; + i<info->chassis[h->fnu.uinfo.chassis].slot_aug; i++) + { + float possa[2] = { + h->fnu.rect_augs[i].x, h->fnu.rect_augs[i].y }; + float sizesa[2] = { + h->fnu.rect_augs[i].w, h->fnu.rect_augs[i].h }; + if (pt_rect(mousepos, possa, sizesa)) { + h->fnu.sel = 4; h->fnu.ind = i; h->state = 2; + hud_open_sel(gs, h, t, info, &h->fnu.rect_augs[i]); + } + } + } + } +} + +void hud_process_overlay_game (graphic_settings *gs, hud *h, MKb *mkb, + infos *info, army *ar, map *m, txtd *t, gamestate *gst, + net_client *netc, net_server *nets, Mix_Chunk *sounds[]) +{ + if (h->og.battle_state == 1) { + if (nets->sock_client == NULL) { + net_server_accept(nets); + } else { + char buffer[1024*64]; + int len = net_server_recv(nets, buffer); + if (len != -1) { + h->og.battle_state = 3; + + int armysize = sizeof(unit)*gst->army_bp[0].uslen; + char data[armysize]; + memcpy(data, gst->army_bp[0].us, armysize); + net_server_send(nets, data, armysize); + printf("send (%d)\n", armysize); + + memcpy(gst->army_bp[1].us, buffer, len); + gst->army_bp[1].uslen = len/sizeof(unit); + gst->playernum = 2; + gst_tobattle(gst); + gst->cam[0] = -gs->resx/2+gst->map_battle.sx*gst->map_battle.ts/2; + gst->cam[1] = -gs->resy/2+gst->map_battle.sy*gst->map_battle.ts/2; + h->state = 4; + } + } + } + if (h->og.battle_state == 2) { + char buffer[1024*64]; + int len = net_client_recv(netc, buffer); + if (len != -1) { + h->og.battle_state = 3; + + memcpy(gst->army_bp[1].us, buffer, len); + gst->army_bp[1].uslen = len/sizeof(unit); + gst->playernum = 2; + gst_tobattle(gst); + gst->cam[0] = -gs->resx/2+gst->map_battle.sx*gst->map_battle.ts/2; + gst->cam[1] = -gs->resy/2+gst->map_battle.sy*gst->map_battle.ts/2; + h->state = 4; + } + } + + float mousepos[2] = { mkb->mx, mkb->my }; + if (mkb->mheld[0] == 1) { + if (mouse_in_button(mousepos, t, &h->og.new_template)) { + info_unit u; info_unit_init(&u); + hud_open_fnu(h, &u, -1); + h->og.temp_place = -1; + } + + if (mouse_in_button(mousepos, t, &h->og.save_templates)) { + info_save_templates(info, "default"); + Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); + } + + if (mouse_in_button(mousepos, t, &h->og.start_battle)) { + /* + army_move(info, ar, m); + army_fire(info, ar, m);*/ + gst_tobattle(gst); + gst->cam[0] = -gs->resx/2+gst->map_battle.sx*gst->map_battle.ts/2; + gst->cam[1] = -gs->resy/2+gst->map_battle.sy*gst->map_battle.ts/2; + h->og.battle_state = 3; + h->state = 4; + Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); + } + + if (mouse_in_button(mousepos, t, &h->og.join_game)) { + printf("open client\n"); + net_client_open(netc); + int conn = net_client_connect(netc, "127.0.0.1", SERVER_PORT); + if (conn == 0) { + int armysize = sizeof(unit)*gst->army_bp[0].uslen; + char data[armysize]; + memcpy(data, gst->army_bp[0].us, armysize); + net_client_send(netc, data, armysize); + printf("send (%d)\n", armysize); + } + h->og.battle_state = 2; + } + + if (mouse_in_button(mousepos, t, &h->og.host_game)) { + printf("open server\n"); + net_server_open(nets, SERVER_PORT); + h->og.battle_state = 1; + } + + if (mouse_in_button(mousepos, t, &h->og.save_army)) { + info_save_army(gst->army_bp+0, h->og.army_listcur); + h->og.army_listlen = info_army_get_list(h->og.army_list); + } + + if (h->og.temp_place != -1) { + int x = (int)((mkb->mx+gst->cam[0])/32); + int y = (int)((mkb->my+gst->cam[1])/32); + if (x >= 0 && y >= 0 && x < m->sx && y < m->sy) { + if (ar->grid[xytoi(m,x,y)] == NULL) { + unit u; + unit_init(info, ar, m, x, y, + info->templates+h->og.temp_place, 0, &u); + army_spawn(ar, m, u); + } + } else { + h->og.temp_place = -1; + } + } + + for (int i=0; i<info->templateslen; i++) { + float x = h->og.rect_templates.x+5; + float y = h->og.rect_templates.y+5 + i*20 + 30; + float wedit = get_text_width("edit", t); + float possa[2] = { x, y }; + float sizesa[2] = { wedit+4*2, 11+4*2 }; + if (pt_rect(mousepos, possa, sizesa)) { + hud_open_fnu(h, info->templates+i, i); + h->og.temp_place = -1; + } + float wplace = get_text_width("place", t); + float posp[2] = { x+wedit+4*2+5, y }; + float sizep[2] = { wplace+4*2, 11+4*2 }; + if (pt_rect(mousepos, posp, sizep)) { + hud_og_place(h, i); + } + } + + for (int i=0; i<h->og.army_listlen; i++) { + float x = h->og.rect_army.x+5; + float y = h->og.rect_army.y+5 + i*20 + 30; + float wload = get_text_width("load", t); + float posp[2] = { x, y }; + float sizep[2] = { wload+4*2, 11+4*2 }; + if (pt_rect(mousepos, posp, sizep)) { + strcpy(h->og.army_listcur, h->og.army_list[i]); + info_load_army(gst->army_bp+0, h->og.army_listcur); + Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); + } + } + + if (h->nameedit == NULL) { + float pn[2] = { h->og.rect_battle.x+5, h->og.rect_battle.y+5 }; + char sn[64]; sprintf(sn, "PLAYER NAME: %s", h->og.playername); + float sizen[2] = { get_text_width(sn, t), 10 }; + if (pt_rect(mousepos, pn, sizen)) { + h->nameedit = h->og.playername; + printf("editing this %s\n", h->nameedit); + h->og.edit_playername = 1; + } + } else { + Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); + hud_edit_close(h); + } + } + + // rm unit + if (mkb->mheld[2] == 1) { + Mix_PlayChannel( -1, sounds[SOUND_MOUSE_CLICK_0], 0 ); + int x = (int)((mkb->mx+gst->cam[0])/32); + int y = (int)((mkb->my+gst->cam[1])/32); + if (x >= 0 && y >= 0 && x < m->sx && y < m->sy) { + if (ar->grid[xytoi(m,x,y)] != NULL) { + unit_remove(ar, m, ar->grid[xytoi(m,x,y)]); + } + } + } +} + +void hud_edit_name(hud *h, MKb *mkb, Mix_Chunk *sounds[]) { + for (int i=0; i<mkb->kbnum; i++) { + if (mkb->kb[i] >= SDL_SCANCODE_A + && mkb->kb[i] <= SDL_SCANCODE_Z) { + if (strlen(h->nameedit) < 31) { + char c = mkb->kb[i]-SDL_SCANCODE_A+'a'; + if (SDL_GetModState() & KMOD_SHIFT) { + c = mkb->kb[i]-SDL_SCANCODE_A+'A'; + } + sprintf(h->nameedit, "%s%c", h->nameedit, c); + } + } + } + if (mkb_search(mkb, SDL_SCANCODE_SPACE)) { + Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); + if (strlen(h->nameedit) < 31) { + sprintf(h->nameedit, "%s ", h->nameedit); + } + } + if (mkb_search(mkb, SDL_SCANCODE_BACKSPACE)) { + if (strlen(h->nameedit) > 0) + h->nameedit[strlen(h->nameedit)-1] = '\0'; + } + if (mkb_search(mkb, SDL_SCANCODE_ESCAPE)) { + Mix_PlayChannel( -1, sounds[SOUND_SUCCESS], 0 ); + hud_edit_close(h); return; + } +} + +void hud_process (graphic_settings *gs, hud *h, MKb *mkb, + infos *info, army *ar, map *m, txtd *t, gamestate *gst, + net_client *netc, net_server *nets, Mix_Chunk *sounds[]) +{ + if (h->nameedit != NULL) { hud_edit_name(h, mkb, sounds); } + switch (h->state) { + case 0: + hud_process_overlay_game(gs, h, mkb, info, ar, m, t, gst, + netc, nets, sounds); + break; + case 1: hud_process_form_new_unit(gs, h, mkb, info, ar, m, t, + sounds); break; + case 2: hud_process_sel(gs, h, mkb, info, ar, m, t, sounds); break; + } +} + + + +// RENDER +void hud_render_sel (hud_sel *sc, MKb *mkb, info_unit *u, + SDL_Renderer* rend, SDL_Texture *sprites, txtd *t, infos *info, + int sel, int ind) +{ + int8_t *n = NULL; int bound = 0; int size[2]; + hud_map_sel(u, info, sel, ind, &n, &bound, size); + SDL_SetRenderDrawColor(rend, 150, 200, 0, 255); + SDL_RenderFillRect(rend, &sc->rect_back); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, &sc->rect_back); + SDL_RenderSetClipRect(rend, &sc->rect_back); + int i; + for (int j=-7;j<sc->rect_back.w/size[0]+1; j++) { + i = *n+j - (int)sc->nav/size[0]; + if (i<-1) continue; + if (i>=bound) break; + float x = sc->rect_back.x+size[0]*j+(int)sc->nav%size[0]+sc->start; + float y = sc->rect_back.y; + SDL_Rect r = { x, y, size[0]+1, size[1] }; + SDL_SetRenderDrawColor(rend, 150, 200, 120, 255); + SDL_RenderFillRect(rend, &r); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, &r); + if (sel==0) render_view_chassis(rend, t, x, y, info, i, sprites); + if (sel==1) render_view_battery(rend, t, x, y, info, i); + if (sel==2) render_view_armor_detail(rend, t, x, y, info, i); + if (sel==3) render_view_weapon_detail(rend, t, x, y, info, i); + if (sel==4) render_view_aug_detail(rend, t, x, y, info, i); + if (sel==5) render_view_brain(rend, t, x, y, info, i); + } + SDL_RenderSetClipRect(rend, NULL); +} + +void hud_render_form_new_unit (form_new_unit *fnu, MKb *mkb, + SDL_Renderer* rend, txtd *t, infos *info, SDL_Texture *sprites) +{ + SDL_SetRenderDrawColor(rend, 150, 200, 255, 255); + SDL_RenderFillRect(rend, &fnu->rect_back); + + SDL_SetRenderDrawColor(rend, 200, 0, 255, 255); + SDL_RenderFillRect(rend, &fnu->rect_chassis); + SDL_RenderFillRect(rend, &fnu->rect_brain); + SDL_RenderFillRect(rend, &fnu->rect_battery); + + SDL_SetRenderDrawColor(rend, 255, 150, 50, 255); + SDL_RenderFillRect(rend, &fnu->rect_stats); + + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, &fnu->rect_back); + SDL_RenderDrawRect(rend, &fnu->rect_chassis); + SDL_RenderDrawRect(rend, &fnu->rect_brain); + SDL_RenderDrawRect(rend, &fnu->rect_battery); + SDL_RenderDrawRect(rend, &fnu->rect_stats); + + render_view_stats(rend, t, fnu->rect_stats.x, fnu->rect_stats.y, + info, &fnu->uinfo); + + if (fnu->uinfo.chassis != -1) { + for (int i=0; i<info->chassis[fnu->uinfo.chassis].slot_weapon; i++) { + SDL_SetRenderDrawColor(rend, 200, 100, 255, 255); + SDL_RenderFillRect(rend, fnu->rect_weapons+i); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, fnu->rect_weapons+i); + render_view_weapon(rend, t, + fnu->rect_weapons[i].x, + fnu->rect_weapons[i].y, info, fnu->uinfo.weapons[i]); + } + for (int i=0; i<info->chassis[fnu->uinfo.chassis].slot_armor; i++) { + SDL_SetRenderDrawColor(rend, 200, 200, 255, 255); + SDL_RenderFillRect(rend, fnu->rect_armor+i); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, fnu->rect_armor+i); + render_view_armor(rend, t, + fnu->rect_armor[i].x, + fnu->rect_armor[i].y, info, fnu->uinfo.armor[i]); + } + for (int i=0; i<info->chassis[fnu->uinfo.chassis].slot_aug; i++) { + SDL_SetRenderDrawColor(rend, 200, 200, 255, 255); + SDL_RenderFillRect(rend, fnu->rect_augs+i); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, fnu->rect_augs+i); + render_view_aug(rend, t, + fnu->rect_augs[i].x, + fnu->rect_augs[i].y, info, fnu->uinfo.augs[i]); + } + } + + char schassis[32] = "CHASSIS"; + float wchassis = get_text_width(schassis, t)*2; + float pchassis[2] = { + fnu->rect_chassis.x+fnu->rect_chassis.w/2 - wchassis / 2, + fnu->rect_chassis.y+fnu->rect_chassis.h + 7 + }; + render_text_scaled(rend, schassis, pchassis, t, 2); + + char sbrain[32] = "CONTROLLER"; + float wbrain = get_text_width(sbrain, t)*2; + float pbrain[2] = { + fnu->rect_brain.x+fnu->rect_brain.w/2 - wbrain / 2, + fnu->rect_brain.y - 16-7 + }; + render_text_scaled(rend, sbrain, pbrain, t, 2); + + char sbattery[32] = "BATTERY"; + float wbattery = get_text_width(sbattery, t)*2; + float pbattery[2] = { + fnu->rect_battery.x+fnu->rect_battery.w/2 - wbattery / 2, + fnu->rect_battery.y - 16-7 + }; + render_text_scaled(rend, sbattery, pbattery, t, 2); + + char sweapons[32] = "WEAPONS"; + float wweapons = get_text_width(sweapons, t)*2; + float pweapons[2] = { + fnu->rect_weapons[0].x+fnu->rect_weapons[0].w/2 - wweapons / 2, + fnu->rect_weapons[0].y - 16-7 + }; + render_text_scaled(rend, sweapons, pweapons, t, 2); + + char sarmor[32] = "ARMOR"; + float warmor = get_text_width(sarmor, t)*2; + float parmor[2] = { + fnu->rect_armor[0].x+fnu->rect_armor[0].w/2 - warmor / 2, + fnu->rect_armor[0].y - 16-7 + }; + render_text_scaled(rend, sarmor, parmor, t, 2); + + char saugs[32] = "AUGMENTS"; + float waugs = get_text_width(saugs, t)*2; + float pagus[2] = { + fnu->rect_augs[0].x+fnu->rect_augs[0].w/2 - waugs / 2, + fnu->rect_augs[0].y - 16-7 + }; + render_text_scaled(rend, saugs, pagus, t, 2); + + render_button(rend, t, &fnu->done); + + int err = hud_fnu_check(&fnu->uinfo, info); + char serr[32] = "ok"; + if (err==1) strcpy(serr, "select a chassis"); + if (err==2) strcpy(serr, "select a battery"); + if (err==3) strcpy(serr, "select a controller"); + if (err==4) strcpy(serr, "overburdened, remove weight"); + float werr = get_text_width(serr, t); + float perr[2] = { + fnu->done.pos[0]-werr-10, + fnu->done.pos[1]+fnu->done.pad + }; + render_text_scaled(rend, serr, perr, t, 1); + + render_view_chassis(rend, t, + fnu->rect_chassis.x, fnu->rect_chassis.y, + info, fnu->uinfo.chassis, sprites); + render_view_battery(rend, t, + fnu->rect_battery.x, fnu->rect_battery.y, info, fnu->uinfo.battery); + render_view_brain(rend, t, + fnu->rect_brain.x, fnu->rect_brain.y, info, fnu->uinfo.brain); +} + +void hud_render_overlay_game (overlay_game *og, MKb *mkb, + SDL_Renderer* rend, txtd *t, infos *info, SDL_Texture *sprites) +{ + SDL_SetRenderDrawColor(rend, 40, 150, 200, 255); + SDL_RenderFillRect(rend, &og->rect_templates); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, &og->rect_templates); + char stemp[32] = "TEMPLATES"; + float ptemp[2] = { + og->rect_templates.x+10, + og->rect_templates.y+10 + }; + render_text_scaled(rend, stemp, ptemp, t, 2); + + render_button(rend, t, &og->new_template); + render_button(rend, t, &og->save_templates); + + for (int i=0; i<info->templateslen; i++) { + float x = og->rect_templates.x+5; + float y = og->rect_templates.y+5 + i*20 + 30; + render_view_template(rend, t, x, y, info, i); + } + + SDL_SetRenderDrawColor(rend, 0, 200, 120, 255); + SDL_RenderFillRect(rend, &og->rect_army); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, &og->rect_army); + char sarmy[32] = "ARMY"; + float parmy[2] = { + og->rect_army.x+10, + og->rect_army.y+10 + }; + render_text_scaled(rend, sarmy, parmy, t, 2); + + render_button(rend, t, &og->save_army); + + button b = { "load", 4, { 0, 0 } }; + for (int i=0; i<og->army_listlen; i++) { + float x = og->rect_army.x+5; + float y = og->rect_army.y+5 + i*20 + 30; + float bw = get_text_width("load", t)+4*2; + b.pos[0] = x; b.pos[1] = y; + render_button(rend, t, &b); + float pa[2] = { x+bw+5, y+4 }; + render_text_scaled(rend, og->army_list[i], pa, t, 1); + if (strcmp(og->army_listcur, og->army_list[i]) == 0) { + float w = get_text_width(og->army_list[i], t); + float pe[2] = { x+bw+5+w+5, y+4 }; + render_text_scaled(rend, "<- editing", pe, t, 1); + } + } + + SDL_SetRenderDrawColor(rend, 250, 60, 60, 255); + SDL_RenderFillRect(rend, &og->rect_battle); + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, &og->rect_battle); + + float pn[2] = { og->rect_battle.x+5, og->rect_battle.y+5 }; + char sn[64]; + if (og->edit_playername == 1) { + sprintf(sn, "PLAYER NAME: %s_", og->playername); + printf("looool\n"); + } else { + sprintf(sn, "PLAYER NAME: %s", og->playername); + } + render_text_scaled(rend, sn, pn, t, 1); + + render_button(rend, t, &og->host_game); + render_button(rend, t, &og->join_game); + render_button(rend, t, &og->start_battle); + + if (og->temp_place != -1) { + SDL_Rect srcRect = { + info->templates[og->temp_place].chassis*32, 32, 32, 32 }; + SDL_Rect dstRect = { mkb->mx - 16, mkb->my - 16, 32, 32 }; + SDL_RenderCopy(rend, sprites, &srcRect, &dstRect); + } +} + +void hud_render (hud *h, SDL_Renderer* rend, txtd *t, MKb *mkb, infos *info, + SDL_Texture *sprites) +{ + switch (h->state) { + case 0: + hud_render_overlay_game(&h->og, mkb, rend, t, info, sprites); + break; + case 1: + hud_render_overlay_game(&h->og, mkb, rend, t, info, sprites); + hud_render_form_new_unit(&h->fnu, mkb, rend, t, info, sprites); + break; + case 2: + hud_render_overlay_game(&h->og, mkb, rend, t, info, sprites); + hud_render_form_new_unit(&h->fnu, mkb, rend, t, info, sprites); + hud_render_sel(&h->sc, mkb, &h->fnu.uinfo, + rend, sprites, t, info, h->fnu.sel, h->fnu.ind); + break; + } +}
\ No newline at end of file diff --git a/hud/hud.h b/hud/hud.h new file mode 100644 index 0000000..2728bb2 --- /dev/null +++ b/hud/hud.h @@ -0,0 +1,74 @@ +#ifndef HUD_H +#define HUD_H + +#include <SDL.h> +#include <SDL_mixer.h> + +#include <render_text.h> +#include <button.h> +#include <graphicsettings.h> +#include <mkb.h> +#include <info.h> +#include <units.h> +#include <map.h> +#include <gst.h> +#include <net.h> + +typedef struct { + float start; + float nav; + SDL_Rect rect_back; + SDL_Rect *ref; +} hud_sel; + +typedef struct { + button new_template; + button save_templates; + button save_army; + button start_battle; + button host_game; + button join_game; + SDL_Rect rect_battle; + SDL_Rect rect_templates; + int temp_modify; + int temp_place; + SDL_Rect rect_army; + char army_list[64][32]; + int army_listlen; + char army_listcur[32]; + char playername[32]; + int battle_state; + int edit_playername; +} overlay_game; + +typedef struct { + SDL_Rect rect_back; + SDL_Rect rect_chassis; + SDL_Rect rect_brain; + SDL_Rect rect_battery; + SDL_Rect rect_weapons[8]; + SDL_Rect rect_armor[8]; + SDL_Rect rect_augs[8]; + SDL_Rect rect_stats; + button done; + info_unit uinfo; + int sel, ind; +} form_new_unit; + +typedef struct { + hud_sel sc; + overlay_game og; + form_new_unit fnu; + int state; + char *nameedit; +} hud; + +void hud_init(graphic_settings *gs, hud *h, txtd *t); +void hud_resize (graphic_settings *gs, hud *h, txtd *t); +void hud_process (graphic_settings *gs, hud *h, MKb *mkb, + infos *info, army *ar, map *m, txtd *t, gamestate *gst, + net_client *netc, net_server *nets, Mix_Chunk *sounds[]); +void hud_render (hud *h, SDL_Renderer* rend, txtd *t, MKb *mkb, infos *info, + SDL_Texture *sprites); + +#endif
\ No newline at end of file diff --git a/hud/hud_views.c b/hud/hud_views.c new file mode 100644 index 0000000..557ff1f --- /dev/null +++ b/hud/hud_views.c @@ -0,0 +1,380 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include <hud_views.h> + +void render_view_stats (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, info_unit *tm) +{ + float h = 10; + float pname[2] = { px+10, py+h }; + char sname[64]; sprintf(sname, "STATS"); + render_text_scaled(rend, sname, pname, t, 2); + h += 35; + + float calcweight = info_unit_get_weight(info, tm); + float maxweight = info->chassis[tm->chassis].weight_max; + float pw[2] = { px+10, py+h }; + char sw[64]; sprintf(sw, "WEIGHT: %.0f/%.0f", + calcweight, maxweight); + render_text_scaled(rend, sw, pw, t, 1); + h += 15; + + float hp = info_unit_get_health(info, tm); + float php[2] = { px+10, py+h }; + char shp[64]; sprintf(shp, "HP: %.2f", hp); + render_text_scaled(rend, shp, php, t, 1); + h += 15; + + float speed = info_unit_get_speed(info, tm); + float pspeed[2] = { px+10, py+h }; + char sspeed[64]; sprintf(sspeed, "SPEED: %.2f", speed); + render_text_scaled(rend, sspeed, pspeed, t, 1); + h += 15; + + float dps = info_unit_get_dps(info, tm); + float pdps[2] = { px+10, py+h }; + char sdps[64]; sprintf(sdps, "DAMAGE PER TURN: %.2f", dps); + render_text_scaled(rend, sdps, pdps, t, 1); + h += 20; + + float part[2] = { px+10, py+h }; + render_text_scaled(rend, "ARMOR:", part, t, 1); + h += 15; + + for (int i=0; i<7; i++) { + float ar = info_unit_get_armor(info, tm, i); + float par[2] = { px+10, py+h }; + char sar[64]; sprintf(sar, "%s: %.1f%", info->damage_types[i], ar); + render_text_scaled(rend, sar, par, t, 1); + h += 15; + } + h += 5; +} + +void render_view_chassis (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int chassis, SDL_Texture *sprites) +{ + if (chassis != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", + info->chassis[chassis].name); + render_text_scaled(rend, sname, pname, t, 2); + float pweight[2] = { px+10, py+40 }; + char sweight[64]; sprintf(sweight, "MAX WEIGHT: %0.0f", + info->chassis[chassis].weight_max); + render_text_scaled(rend, sweight, pweight, t, 1); + float php[2] = { px+10, py+55 }; + char shp[64]; sprintf(shp, "HP: %0.1f", + info->chassis[chassis].hp); + render_text_scaled(rend, shp, php, t, 1); + float pspeed[2] = { px+10, py+70 }; + char sspeed[64]; sprintf(sspeed, "SPEED: %0.2f tiles/turn", + info->chassis[chassis].speed); + render_text_scaled(rend, sspeed, pspeed, t, 1); + + SDL_Rect srcRect = { chassis*32, 32, 32, 32 }; + SDL_Rect dstRect = { px+300-32-10, py+10, 32, 32 }; + SDL_RenderCopy(rend, sprites, &srcRect, &dstRect); + } else { + float pname[2] = { px+10, py+10 }; + render_text_scaled(rend, "select a chassis...", pname, t, 1); + } +} + +void render_view_battery (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int batt) +{ + if (batt != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", + info->batteries[batt].name); + render_text_scaled(rend, sname, pname, t, 1); + float pweight[2] = { px+10, py+40 }; + char sweight[64]; sprintf(sweight, "WEIGHT: %0.0f", + info->batteries[batt].weight); + render_text_scaled(rend, sweight, pweight, t, 1); + float pcapacity[2] = { px+10, py+55 }; + char scapacity[64]; sprintf(scapacity, "CAPACITY: %0.1f", + info->batteries[batt].capacity); + render_text_scaled(rend, scapacity, pcapacity, t, 1); + float prech[2] = { px+10, py+70 }; + char srech[64]; + if (info->batteries[batt].recharge == 0) { + strcpy(srech, "NOT RECHARGEABLE"); + } else { + strcpy(srech, "RECHARGEABLE"); + } + render_text_scaled(rend, srech, prech, t, 1); + } else { + float pname[2] = { px+10, py+10 }; + render_text_scaled(rend, "select a battery...", pname, t, 1); + } +} + + +void render_view_armor (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int armor) +{ + if (armor != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", info->armors[armor].name); + render_text_scaled(rend, sname, pname, t, 1); + char sa[64]; int j=0; + char temp[16] = "red: "; + strcpy(sa+j, temp); + j += strlen(temp); + for (int i=0; i<7; i++) { + if (i<7-1) { + sprintf(temp, "%.0f, ", info->armors[armor].armor[i]); + } else { + sprintf(temp, "%.0f", info->armors[armor].armor[i]); + } + strcpy(sa+j, temp); + j += strlen(temp); + } + sa[j] = '\0'; + float pa[2] = { px+10, py+25 }; + render_text_scaled(rend, sa, pa, t, 1); + } else { + float pname[2] = { px+10, py+10 }; + render_text_scaled(rend, "select an armor...", pname, t, 1); + } +} + +void render_view_armor_detail (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int armor) +{ + if (armor != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", info->armors[armor].name); + render_text_scaled(rend, sname, pname, t, 1); + float pweight[2] = { px+10, py+40 }; + char sweight[64]; sprintf(sweight, "WEIGHT: %0.0f", + info->armors[armor].weight); + render_text_scaled(rend, sweight, pweight, t, 1); + + float pred[2] = { px+10, py+60 }; + render_text_scaled(rend, "DAMAGE REDUCTION", pred, t, 1); + + int h=0; + for (int i=0; i<7; i++) { + if (info->armors[armor].armor[i] < 0.001) continue; + float pa[2] = { px+10, py+75+h*15 }; + char sa[64]; sprintf(sa, "%s: %.1f%", + info->damage_types[i], info->armors[armor].armor[i]); + render_text_scaled(rend, sa, pa, t, 1); + h++; + } + } else { + render_view_weapon(rend, t, px, py, info, armor); + } +} + + +void render_view_weapon (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int weapon) +{ + if (weapon != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", + info->weapons[weapon].name); + render_text_scaled(rend, sname, pname, t, 1); + float pweight[2] = { px+10, py+30 }; + char sweight[64]; sprintf(sweight, "WEIGHT: %.0f", + info->weapons[weapon].weight); + render_text_scaled(rend, sweight, pweight, t, 1); + float ptype[2] = { px+10, py+45 }; + char stype[64]; sprintf(stype, "DAMAGE TYPE: %s", + info->damage_types[info->weapons[weapon].damage_type]); + render_text_scaled(rend, stype, ptype, t, 1); + float pdamage[2] = { px+10, py+60 }; + char sdamage[64]; sprintf(sdamage, "DAMAGE: %.0f", + info->weapons[weapon].damage); + render_text_scaled(rend, sdamage, pdamage, t, 1); + float prange[2] = { px+10, py+75 }; + char srange[64]; sprintf(srange, "RANGE: %.0f", + info->weapons[weapon].range); + render_text_scaled(rend, srange, prange, t, 1); + float pcool[2] = { px+10, py+90 }; + char scool[64]; sprintf(scool, "COOLDOWN: %.0f", + info->weapons[weapon].cooldown); + render_text_scaled(rend, scool, pcool, t, 1); + } else { + float pname[2] = { px+10, py+10 }; + render_text_scaled(rend, "select a weapon...", pname, t, 1); + } +} + +void render_view_weapon_detail (SDL_Renderer* rend, txtd *t, + int px, int py, infos *info, int weapon) +{ + if (weapon != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", + info->weapons[weapon].name); + render_text_scaled(rend, sname, pname, t, 1); + float pweight[2] = { px+10, py+30 }; + char sweight[64]; sprintf(sweight, "WEIGHT: %.0f", + info->weapons[weapon].weight); + render_text_scaled(rend, sweight, pweight, t, 1); + float ptype[2] = { px+10, py+45 }; + char stype[64]; sprintf(stype, "DAMAGE TYPE: %s", + info->damage_types[info->weapons[weapon].damage_type]); + render_text_scaled(rend, stype, ptype, t, 1); + float pdamage[2] = { px+10, py+60 }; + char sdamage[64]; sprintf(sdamage, "DAMAGE: %.0f", + info->weapons[weapon].damage); + render_text_scaled(rend, sdamage, pdamage, t, 1); + float prange[2] = { px+10, py+75 }; + char srange[64]; sprintf(srange, "RANGE: %.0f", + info->weapons[weapon].range); + render_text_scaled(rend, srange, prange, t, 1); + float pcool[2] = { px+10, py+90 }; + char scool[64]; sprintf(scool, "COOLDOWN: %.0f", + info->weapons[weapon].cooldown); + render_text_scaled(rend, scool, pcool, t, 1); + } else { + render_view_weapon(rend, t, px, py, info, weapon); + } +} + + +void render_view_aug (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int aug) +{ + if (aug != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", + info->augs[aug].name); + render_text_scaled(rend, sname, pname, t, 1); + float pweight[2] = { px+10, py+30 }; + char sweight[64]; sprintf(sweight, "WEIGHT: %.0f", + info->augs[aug].weight); + render_text_scaled(rend, sweight, pweight, t, 1); + } else { + float pname[2] = { px+10, py+10 }; + render_text_scaled(rend, "select an augment...", pname, t, 1); + } +} + +void render_view_aug_detail (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int aug) +{ + if (aug != -1) { + float h = 10; + float pname[2] = { px+10, py+h }; + char sname[64]; sprintf(sname, "%s", + info->augs[aug].name); + render_text_scaled(rend, sname, pname, t, 1); + h += 20; + + float pweight[2] = { px+10, py+h }; + char sweight[64]; sprintf(sweight, "WEIGHT: %.0f", + info->augs[aug].weight); + render_text_scaled(rend, sweight, pweight, t, 1); + h += 15; + + float range = info->augs[aug].add_range; + if (range != 0) { + float p[2] = { px+10, py+h }; + char s[64]; sprintf(s, "RANGE: %.1f", range); + render_text_scaled(rend, s, p, t, 1); + h += 15; + } + + float cooldown = info->augs[aug].add_cooldown; + if (cooldown != 0) { + float p[2] = { px+10, py+h }; + char s[64]; sprintf(s, "COOLDOWN: %.2f", cooldown); + render_text_scaled(rend, s, p, t, 1); + h += 15; + } + + float speed = info->augs[aug].add_speed; + if (speed != 0) { + float p[2] = { px+10, py+h }; + char s[64]; sprintf(s, "SPEED: %.2f", speed); + render_text_scaled(rend, s, p, t, 1); + h += 15; + } + + float hp = info->augs[aug].add_hp; + if (hp != 0) { + float p[2] = { px+10, py+h }; + char s[64]; sprintf(s, "HP: %.1f", hp); + render_text_scaled(rend, s, p, t, 1); + h += 15; + } + + h += 5; + + float sum = 0; + for (int i=0; i<7; i++) sum += fabs(info->augs[aug].add_armor[i]); + if (sum != 0) { + float p[2] = { px+10, py+h }; + render_text_scaled(rend, "ARMOR: ", p, t, 1); + h += 15; + for (int i=0; i<7; i++) { + if (info->augs[aug].add_armor[i] == 0) continue; + float pa[2] = { px+10, py+h }; + char sa[64]; sprintf(sa, "%s: %.1f%", + info->damage_types[i], info->augs[aug].add_armor[i]); + render_text_scaled(rend, sa, pa, t, 1); + h += 15; + } + } + + sum = 0; + for (int i=0; i<7; i++) sum += fabs(info->augs[aug].add_damage[i]); + if (sum != 0) { + float p[2] = { px+10, py+h }; + render_text_scaled(rend, "DAMAGE: ", p, t, 1); + h += 15; + for (int i=0; i<7; i++) { + if (info->augs[aug].add_damage[i] == 0) continue; + float pa[2] = { px+10, py+h }; + char sa[64]; sprintf(sa, "%s: %.1f%", + info->damage_types[i], info->augs[aug].add_damage[i]); + render_text_scaled(rend, sa, pa, t, 1); + h += 15; + } + } + } else { + render_view_aug(rend, t, px, py, info, aug); + } +} + + +void render_view_brain (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int brain) +{ + if (brain != -1) { + float pname[2] = { px+10, py+10 }; + char sname[64]; sprintf(sname, "%s", + info->brains[brain].name); + render_text_scaled(rend, sname, pname, t, 1); + } else { + float pname[2] = { px+10, py+10 }; + render_text_scaled(rend, "select a controller...", pname, t, 1); + } +} + + +void render_view_template (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int temp) +{ + button b = { "edit", 4, { px, py } }; + render_button(rend, t, &b); + float wedit = get_text_width("edit", t); + + button b1 = { "place", 4, { px+wedit+2*4+5, py } }; + render_button(rend, t, &b1); + float wplace = get_text_width("place", t); + + float pname[2] = { wplace+wedit+4*4+10+px, py+4 }; + char *sname = info->chassis[info->templates[temp].chassis].name; + render_text_scaled(rend, sname, pname, t, 1); +}
\ No newline at end of file diff --git a/hud/hud_views.h b/hud/hud_views.h new file mode 100644 index 0000000..ceced23 --- /dev/null +++ b/hud/hud_views.h @@ -0,0 +1,47 @@ +#ifndef HUD_VIEWS_H +#define HUD_VIEWS_H + +#include <SDL.h> + +#include <render_text.h> +#include <button.h> +#include <graphicsettings.h> +#include <mkb.h> +#include <info.h> +#include <units.h> +#include <hud.h> + +void render_view_stats (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, info_unit *tm); + + +void render_view_chassis (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int chassis, SDL_Texture *sprites); + +void render_view_battery (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int batt); + +void render_view_armor (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int armor); +void render_view_armor_detail (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int armor); + +void render_view_weapon (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int weapon); +void render_view_weapon_detail (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int weapon); + +void render_view_aug (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int aug); +void render_view_aug_detail (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int aug); + +void render_view_brain (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int brain); + + +void render_view_template (SDL_Renderer* rend, txtd *t, int px, int py, + infos *info, int temp); + + +#endif
\ No newline at end of file diff --git a/json/jsmn.h b/json/jsmn.h new file mode 100644 index 0000000..3178dcc --- /dev/null +++ b/json/jsmn.h @@ -0,0 +1,471 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef JSMN_H +#define JSMN_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct jsmntok { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct jsmn_parser { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +#ifndef JSMN_HEADER +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + default: + /* to quiet a warning from gcc*/ + break; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + parser->pos++; + + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#endif /* JSMN_HEADER */ + +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/json/jsonparse.c b/json/jsonparse.c new file mode 100644 index 0000000..6cfae2e --- /dev/null +++ b/json/jsonparse.c @@ -0,0 +1,167 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#include <jsonparse.h> + +void substr_token (char *json, char *temp, jsmntok_t *t) { + memcpy(temp, json+t->start, t->end - t->start); + temp[t->end-t->start] = '\0'; +} + +void json_parse_array(char *json, void *temp, jsmntok_t *t, int r, char type) { + for (int i=0; i<r; i++) { + if (t[i].type == JSMN_PRIMITIVE) { + char val[32]; substr_token(json, val, t+i); + if (type == 'i') { + int *p = (int*)(intptr_t)temp+sizeof(int)*i; + *p = atoi(val); + } + if (type == 'c') { + int8_t *p = (int8_t*)(intptr_t)temp+sizeof(int8_t)*i; + *p = atoi(val); + } + } + } +} + +void json_dump_array (char *str, void *arr, int len, char type) { + int cur = 0; + sprintf(str+cur, "[ "); cur = strlen(str); + for (int i=0; i<len; i++) { + if (type == 'i') { + sprintf(str+cur, "%d", (int)(intptr_t)(arr+i*sizeof(int))); + cur = strlen(str); + } + if (type == 'c') { + printf("%d\n", ((int8_t*)(intptr_t)(arr))[i]); + sprintf(str+cur, "%d", ((int8_t*)(intptr_t)(arr))[i]); + cur = strlen(str); + } + if (i < len-1) { + sprintf(str+cur, ", "); cur = strlen(str); + } + } + sprintf(str+cur, " ]"); +} + +int json_parse_subtokens (char *json, jsmntok_t *t, int r, int i) { + int rt = 0; + for (int j=i; j<r; j++) { + if (t[j].start < t[i].end) { rt ++; } + else { break; } + } + return rt; +} + +/* DEPRECATED TRIALS, delete after backup +// parses a <str, int> pair set with a set of already parsed tokens +int json_parse_dict_ci_init (char *json, + pair_ci *dict, jsmntok_t *t, int r) { + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i++) { + if (t[i].type == JSMN_OBJECT) { + dict_i ++; + obj_i = 0; + } + if (t[i].type == JSMN_STRING) { + if (obj_i == 0) { + substr_token(json, dict[dict_i].key, t+i); + } else if (obj_i == 1) { + char ts[13]; substr_token(json, ts, t+i); + dict[dict_i].i = atoi(ts); + } + obj_i++; + } + } + return dict_i+1; +} + +// parses a <str, int> pair set with a set of already parsed tokens +int json_parse_dict_cf_init (char *json, + pair_cf *dict, jsmntok_t *t, int r) { + int obj_i = 0, dict_i = -1; + for (int i=0; i<r; i++) { + if (t[i].type == JSMN_OBJECT) { + dict_i ++; + obj_i = 0; + } + if (t[i].type == JSMN_STRING) { + if (obj_i == 0) { + substr_token(json, dict[dict_i].key, t+i); + } else if (obj_i == 1) { + char ts[13]; substr_token(json, ts, t+i); + dict[dict_i].i = atof(ts); + } + obj_i++; + } + } + return dict_i+1; +} + + +// parses a <str, int> pair set +int json_parse_dict_ci (char *json, pair_ci *dict) { + jsmn_parser p; jsmn_init(&p); + jsmntok_t t[MAXTOKENS]; + int r = jsmn_parse(&p, json, strlen(json), t, MAXTOKENS); + json_parse_dict_ci_init(json, dict, t, r); +} + +// parses a <str, float> pair set +int json_parse_dict_cf (char *json, pair_cf *dict) { + jsmn_parser p; jsmn_init(&p); + jsmntok_t t[MAXTOKENS]; + int r = jsmn_parse(&p, json, strlen(json), t, MAXTOKENS); + json_parse_dict_cf_init(json, dict, t, r); +} + + + +// parses a list of objects which are lists of pairs <str, int> +int json_parse_list_ci (char *json, list_ci *list) { + jsmn_parser p; jsmn_init(&p); + jsmntok_t t[MAXTOKENS]; + int r = jsmn_parse(&p, json, strlen(json), t, MAXTOKENS); + int list_i = 0; + for (int i=1; i<r; i++) { // i=1: ignore outer [] + if (t[i].type == JSMN_ARRAY) { + int rt = 0; + for (int j=i; j<r; j++) { + if (t[j].start < t[i].end) { rt ++; } + else { break; } + } + int len = json_parse_dict_ci_init( + json, list[list_i].pairs, t+i, rt); + list[list_i].len = len; + list_i ++; + i += rt-1; + } + } + return list_i; +} + +// parses a list of objects which are lists of pairs <str, float> +int json_parse_list_cf (char *json, list_cf *list) { + jsmn_parser p; jsmn_init(&p); + jsmntok_t t[MAXTOKENS]; + int r = jsmn_parse(&p, json, strlen(json), t, MAXTOKENS); + int list_i = 0; + for (int i=1; i<r; i++) { // i=1: ignore outer [] + if (t[i].type == JSMN_ARRAY) { + int rt = 0; + for (int j=i; j<r; j++) { + if (t[j].start < t[i].end) { rt ++; } + else { break; } + } + int len = json_parse_dict_cf_init( + json, list[list_i].pairs, t+i, rt); + list[list_i].len = len; + list_i ++; + i += rt-1; + } + } + return list_i; +} +*/
\ No newline at end of file diff --git a/json/jsonparse.h b/json/jsonparse.h new file mode 100644 index 0000000..2186154 --- /dev/null +++ b/json/jsonparse.h @@ -0,0 +1,35 @@ +#ifndef JSONPARSE_H +#define JSONPARSE_H + +#define JSMN_STATIC +#include <jsmn.h> + +#define MAXTOKENS 2048 + +void substr_token(char *json, char *temp, jsmntok_t *t); + +void json_parse_array(char *json, void *temp, jsmntok_t *t, int r, char type); +void json_dump_array (char *str, void *arr, int len, char type); + +int json_parse_subtokens (char *json, jsmntok_t *t, int r, int i); +/* + +typedef struct { char key[32]; int i; } pair_ci; +typedef struct { char key[32]; float i; } pair_cf; + + +int json_parse_dict_ci_init (char *json, pair_ci *dict, jsmntok_t *t, int r); +int json_parse_dict_cf_init (char *json, pair_cf *dict, jsmntok_t *t, int r); +int json_parse_dict_ci (char *json, pair_ci *dict); +int json_parse_dict_cf (char *json, pair_cf *dict); + +#define MAXLISTLEN 64 +#define MAXOBJLEN 32 + +typedef struct { pair_ci pairs[MAXOBJLEN]; int len; } list_ci; +typedef struct { pair_cf pairs[MAXOBJLEN]; int len; } list_cf; + +int json_parse_list_ci (char *json, list_ci *list); +int json_parse_list_cf (char *json, list_cf *list); +*/ +#endif
\ No newline at end of file @@ -0,0 +1,61 @@ +# Jacopo Grandi, 15/08/2020 +# Link - Compile - Build +# mingw command creation and execution + +try: + import os + import sys + + if len(sys.argv) > 1: + os.chdir(sys.argv[1]) + + if not("main.c" in os.listdir(".")): + # try searching father folder + os.chdir("../") + if not("main.c" in os.listdir(".")): + print("no main.c found, press any key to abort...") + import msvcrt as m + m.getch() + quit() + + dirs = "-I. " + fs = "" + for d in os.listdir("."): + if d.find(".") == -1: + flag = False + for f in os.listdir("./"+d+"/"): + if f.endswith(".c"): + fs += d+"/"+f+" " + flag = True + if flag: dirs += "-I" + d + " " + + cons = "" + f = open("main.c", "r"); + mainraw = f.read(); f.close(); + if "#define LCB_NO_CONSOLE" in mainraw.splitlines(): + cons = "-Wl,-subsystem,windows" + + os.system("mkdir build") + cmd = "g++ "+\ + "main.c "+\ + fs+\ + dirs+\ + "-IC:\MinGW_libs\include\SDL2 "+\ + "-IC:\MinGW_libs\include\plibsys "+\ + "-LC:\MinGW_libs\lib "+\ + "-w "+\ + "-lmingw32 -lSDL2main -lSDL2 -lSDL2_mixer -lplibsys "+\ + "-o build/test "+\ + cons + print(cmd) + r = os.system(cmd) + + if r == 0: + print("build successfull") + os.chdir("build") + os.system("test.exe") + else: + os.system("pause") +except e: + import traceback; + open("error.txt", "w").write(''.join(tb.format_exception(None, e, e.__traceback__)))
\ No newline at end of file @@ -0,0 +1,231 @@ +//#define LCB_NO_CONSOLE + +#include <SDL.h> +#include <SDL_mixer.h> +#include <stdio.h> +#include <math.h> + +#include <jsonparse.h> +#include <render_text.h> +#include <graphicsettings.h> +#include <button.h> +#include <mkb.h> +#include <vec.h> +#include <net.h> + +#include <units.h> +#include <map.h> +#include <info.h> +#include <hud.h> +#include <gst.h> + +//The music that will be played +Mix_Music *gMusic = NULL; + +//The sound effects that will be used +Mix_Chunk *sounds[16]; + + +int main( int argc, char* args[] ) { + net_init(); + + graphic_settings gs = { 1250, 700 }; + + SDL_Window* window = NULL; + SDL_Surface* screenSurface = NULL; + SDL_Renderer* rend = NULL; + + SDL_Init(SDL_INIT_VIDEO); + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); + + window = SDL_CreateWindow("DESCRIPT", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, gs.resx, gs.resy, SDL_WINDOW_SHOWN + | SDL_WINDOW_RESIZABLE); + screenSurface = SDL_GetWindowSurface(window); + + rend = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + + // render text init + txtd textd; char_width_init(textd.cw); + SDL_Surface* image = SDL_LoadBMP("content/gf.bmp"); + textd.tex = SDL_CreateTextureFromSurface(rend, image); + + SDL_Surface* sprites = SDL_LoadBMP("content/sprites.bmp"); + SDL_Texture* txsprites = SDL_CreateTextureFromSurface(rend, sprites); + + Mix_OpenAudio( 44100, MIX_DEFAULT_FORMAT, 2, 2048 ); + #define SOUND_MOUSE_OVER 0 + sounds[SOUND_MOUSE_OVER] = Mix_LoadWAV( + "content/sounds/mouse_over.wav" ); + #define SOUND_MOUSE_CLICK_0 1 + sounds[SOUND_MOUSE_CLICK_0] = Mix_LoadWAV( + "content/sounds/mouse_click_0.wav" ); + #define SOUND_MOUSE_WHEEL 2 + sounds[SOUND_MOUSE_WHEEL] = Mix_LoadWAV( + "content/sounds/mouse_wheel.wav" ); + #define SOUND_SUCCESS 3 + sounds[SOUND_SUCCESS] = Mix_LoadWAV( + "content/sounds/success.wav" ); + Mix_Volume(-1,MIX_MAX_VOLUME/16); + // Mix_PlayChannel( -1, mouse_over, 0 ); + + // frame timing + const double FRAME_TIME = (double)1/60; // delta time for 60 FPS + double last_time = SDL_GetTicks(); + double frame_counter = 0; + double tot_time = 0; + double unprocessed_time = 0; + int frames = 0; + + // mouse and keyboard + MKb mkb; + mkb_init(&mkb); + + + // info + infos info; + info_load(&info); + + gamestate gst; + gst_init(&gst); + gst.cam[0] = -gs.resx/2+gst.map_editor.sx*gst.map_editor.ts/2; + gst.cam[1] = -gs.resy/2+gst.map_editor.sy*gst.map_editor.ts/2; + + // hud + hud _hud; + hud_init(&gs, &_hud, &textd); + _hud.og.army_listlen = info_army_get_list(_hud.og.army_list); + info_load_playername(_hud.og.playername); + + float mlast[2] = {0, 0}; + + // sockets + net_client netc; + net_server nets; + int server = 0; + + bool quit = false; + SDL_Event e; + while(!quit) { + while(SDL_PollEvent(&e) != 0) { + if(e.type == SDL_QUIT) { + quit = true; + } + if(e.type == SDL_WINDOWEVENT + && e.window.event == SDL_WINDOWEVENT_RESIZED ) { + gs.resx = e.window.data1; gs.resy = e.window.data2; + SDL_SetWindowSize(window, gs.resx, gs.resy); + hud_resize(&gs, &_hud, &textd); + } + mkb_event(&mkb, &e); + } + + bool render = false; + + double startTime = SDL_GetTicks(); + double passedTime = (startTime - last_time)/1000; + last_time = startTime; + + unprocessed_time += passedTime; + frame_counter += passedTime; + tot_time += passedTime; + + if (frame_counter >= 1.0) { + //printf("FPS: %i | %f ms\n", frames, 1000.0 / ((double)frames)); + frames = 0; + frame_counter = 0; + } + + while (unprocessed_time > FRAME_TIME) { + float mp[2] = { mkb.mx, mkb.my }; + if (mkb.mclick[1] == 1) { + float delta[2] = { mkb.mx-mlast[0], mkb.my-mlast[1] }; + vec2_sub(gst.cam, gst.cam, delta); + } + /* + if (mkb_search(&mkb, SDL_SCANCODE_E)) { + map *m; army *ar; + gst_get_maparmy(&gst, &m, &ar); + army_move(&info, ar, m); + army_fire(&info, ar, m); + }*/ + + hud_process(&gs, &_hud, &mkb, &info, + gst.army_bp+0, &gst.map_editor, &textd, &gst, + &netc, &nets, sounds); + + if (gst.state == 1) { + gst_process(&gst, &info, tot_time); + } + + render = true; + unprocessed_time -= FRAME_TIME; + mlast[0] = mkb.mx; mlast[1] = mkb.my; + mkb_process(&mkb); + } + + if (render) { + SDL_SetRenderDrawColor(rend, 255, 255, 255, 255); + SDL_RenderClear(rend); + + float ts = 32; + int posx = gst.cam[0]; + int posy = gst.cam[1]; + + map *m; army *ar; + gst_get_maparmy(&gst, &m, &ar); + + // render map + for (int y=0; y<m->sy; y++) { + for (int x=0; x<m->sx; x++) { + float px = x*ts; + float py = y*ts; + SDL_Rect srcRect = { 1*ts, 0*ts, ts, ts }; + SDL_Rect dstRect = { (int)px-posx, (int)py-posy, ts, ts }; + SDL_RenderCopy(rend, txsprites, &srcRect, &dstRect); + } + } + + // render enemies + for (int i=0; i<ar->uslen; i++) { + if (ar->us[i].hp <= 0) continue; + float x = ar->us[i].pos[0]; + float y = ar->us[i].pos[1]; + SDL_Rect srcRect = { ar->us[i].info.chassis*ts, ts, ts, ts }; + SDL_Rect dstRect = { (int)x-posx, (int)y-posy, ts, ts }; + SDL_RenderCopy(rend, txsprites, &srcRect, &dstRect); + + float amt = ar->us[i].hp + / info_unit_get_health(&info, &ar->us[i].info); + SDL_Rect hprect = { + (int)x-posx, (int)y-posy+ts-5, + ts*amt, 5 }; + int sw = 1 ? ar->us[i].owner : 0; + SDL_SetRenderDrawColor(rend, 255*sw, 255*(1-sw), 0, 255); + SDL_RenderFillRect(rend, &hprect); + + char shp[32]; sprintf(shp, "%.0f", ar->us[i].hp); + float php[2] = { (int)x-posx, (int)y-posy+ts-5 }; + render_text_scaled(rend, shp, php, &textd, 1); + } + + hud_render(&_hud, rend, &textd, &mkb, &info, txsprites); + + SDL_RenderPresent(rend); + frames++; + } + else { + SDL_Delay(1); + } + } + + Mix_FreeMusic(gMusic); + SDL_DestroyWindow(window); + Mix_Quit(); + SDL_Quit(); + net_client_close(&netc); + gst_destroy(&gst); + + return 0; +}
\ No newline at end of file diff --git a/mkb/mkb.c b/mkb/mkb.c new file mode 100644 index 0000000..169aa8c --- /dev/null +++ b/mkb/mkb.c @@ -0,0 +1,53 @@ +#include <mkb.h> + +bool mkb_search(MKb *mkb, SDL_Scancode scancode) { + for (int i=0; i<mkb->kbnum; i++) { + if (mkb->kb[i] == scancode) + return true; + } + return false; +} + +bool mkb_statesearch (MKb *mkb, SDL_Scancode scancode) { + const Uint8 *state = SDL_GetKeyboardState(NULL); + if (state[scancode]) return true; + return false; +} + +void mkb_init(MKb *mkb) { + mkb->kbnum = 0; + for (int i=0;i<3;mkb->mheld[i]=0,mkb->mclick[i]=0,i++); + mkb->mwheeldelta = 0; +} + +void mkb_process(MKb *mkb) { + mkb->kbnum = 0; + SDL_GetMouseState(&(mkb->mx), &(mkb->my)); + for (int i=0;i<3;i++) { + if (mkb->mclick[i] > 0) mkb->mheld[i] += 1; + else if (mkb->mheld[i] > 0) mkb->mheld[i] = -1; + else mkb->mheld[i] = 0; + } + mkb->mwheeldelta = 0; +} + +void mkb_event(MKb *mkb, SDL_Event *e) { + if(e->type == SDL_KEYDOWN && e->key.repeat == 0) { + mkb->kb[mkb->kbnum++] = e->key.keysym.scancode; + } + if(e->type == SDL_KEYUP) { + } + if(e->type == SDL_MOUSEBUTTONDOWN) { + if (e->button.button == SDL_BUTTON_LEFT) { mkb->mclick[0] = 1; } + if (e->button.button == SDL_BUTTON_MIDDLE) { mkb->mclick[1] = 1; } + if (e->button.button == SDL_BUTTON_RIGHT) { mkb->mclick[2] = 1; } + } + if(e->type == SDL_MOUSEBUTTONUP) { + if (e->button.button == SDL_BUTTON_LEFT) { mkb->mclick[0] = 0; } + if (e->button.button == SDL_BUTTON_MIDDLE) { mkb->mclick[1] = 0; } + if (e->button.button == SDL_BUTTON_RIGHT) { mkb->mclick[2] = 0; } + } + if(e->type == SDL_MOUSEWHEEL) { + mkb->mwheeldelta = e->wheel.y; + } +}
\ No newline at end of file diff --git a/mkb/mkb.h b/mkb/mkb.h new file mode 100644 index 0000000..74b1a47 --- /dev/null +++ b/mkb/mkb.h @@ -0,0 +1,24 @@ +#ifndef MKB_H +#define MKB_H + +#include <SDL.h> + +// SDL2 mouse and keyboard + +typedef struct { + SDL_Scancode kb[128]; /* keyboard state, reset every frame */ + int kbnum; + int mx; /* mouse x pos */ + int my; /* mouse y pos */ + int mclick[3]; + int mheld[3]; + int mwheeldelta; +} MKb; + +void mkb_init(MKb *mkb); +bool mkb_search(MKb *mkb, SDL_Scancode scancode); +bool mkb_statesearch(MKb *mkb, SDL_Scancode scancode); +void mkb_event(MKb *mkb, SDL_Event *e); +void mkb_process(MKb *mkb); + +#endif
\ No newline at end of file diff --git a/net/net.c b/net/net.c new file mode 100644 index 0000000..7e1dbf4 --- /dev/null +++ b/net/net.c @@ -0,0 +1,168 @@ +#include <net.h> + +void itob (char *buf, int n) { + buf[0] = (n >> 24) & 0xFF; + buf[1] = (n >> 16) & 0xFF; + buf[2] = (n >> 8) & 0xFF; + buf[3] = n & 0xFF; +} + +int btoi (char *buf) { + int n = 0; + n += buf[0]*256*256*256; + n += buf[1]*256*256; + n += buf[2]*256; + n += buf[3]; + return n; +} + + +void net_init () { + p_libsys_init (); +} + +int net_open_socket(PSocket **socket, int port) { + *socket = p_socket_new (P_SOCKET_FAMILY_INET, + P_SOCKET_TYPE_STREAM, + P_SOCKET_PROTOCOL_TCP, + NULL); + p_socket_set_blocking (*socket, FALSE); + p_socket_set_timeout (*socket, 10); + PSocketAddress *sock_addr = p_socket_address_new("127.0.0.1", port); + int sender_port = 0; + if (p_socket_bind (*socket, sock_addr, FALSE, NULL) == FALSE) { + p_socket_free (*socket); + p_socket_address_free (sock_addr); + return 1; + } else { + p_socket_address_free (sock_addr); + PSocketAddress *local_addr = p_socket_get_local_address(*socket, NULL); + if (local_addr == NULL) { + p_socket_free (*socket); + p_uthread_exit (-1); + return 2; + } + sender_port = p_socket_address_get_port (local_addr); + p_socket_address_free (local_addr); + } + return 0; +} + +int net_recv (PSocket *socket, char buffer[]) { + int len = 0; + for (int i=0; ; i++) { + psize recv_now = p_socket_receive (socket, + buffer+i*1024, 1024, NULL); + if (recv_now == -1) { + if (len > 0) { + printf("received (%d)\n", len); + return len; + } + printf("error server recv\n"); + return -1; + } else { + len += recv_now; + if (recv_now < 1024) { + printf("received (%d)\n", len); + return len; + } + } + } + printf("received (%d)\n", len); + return len; +} + + +void net_client_open(net_client *c) { + int err = net_open_socket(&c->socket, 0); + if (err > 0) printf("error opening client socket: %d\n", err); +} + +int net_client_connect (net_client *c, char ip[], int port) { + c->addr_server = p_socket_address_new(ip, port); + if (c->addr_server == NULL) printf("error client making server addr\n"); + int is_connected = p_socket_connect(c->socket, c->addr_server, NULL); + if (is_connected == FALSE) { + if (p_socket_io_condition_wait + (c->socket, P_SOCKET_IO_CONDITION_POLLOUT, NULL) == TRUE && + p_socket_check_connect_result (c->socket, NULL) == FALSE) + { + p_socket_address_free (c->addr_server); + p_socket_free (c->socket); + p_uthread_exit (-1); + printf("error client socket freed\n"); + } + } + + is_connected = p_socket_is_connected (c->socket); + if (is_connected == FALSE) { + printf("error client can't connect to %s:%d\n", ip, port); + return 1; + } + return 0; +} + +void net_client_send (net_client *c, char data[], int sizeofdata) { + if(p_socket_is_connected (c->socket) == FALSE) { + printf("error client send lost connection\n"); + } + PError *err; + int send_now = p_socket_send (c->socket, data, sizeofdata, &err); + if (send_now == -1) printf("error: %d\n", p_error_get_code(err)); +} + +int net_client_recv (net_client *c, char buffer[]) { + net_recv(c->socket, buffer); +} + +void net_client_close (net_client *c) { + p_socket_close (c->socket, NULL); + p_socket_address_free (c->addr_server); + p_socket_free (c->socket); +} + + + +void net_server_open(net_server *s, int port) { + int err = net_open_socket(&s->socket, port); + if (err > 0) printf("error opening server socket: %d\n", err); + if (p_socket_listen (s->socket, NULL) == FALSE) { + printf("error server socket listen, nobody in.\n"); + return; + } +} + +void net_server_accept (net_server *s) { + pboolean poll = p_socket_io_condition_wait (s->socket, + P_SOCKET_IO_CONDITION_POLLIN, NULL); + if (poll == FALSE) { + printf("server socket, no one in queue\n"); + return; + } + s->sock_client = p_socket_accept (s->socket, NULL); + if (s->sock_client == NULL) { + printf("server socket, no accept\n"); + } + p_socket_set_blocking (s->sock_client, FALSE); + printf("connected\n"); +} + +int net_server_recv (net_server *s, char buffer[]) { + net_recv(s->sock_client, buffer); +} + +void net_server_send (net_server *s, char data[], int sizeofdata) { + if(p_socket_is_connected (s->sock_client) == FALSE) { + printf("error client send lost connection\n"); + return; + } + PError *err; + int send_now = p_socket_send (s->sock_client, data, sizeofdata, &err); + if (send_now == -1) printf("error: %d\n", p_error_get_code(err)); +} + +void net_server_close (net_server *s) { + p_socket_close (s->socket, NULL); + p_socket_free (s->sock_client); + p_socket_free(s->socket); +} diff --git a/net/net.h b/net/net.h new file mode 100644 index 0000000..056114b --- /dev/null +++ b/net/net.h @@ -0,0 +1,35 @@ +#ifndef NET_H +#define NET_H + +#include <plibsys.h> + +#define SERVER_PORT 9999 + +void itob (char *buf, int n); +int btoi (char *buf); + +void net_init (); + +typedef struct { + PSocket *socket; + PSocketAddress * addr_server; +} net_client; + +void net_client_open(net_client *c); +int net_client_connect (net_client *c, char ip[], int port); +int net_client_recv(net_client *c, char buffer[]); +void net_client_send (net_client *c, char data[], int sizeofdata); +void net_client_close (net_client *c); + +typedef struct { + PSocket *socket; + PSocket *sock_client; +} net_server; + +void net_server_open(net_server *s, int port); +void net_server_accept(net_server *s); +int net_server_recv(net_server *s, char buffer[]); +void net_server_send (net_server *s, char data[], int sizeofdata); +void net_server_close (net_server *s); + +#endif
\ No newline at end of file diff --git a/render/button.c b/render/button.c new file mode 100644 index 0000000..eb96f59 --- /dev/null +++ b/render/button.c @@ -0,0 +1,21 @@ +#include <stdlib.h> +#include <stdio.h> +#include <button.h> + +#include <intersect.h> + +bool mouse_in_button (float pt[], txtd *t, button *b) { + int width = get_text_width(b->txt, t); + float size[2] = { width+b->pad*2, 10+b->pad*2 }; + if (pt_rect(pt, b->pos, size)) return true; + return false; +} + +void render_button (SDL_Renderer* rend, txtd *t, button *b) { + int width = get_text_width(b->txt, t); + SDL_Rect rect = { b->pos[0], b->pos[1], width+b->pad*2, 10+b->pad*2 }; + SDL_SetRenderDrawColor(rend, 0, 0, 0, 255); + SDL_RenderDrawRect(rend, &rect); + float offpad[2] = { b->pos[0]+b->pad, b->pos[1]+b->pad }; + render_text(rend, b->txt, offpad, t); +}
\ No newline at end of file diff --git a/render/button.h b/render/button.h new file mode 100644 index 0000000..b8d10b6 --- /dev/null +++ b/render/button.h @@ -0,0 +1,16 @@ +#ifndef BUTTON_H +#define BUTTON_H + +#include <SDL.h> +#include <render_text.h> + +typedef struct { + char txt[32]; + int pad; + float pos[2]; +} button; + +bool mouse_in_button (float pt[], txtd *t, button *b); +void render_button (SDL_Renderer* rend, txtd *t, button *b); + +#endif
\ No newline at end of file diff --git a/render/graphicsettings.h b/render/graphicsettings.h new file mode 100644 index 0000000..53a83c2 --- /dev/null +++ b/render/graphicsettings.h @@ -0,0 +1,8 @@ +#ifndef GRAPHICSETTINGS_H +#define GRAPHICSETTINGS_H + +typedef struct { + int resx, resy; +} graphic_settings; + +#endif
\ No newline at end of file diff --git a/render/render_text.c b/render/render_text.c new file mode 100644 index 0000000..67a13e2 --- /dev/null +++ b/render/render_text.c @@ -0,0 +1,48 @@ +#include <stdlib.h> +#include <stdio.h> +#include <render_text.h> + +void char_width_init (int *char_width) { + for (int i=0; i<128; char_width[i++]=5); + char_width[','] = 1; char_width['-'] = 3; char_width['.'] = 1; + char_width['/'] = 4; char_width['!'] = 1; + char_width[':'] = 1; char_width[';'] = 1; + char_width['<'] = 3; char_width['>'] = 3; char_width['='] = 4; + char_width['I'] = 1; + char_width['f'] = 4; char_width['i'] = 1; char_width['j'] = 3; + char_width['l'] = 1; char_width['k'] = 4; char_width['t'] = 4; +} + +int get_text_width (char str[], txtd *t) { + int width = 0; + for (int i=0; str[i]!='\0'; i++) { + width += t->cw[str[i]]; + if (str[i+1]!='\0') width++; + } + return width; +} + +void render_text (SDL_Renderer* gRenderer, char str[], float off[], txtd *t) +{ + int width = 0; + for (int i=0; str[i]!='\0'; i++) { + int char_i = str[i]; + SDL_Rect srcRect = { (char_i%32)*6+1, (char_i/32)*12+1, 5, 11 }; + SDL_Rect dstRect = { off[0]+width, off[1], 5, 11 }; + SDL_RenderCopy(gRenderer, t->tex, &srcRect, &dstRect); + width += t->cw[char_i]+1; + } +} + +void render_text_scaled (SDL_Renderer* gRenderer, char str[], + float off[], txtd *t, float scale) +{ + int width = 0; + for (int i=0; str[i]!='\0'; i++) { + int char_i = str[i]; + SDL_Rect srcRect = { (char_i%32)*6+1, (char_i/32)*12+1, 5, 11 }; + SDL_Rect dstRect = { off[0]+width, off[1], 5*scale, 11*scale }; + SDL_RenderCopy(gRenderer, t->tex, &srcRect, &dstRect); + width += t->cw[char_i]*scale+1*scale; + } +}
\ No newline at end of file diff --git a/render/render_text.h b/render/render_text.h new file mode 100644 index 0000000..e7474ff --- /dev/null +++ b/render/render_text.h @@ -0,0 +1,18 @@ +#ifndef RENDER_TEXT_H +#define RENDER_TEXT_H + +#include <SDL.h> + +typedef struct { + SDL_Texture *tex; + int cw[128]; +} txtd; + +void char_width_init (int *char_width); +int get_text_width (char str[], txtd *t); + +void render_text (SDL_Renderer* gRenderer, char str[], float off[], txtd *t); +void render_text_scaled (SDL_Renderer* gRenderer, char str[], + float off[], txtd *t, float scale); + +#endif
\ No newline at end of file diff --git a/umath/intersect.c b/umath/intersect.c new file mode 100644 index 0000000..2d21389 --- /dev/null +++ b/umath/intersect.c @@ -0,0 +1,7 @@ +#include <intersect.h> + +int pt_rect (float p[], float a[], float b[]) { + if (p[0]>a[0] && p[0]<a[0]+b[0] && p[1]>a[1] && p[1]<a[1]+b[1]) + return 1; + return 0; +}
\ No newline at end of file diff --git a/umath/intersect.h b/umath/intersect.h new file mode 100644 index 0000000..d3e24ec --- /dev/null +++ b/umath/intersect.h @@ -0,0 +1,7 @@ +#ifndef INTERSECT_H +#define INTERSECT_H + +// rect is [a, b] = [pos, size] +int pt_rect (float p[], float a[], float b[]); + +#endif
\ No newline at end of file diff --git a/umath/vec.c b/umath/vec.c new file mode 100644 index 0000000..fe82f58 --- /dev/null +++ b/umath/vec.c @@ -0,0 +1,42 @@ +#include <vec.h> + +float vec2_add (float c[], float a[], float b[]) { + c[0]=a[0]+b[0]; c[1]=a[1]+b[1]; +} +float vec2_sub (float c[], float a[], float b[]) { + c[0]=a[0]-b[0]; c[1]=a[1]-b[1]; +} +float vec2_mul (float c[], float a[], float b) { + c[0]=a[0]*b; c[1]=a[1]*b; +} +float vec2_div (float c[], float a[], float b) { + c[0]=a[0]/b; c[1]=a[1]/b; +} + +float vec2_mag (float v[]) { return sqrt(v[0]*v[0]+v[1]*v[1]); } +float vec2_mag2 (float v[]) { return v[0]*v[0]+v[1]*v[1]; } + +void vec2_norm (float v[]) { + float m=vec2_mag(v); v[0]/=m; v[1]/=m; +} + + +float vec3_add (float c[], float a[], float b[]) { + c[0]=a[0]+b[0]; c[1]=a[1]+b[1]; c[2]=a[2]+b[2]; +} +float vec3_sub (float c[], float a[], float b[]) { + c[0]=a[0]-b[0]; c[1]=a[1]-b[1]; c[2]=a[2]-b[2]; +} +float vec3_mul (float c[], float a[], float b) { + c[0]=a[0]*b; c[1]=a[1]*b; c[2]=a[2]*b; +} +float vec3_div (float c[], float a[], float b) { + c[0]=a[0]/b; c[1]=a[1]/b; c[2]=a[2]/b; +} + +float vec3_mag (float v[]) { return sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); } +float vec3_mag2 (float v[]) { return v[0]*v[0]+v[1]*v[1]+v[2]*v[2]; } + +void vec3_norm (float v[]) { + float m=vec3_mag(v); v[0]/=m; v[1]/=m; v[2]/=m; +}
\ No newline at end of file diff --git a/umath/vec.h b/umath/vec.h new file mode 100644 index 0000000..b87cae1 --- /dev/null +++ b/umath/vec.h @@ -0,0 +1,22 @@ +#ifndef VEC_H +#define VEC_H + +#include <math.h> + +float vec2_add (float c[], float a[], float b[]); +float vec2_sub (float c[], float a[], float b[]); +float vec2_mul (float c[], float a[], float b); +float vec2_div (float c[], float a[], float b); +float vec2_mag (float v[]); +float vec2_mag2 (float v[]); +void vec2_norm (float v[]); + +float vec3_add (float c[], float a[], float b[]); +float vec3_sub (float c[], float a[], float b[]); +float vec3_mul (float c[], float a[], float b); +float vec3_div (float c[], float a[], float b); +float vec3_mag (float v[]); +float vec3_mag2 (float v[]); +void vec3_norm (float v[]); + +#endif
\ No newline at end of file |