Cleaning up stuff

This commit is contained in:
tognee 2019-09-18 00:09:46 +02:00
parent 5423be67ca
commit a5ea06a928
44 changed files with 7329 additions and 7432 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -2,9 +2,9 @@
echo Building 3DSX/ELF/SMDH... echo Building 3DSX/ELF/SMDH...
make make
echo Creating banner... echo Creating banner...
bannertool.exe makebanner -i icons-banners/banner.png -a icons-banners/audio.wav -o icons-banners/banner.bnr bannertool makebanner -i icons-banners/banner.png -a icons-banners/audio.wav -o icons-banners/banner.bnr
echo Creating icon... echo Creating icon...
bannertool.exe makesmdh -s "Minicraft3DS" -l "3DS Homebrew port of Notch's ludum dare game 'Minicraft', updated." -p "Davideesk/Andre111/ElijahZAwesome" -i icons-banners/icon.png -o icons-banners/icon.icn bannertool makesmdh -s "Minicraft3DS" -l "3DS Homebrew port of Notch's ludum dare game 'Minicraft', updated." -p "Davideesk/Andre111/ElijahZAwesome" -i icons-banners/icon.png -o icons-banners/icon.icn
echo Creating ROMFS... echo Creating ROMFS...
3dstool -cvtf romfs icons-banners/romfs.bin --romfs-dir romfs/ 3dstool -cvtf romfs icons-banners/romfs.bin --romfs-dir romfs/
echo Creating CIA... echo Creating CIA...

Binary file not shown.

BIN
data/icons.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

View file

@ -1,78 +0,0 @@
# Minicraft3DS
3DS Homebrew port of Notch's ludum dare game "Minicraft"
Current Version: Version 1.6.1
----------
**Download:**
If you just want to download the game prebuilt check the releases tab in Github:
https://github.com/ElijahZAwesome/Minicraft3DS/releases
For building the game yourself look below.
----------
**Dependencies:**
For building and installing the dependencies look below.
ctrulib by smea: https://github.com/smealum/ctrulib
citro3d by fincs: https://github.com/fincs/citro3d
sf2dlib by xerpi: https://github.com/xerpi/sf2dlib
sfillib by xerpi: https://github.com/xerpi/sfillib
zlib: http://www.zlib.net/
----------
**Building:**
**1. Install devkitARM by devkitPro**
- On Windows download https://sourceforge.net/projects/devkitpro/files/Automated%20Installer/
- And install atleast Minimal System and devkitARM
- This includes make, ctrulib and citro3d
**2. Install zlib, libjpeg-turbo and libpng**
- Download 3DS-Portlibs: https://github.com/devkitPro/3ds_portlibs
- Run these commands:
```
make zlib
make install-zlib
make libjpeg-turbo
make libpng
make install
```
**3. Install sf2dlib**
- Download https://github.com/xerpi/sf2dlib
- In the libsf2d directory run these commands:
```
make
make install
```
**4. Install sfillib**
- Download https://github.com/xerpi/sfillib
- In the libsfil directory run these commands:
```
make
make install
```
**5. You can now build Minicraft3DS 3dsx, elf, cia, and 3ds files by running the build.bat file.**
----------
You can do anything with the source code (besides sell it) as long as you give proper credit to the right people.
If you are going to make a mod of this version, be sure to give credit to Markus "Notch" Perrson because he did create the original game after all.
# Misc
This source code is subject to a lot of change for better optimization/cleanliness.
Forum thread: https://gbatemp.net/threads/release-new-minicraft3ds-fork-v1-4.494947/

View file

@ -1,4 +0,0 @@
theme: jekyll-theme-cayman
title: Minicraft3DS
description: A 2D Homebrew for 3DS
show_downloads: true

View file

Binary file not shown.

View file

@ -1,5 +0,0 @@
@echo off
echo Building 3DSX/ELF/SMDH...
make
echo Running in citra
%localappdata%/Citra/canary-mingw/citra-qt.exe result/Minicraft3DS.3dsx

View file

@ -1,132 +1,132 @@
#include "Crafting.h" #include "Crafting.h"
void cloneRecipeManager(RecipeManager *from, RecipeManager *to) { void cloneRecipeManager(RecipeManager *from, RecipeManager *to) {
//free old manager recipes //free old manager recipes
free(to->recipes); free(to->recipes);
//copy over recipes //copy over recipes
to->size = from->size; to->size = from->size;
to->recipes = (Recipe*)malloc(sizeof(Recipe) * to->size); to->recipes = (Recipe*)malloc(sizeof(Recipe) * to->size);
memcpy(to->recipes, from->recipes, sizeof(Recipe) * to->size); memcpy(to->recipes, from->recipes, sizeof(Recipe) * to->size);
} }
void checkCanCraftRecipes(RecipeManager * rm, Inventory * inv){ void checkCanCraftRecipes(RecipeManager * rm, Inventory * inv){
int i, j; int i, j;
for(i = 0; i < rm->size; i++){ for(i = 0; i < rm->size; i++){
rm->recipes[i].canCraft = true; rm->recipes[i].canCraft = true;
for(j = 0; j < rm->recipes[i].numOfCosts; j++){ for(j = 0; j < rm->recipes[i].numOfCosts; j++){
if(countItemInv(rm->recipes[i].costs[j].costItem,0,inv) < rm->recipes[i].costs[j].costAmount){ if(countItemInv(rm->recipes[i].costs[j].costItem,0,inv) < rm->recipes[i].costs[j].costAmount){
rm->recipes[i].canCraft = false; rm->recipes[i].canCraft = false;
} }
} }
} }
} }
int compareCanCraft(const void * ra, const void * rb) { int compareCanCraft(const void * ra, const void * rb) {
Recipe* r1 = (Recipe*)ra; Recipe* r1 = (Recipe*)ra;
Recipe* r2 = (Recipe*)rb; Recipe* r2 = (Recipe*)rb;
if (r1->canCraft && !r2->canCraft) return -1; if (r1->canCraft && !r2->canCraft) return -1;
if (!r1->canCraft && r2->canCraft) return 1; if (!r1->canCraft && r2->canCraft) return 1;
return r1->order - r2->order; // Needed for stable sorting. return r1->order - r2->order; // Needed for stable sorting.
} }
void sortRecipes(RecipeManager * rm){ void sortRecipes(RecipeManager * rm){
qsort(rm->recipes,rm->size,sizeof(Recipe),compareCanCraft); qsort(rm->recipes,rm->size,sizeof(Recipe),compareCanCraft);
} }
void deductCost(Cost c, Inventory * inv){ void deductCost(Cost c, Inventory * inv){
Item* item = getItemFromInventory(c.costItem, inv); Item* item = getItemFromInventory(c.costItem, inv);
if(!item->onlyOne){ if(!item->onlyOne){
item->countLevel -= c.costAmount; item->countLevel -= c.costAmount;
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, inv); if(item->countLevel < 1) removeItemFromInventory(item->slotNum, inv);
} else { } else {
removeItemFromInventory(item->slotNum, inv); removeItemFromInventory(item->slotNum, inv);
} }
} }
bool craftItem(RecipeManager * rm, Recipe* r, Inventory* inv){ bool craftItem(RecipeManager * rm, Recipe* r, Inventory* inv){
if(r->canCraft){ if(r->canCraft){
int i; int i;
for(i=0;i<r->numOfCosts;++i) deductCost(r->costs[i], inv); for(i=0;i<r->numOfCosts;++i) deductCost(r->costs[i], inv);
Item item = newItem(r->itemResult,r->itemAmountLevel); Item item = newItem(r->itemResult,r->itemAmountLevel);
if(!item.onlyOne && countItemInv(item.id,item.countLevel,inv) > 0){ if(!item.onlyOne && countItemInv(item.id,item.countLevel,inv) > 0){
getItemFromInventory(item.id, inv)->countLevel += r->itemAmountLevel; getItemFromInventory(item.id, inv)->countLevel += r->itemAmountLevel;
} else{ } else{
pushItemToInventoryFront(item, inv); pushItemToInventoryFront(item, inv);
} }
checkCanCraftRecipes(rm, inv); checkCanCraftRecipes(rm, inv);
sortRecipes(rm); sortRecipes(rm);
return true; return true;
} }
return false; return false;
} }
Cost newCost(int i, int c){ Cost newCost(int i, int c){
Cost nc; Cost nc;
nc.costItem = i; nc.costItem = i;
nc.costAmount = c; nc.costAmount = c;
return nc; return nc;
} }
u8 curPlace = 0; u8 curPlace = 0;
Recipe defineRecipe(int item, int amountOrLevel, int numArgs, ...){ Recipe defineRecipe(int item, int amountOrLevel, int numArgs, ...){
Recipe r; Recipe r;
r.itemResult = item; r.itemResult = item;
r.itemAmountLevel = amountOrLevel; r.itemAmountLevel = amountOrLevel;
r.numOfCosts = numArgs; r.numOfCosts = numArgs;
int i; int i;
va_list al; va_list al;
numArgs <<= 1; // Did this to get rid of a warning. numArgs <<= 1; // Did this to get rid of a warning.
va_start(al,numArgs); va_start(al,numArgs);
for(i=0;i<r.numOfCosts;++i) r.costs[i] = newCost(va_arg(al,int), va_arg(al,int)); for(i=0;i<r.numOfCosts;++i) r.costs[i] = newCost(va_arg(al,int), va_arg(al,int));
va_end(al); va_end(al);
r.order = curPlace; r.order = curPlace;
curPlace++; curPlace++;
return r; return r;
} }
void initRecipes(){ void initRecipes(){
curPlace = 0; curPlace = 0;
workbenchRecipes.size = 22; workbenchRecipes.size = 22;
workbenchRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (workbenchRecipes.size)); workbenchRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (workbenchRecipes.size));
workbenchRecipes.recipes[0] = defineRecipe(ITEM_WORKBENCH,1,1,ITEM_WOOD,20); workbenchRecipes.recipes[0] = defineRecipe(ITEM_WORKBENCH,1,1,ITEM_WOOD,20);
workbenchRecipes.recipes[1] = defineRecipe(ITEM_FURNACE,1,1,ITEM_STONE,20); workbenchRecipes.recipes[1] = defineRecipe(ITEM_FURNACE,1,1,ITEM_STONE,20);
workbenchRecipes.recipes[2] = defineRecipe(ITEM_OVEN,1,1,ITEM_STONE,20); workbenchRecipes.recipes[2] = defineRecipe(ITEM_OVEN,1,1,ITEM_STONE,20);
workbenchRecipes.recipes[3] = defineRecipe(ITEM_CHEST,1,1,ITEM_WOOD,20); workbenchRecipes.recipes[3] = defineRecipe(ITEM_CHEST,1,1,ITEM_WOOD,20);
workbenchRecipes.recipes[4] = defineRecipe(ITEM_ANVIL,1,1,ITEM_IRONINGOT,5); workbenchRecipes.recipes[4] = defineRecipe(ITEM_ANVIL,1,1,ITEM_IRONINGOT,5);
workbenchRecipes.recipes[5] = defineRecipe(ITEM_LANTERN,1,3,ITEM_WOOD,5,ITEM_SLIME,10,ITEM_GLASS,4); workbenchRecipes.recipes[5] = defineRecipe(ITEM_LANTERN,1,3,ITEM_WOOD,5,ITEM_SLIME,10,ITEM_GLASS,4);
workbenchRecipes.recipes[6] = defineRecipe(ITEM_LOOM,1,2,ITEM_WOOD,10,ITEM_WOOL,5); workbenchRecipes.recipes[6] = defineRecipe(ITEM_LOOM,1,2,ITEM_WOOD,10,ITEM_WOOL,5);
workbenchRecipes.recipes[7] = defineRecipe(TOOL_SWORD,0,1,ITEM_WOOD,5); workbenchRecipes.recipes[7] = defineRecipe(TOOL_SWORD,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[8] = defineRecipe(TOOL_AXE,0,1,ITEM_WOOD,5); workbenchRecipes.recipes[8] = defineRecipe(TOOL_AXE,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[9] = defineRecipe(TOOL_HOE,0,1,ITEM_WOOD,5); workbenchRecipes.recipes[9] = defineRecipe(TOOL_HOE,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[10] = defineRecipe(TOOL_PICKAXE,0,1,ITEM_WOOD,5); workbenchRecipes.recipes[10] = defineRecipe(TOOL_PICKAXE,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[11] = defineRecipe(TOOL_SHOVEL,0,1,ITEM_WOOD,5); workbenchRecipes.recipes[11] = defineRecipe(TOOL_SHOVEL,0,1,ITEM_WOOD,5);
workbenchRecipes.recipes[12] = defineRecipe(TOOL_BOW,0,2,ITEM_WOOD,10,ITEM_STRING,1); workbenchRecipes.recipes[12] = defineRecipe(TOOL_BOW,0,2,ITEM_WOOD,10,ITEM_STRING,1);
workbenchRecipes.recipes[13] = defineRecipe(ITEM_ARROW_WOOD,1,2,ITEM_WOOD,2,ITEM_STRING,1); workbenchRecipes.recipes[13] = defineRecipe(ITEM_ARROW_WOOD,1,2,ITEM_WOOD,2,ITEM_STRING,1);
workbenchRecipes.recipes[14] = defineRecipe(TOOL_SWORD,1,2,ITEM_WOOD,5,ITEM_STONE,5); workbenchRecipes.recipes[14] = defineRecipe(TOOL_SWORD,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[15] = defineRecipe(TOOL_AXE,1,2,ITEM_WOOD,5,ITEM_STONE,5); workbenchRecipes.recipes[15] = defineRecipe(TOOL_AXE,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[16] = defineRecipe(TOOL_HOE,1,2,ITEM_WOOD,5,ITEM_STONE,5); workbenchRecipes.recipes[16] = defineRecipe(TOOL_HOE,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[17] = defineRecipe(TOOL_PICKAXE,1,2,ITEM_WOOD,5,ITEM_STONE,5); workbenchRecipes.recipes[17] = defineRecipe(TOOL_PICKAXE,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[18] = defineRecipe(TOOL_SHOVEL,1,2,ITEM_WOOD,5,ITEM_STONE,5); workbenchRecipes.recipes[18] = defineRecipe(TOOL_SHOVEL,1,2,ITEM_WOOD,5,ITEM_STONE,5);
workbenchRecipes.recipes[19] = defineRecipe(ITEM_ARROW_STONE,1,3,ITEM_WOOD,1,ITEM_STONE,1,ITEM_STRING,1); workbenchRecipes.recipes[19] = defineRecipe(ITEM_ARROW_STONE,1,3,ITEM_WOOD,1,ITEM_STONE,1,ITEM_STRING,1);
workbenchRecipes.recipes[20] = defineRecipe(ITEM_WALL_WOOD,1,1,ITEM_WOOD,4); workbenchRecipes.recipes[20] = defineRecipe(ITEM_WALL_WOOD,1,1,ITEM_WOOD,4);
workbenchRecipes.recipes[21] = defineRecipe(ITEM_WALL_STONE,1,1,ITEM_STONE,4); workbenchRecipes.recipes[21] = defineRecipe(ITEM_WALL_STONE,1,1,ITEM_STONE,4);
anvilRecipes.size = 18; anvilRecipes.size = 18;
anvilRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (anvilRecipes.size)); anvilRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (anvilRecipes.size));
anvilRecipes.recipes[0] = defineRecipe(TOOL_SWORD,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5); anvilRecipes.recipes[0] = defineRecipe(TOOL_SWORD,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[1] = defineRecipe(TOOL_AXE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5); anvilRecipes.recipes[1] = defineRecipe(TOOL_AXE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[2] = defineRecipe(TOOL_HOE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5); anvilRecipes.recipes[2] = defineRecipe(TOOL_HOE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[3] = defineRecipe(TOOL_PICKAXE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5); anvilRecipes.recipes[3] = defineRecipe(TOOL_PICKAXE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[4] = defineRecipe(TOOL_SHOVEL,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5); anvilRecipes.recipes[4] = defineRecipe(TOOL_SHOVEL,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
anvilRecipes.recipes[5] = defineRecipe(ITEM_ARROW_IRON,1,3,ITEM_WOOD,1,ITEM_IRONINGOT,1,ITEM_STRING,1); anvilRecipes.recipes[5] = defineRecipe(ITEM_ARROW_IRON,1,3,ITEM_WOOD,1,ITEM_IRONINGOT,1,ITEM_STRING,1);
anvilRecipes.recipes[6] = defineRecipe(TOOL_SWORD,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5); anvilRecipes.recipes[6] = defineRecipe(TOOL_SWORD,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[7] = defineRecipe(TOOL_AXE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5); anvilRecipes.recipes[7] = defineRecipe(TOOL_AXE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[8] = defineRecipe(TOOL_HOE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5); anvilRecipes.recipes[8] = defineRecipe(TOOL_HOE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[9] = defineRecipe(TOOL_PICKAXE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5); anvilRecipes.recipes[9] = defineRecipe(TOOL_PICKAXE,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[10] = defineRecipe(TOOL_SHOVEL,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5); anvilRecipes.recipes[10] = defineRecipe(TOOL_SHOVEL,3,2,ITEM_WOOD,5,ITEM_GOLDINGOT,5);
anvilRecipes.recipes[11] = defineRecipe(ITEM_ARROW_GOLD,1,3,ITEM_WOOD,1,ITEM_GOLDINGOT,1,ITEM_STRING,1); anvilRecipes.recipes[11] = defineRecipe(ITEM_ARROW_GOLD,1,3,ITEM_WOOD,1,ITEM_GOLDINGOT,1,ITEM_STRING,1);
anvilRecipes.recipes[12] = defineRecipe(TOOL_BUCKET,0,1,ITEM_IRONINGOT,10); anvilRecipes.recipes[12] = defineRecipe(TOOL_BUCKET,0,1,ITEM_IRONINGOT,10);
anvilRecipes.recipes[13] = defineRecipe(ITEM_ENCHANTER,1,3,ITEM_WOOD,10,ITEM_GOLDINGOT,10,ITEM_GEM,20); anvilRecipes.recipes[13] = defineRecipe(ITEM_ENCHANTER,1,3,ITEM_WOOD,10,ITEM_GOLDINGOT,10,ITEM_GEM,20);
@ -135,35 +135,35 @@ void initRecipes(){
anvilRecipes.recipes[16] = defineRecipe(ITEM_COIN,3,1,ITEM_IRONINGOT,1); anvilRecipes.recipes[16] = defineRecipe(ITEM_COIN,3,1,ITEM_IRONINGOT,1);
anvilRecipes.recipes[17] = defineRecipe(ITEM_POTION_MAKER,1,3,ITEM_IRONINGOT,5,ITEM_GOLDINGOT,25,ITEM_GEM,5); anvilRecipes.recipes[17] = defineRecipe(ITEM_POTION_MAKER,1,3,ITEM_IRONINGOT,5,ITEM_GOLDINGOT,25,ITEM_GEM,5);
furnaceRecipes.size = 3; furnaceRecipes.size = 3;
furnaceRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (furnaceRecipes.size)); furnaceRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (furnaceRecipes.size));
furnaceRecipes.recipes[0] = defineRecipe(ITEM_IRONINGOT,1,2,ITEM_IRONORE,4,ITEM_COAL,1); furnaceRecipes.recipes[0] = defineRecipe(ITEM_IRONINGOT,1,2,ITEM_IRONORE,4,ITEM_COAL,1);
furnaceRecipes.recipes[1] = defineRecipe(ITEM_GOLDINGOT,1,2,ITEM_GOLDORE,4,ITEM_COAL,1); furnaceRecipes.recipes[1] = defineRecipe(ITEM_GOLDINGOT,1,2,ITEM_GOLDORE,4,ITEM_COAL,1);
furnaceRecipes.recipes[2] = defineRecipe(ITEM_GLASS,1,2,ITEM_SAND,4,ITEM_COAL,1); furnaceRecipes.recipes[2] = defineRecipe(ITEM_GLASS,1,2,ITEM_SAND,4,ITEM_COAL,1);
ovenRecipes.size = 3; ovenRecipes.size = 3;
ovenRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (ovenRecipes.size)); ovenRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (ovenRecipes.size));
ovenRecipes.recipes[0] = defineRecipe(ITEM_BREAD,1,1,ITEM_WHEAT,4); ovenRecipes.recipes[0] = defineRecipe(ITEM_BREAD,1,1,ITEM_WHEAT,4);
ovenRecipes.recipes[1] = defineRecipe(ITEM_PORK_COOKED,1,2,ITEM_PORK_RAW,1,ITEM_COAL,1); ovenRecipes.recipes[1] = defineRecipe(ITEM_PORK_COOKED,1,2,ITEM_PORK_RAW,1,ITEM_COAL,1);
ovenRecipes.recipes[2] = defineRecipe(ITEM_BEEF_COOKED,1,2,ITEM_BEEF_RAW,1,ITEM_COAL,1); ovenRecipes.recipes[2] = defineRecipe(ITEM_BEEF_COOKED,1,2,ITEM_BEEF_RAW,1,ITEM_COAL,1);
loomRecipes.size = 1; loomRecipes.size = 1;
loomRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (loomRecipes.size)); loomRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (loomRecipes.size));
loomRecipes.recipes[0] = defineRecipe(ITEM_STRING,1,1,ITEM_WOOL,1); loomRecipes.recipes[0] = defineRecipe(ITEM_STRING,1,1,ITEM_WOOL,1);
enchanterRecipes.size = 8; enchanterRecipes.size = 8;
enchanterRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (enchanterRecipes.size)); enchanterRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (enchanterRecipes.size));
enchanterRecipes.recipes[0] = defineRecipe(TOOL_SWORD,4,2,ITEM_WOOD,5,ITEM_GEM,50); enchanterRecipes.recipes[0] = defineRecipe(TOOL_SWORD,4,2,ITEM_WOOD,5,ITEM_GEM,50);
enchanterRecipes.recipes[1] = defineRecipe(TOOL_AXE,4,2,ITEM_WOOD,5,ITEM_GEM,50); enchanterRecipes.recipes[1] = defineRecipe(TOOL_AXE,4,2,ITEM_WOOD,5,ITEM_GEM,50);
enchanterRecipes.recipes[2] = defineRecipe(TOOL_HOE,4,2,ITEM_WOOD,5,ITEM_GEM,50); enchanterRecipes.recipes[2] = defineRecipe(TOOL_HOE,4,2,ITEM_WOOD,5,ITEM_GEM,50);
enchanterRecipes.recipes[3] = defineRecipe(TOOL_PICKAXE,4,2,ITEM_WOOD,5,ITEM_GEM,50); enchanterRecipes.recipes[3] = defineRecipe(TOOL_PICKAXE,4,2,ITEM_WOOD,5,ITEM_GEM,50);
enchanterRecipes.recipes[4] = defineRecipe(TOOL_SHOVEL,4,2,ITEM_WOOD,5,ITEM_GEM,50); enchanterRecipes.recipes[4] = defineRecipe(TOOL_SHOVEL,4,2,ITEM_WOOD,5,ITEM_GEM,50);
enchanterRecipes.recipes[5] = defineRecipe(ITEM_ARROW_GEM,1,3,ITEM_WOOD,1,ITEM_GEM,3,ITEM_STRING,1); enchanterRecipes.recipes[5] = defineRecipe(ITEM_ARROW_GEM,1,3,ITEM_WOOD,1,ITEM_GEM,3,ITEM_STRING,1);
enchanterRecipes.recipes[6] = defineRecipe(ITEM_WALL_GEM,1,1,ITEM_GEM,10); enchanterRecipes.recipes[6] = defineRecipe(ITEM_WALL_GEM,1,1,ITEM_GEM,10);
enchanterRecipes.recipes[7] = defineRecipe(ITEM_GOLD_APPLE,1,2,ITEM_APPLE,1,ITEM_GOLDINGOT,15); enchanterRecipes.recipes[7] = defineRecipe(ITEM_GOLD_APPLE,1,2,ITEM_APPLE,1,ITEM_GOLDINGOT,15);
potionMakerRecipes.size = 4; potionMakerRecipes.size = 4;
potionMakerRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (potionMakerRecipes.size)); potionMakerRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (potionMakerRecipes.size));
potionMakerRecipes.recipes[0] = defineRecipe(ITEM_STRENGTH_POTION,1,3,ITEM_GOLD_APPLE,1,ITEM_GLASS,10,ITEM_IRONINGOT,10); potionMakerRecipes.recipes[0] = defineRecipe(ITEM_STRENGTH_POTION,1,3,ITEM_GOLD_APPLE,1,ITEM_GLASS,10,ITEM_IRONINGOT,10);
potionMakerRecipes.recipes[1] = defineRecipe(ITEM_SPEED_POTION,1,4,ITEM_GEM,2,ITEM_GLASS,10,ITEM_IRONINGOT,10, ITEM_GOLDINGOT,15); potionMakerRecipes.recipes[1] = defineRecipe(ITEM_SPEED_POTION,1,4,ITEM_GEM,2,ITEM_GLASS,10,ITEM_IRONINGOT,10, ITEM_GOLDINGOT,15);
potionMakerRecipes.recipes[2] = defineRecipe(ITEM_REGEN_POTION,1,3,ITEM_GOLD_APPLE,2,ITEM_GLASS,10,ITEM_GEM,10); potionMakerRecipes.recipes[2] = defineRecipe(ITEM_REGEN_POTION,1,3,ITEM_GOLD_APPLE,2,ITEM_GLASS,10,ITEM_GEM,10);
@ -172,10 +172,10 @@ void initRecipes(){
/* Free up allocated memory */ /* Free up allocated memory */
void freeRecipes(){ void freeRecipes(){
free(workbenchRecipes.recipes); free(workbenchRecipes.recipes);
free(ovenRecipes.recipes); free(ovenRecipes.recipes);
free(furnaceRecipes.recipes); free(furnaceRecipes.recipes);
free(anvilRecipes.recipes); free(anvilRecipes.recipes);
free(loomRecipes.recipes); free(loomRecipes.recipes);
free(enchanterRecipes.recipes); free(enchanterRecipes.recipes);
free(potionMakerRecipes.recipes); free(potionMakerRecipes.recipes);

View file

@ -3,22 +3,22 @@
#include "Item.h" #include "Item.h"
typedef struct _recipecost { typedef struct _recipecost {
int costItem; int costItem;
int costAmount; int costAmount;
} Cost; } Cost;
typedef struct _recipe { typedef struct _recipe {
bool canCraft; bool canCraft;
int itemResult; int itemResult;
int itemAmountLevel; int itemAmountLevel;
s8 numOfCosts; s8 numOfCosts;
Cost costs[6]; // Up to 6 items for costs Cost costs[6]; // Up to 6 items for costs
u8 order; // Used for stable sorting. u8 order; // Used for stable sorting.
} Recipe; } Recipe;
typedef struct _recipeManager { typedef struct _recipeManager {
int size; int size;
Recipe * recipes; Recipe * recipes;
} RecipeManager; } RecipeManager;

View file

@ -3,16 +3,16 @@
#include "Synchronizer.h" #include "Synchronizer.h"
Entity newItemEntity(Item item, int x, int y, int level){ Entity newItemEntity(Item item, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_ITEM; e.type = ENTITY_ITEM;
e.level = level; e.level = level;
e.entityItem.age = 0; e.entityItem.age = 0;
e.entityItem.item = item; e.entityItem.item = item;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.xr = 3; e.xr = 3;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
e.entityItem.xx = x; e.entityItem.xx = x;
e.entityItem.yy = y; e.entityItem.yy = y;
@ -21,261 +21,261 @@ Entity newItemEntity(Item item, int x, int y, int level){
e.entityItem.ya = gaussrand(false) * 0.1; e.entityItem.ya = gaussrand(false) * 0.1;
e.entityItem.za = ((float)rand() / RAND_MAX) * 0.45 + 1; e.entityItem.za = ((float)rand() / RAND_MAX) * 0.45 + 1;
return e; return e;
} }
void assignInventory(Entity* e){ void assignInventory(Entity* e){
if(eManager.nextInv > 300) return; if(eManager.nextInv > 300) return;
e->entityFurniture.inv = &eManager.invs[eManager.nextInv]; e->entityFurniture.inv = &eManager.invs[eManager.nextInv];
eManager.nextInv++; eManager.nextInv++;
} }
Entity newFurnitureEntity(int itemID,Inventory * invPtr, int x, int y, int level){ Entity newFurnitureEntity(int itemID,Inventory * invPtr, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_FURNITURE; e.type = ENTITY_FURNITURE;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.xr = 3; e.xr = 3;
e.yr = 3; e.yr = 3;
e.entityFurniture.itemID = itemID; e.entityFurniture.itemID = itemID;
e.canPass = false; e.canPass = false;
if(itemID == ITEM_LANTERN) e.entityFurniture.r = 8; if(itemID == ITEM_LANTERN) e.entityFurniture.r = 8;
else if(itemID == ITEM_CHEST){ else if(itemID == ITEM_CHEST){
if(invPtr == NULL)assignInventory(&e); if(invPtr == NULL)assignInventory(&e);
else e.entityFurniture.inv = invPtr; else e.entityFurniture.inv = invPtr;
} }
return e; return e;
} }
Entity newPassiveEntity(int type, int x, int y, int level){ Entity newPassiveEntity(int type, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_PASSIVE; e.type = ENTITY_PASSIVE;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.passive.mtype = type; e.passive.mtype = type;
e.passive.health = 20; e.passive.health = 20;
e.passive.dir = 0; e.passive.dir = 0;
e.passive.xa = 0; e.passive.xa = 0;
e.passive.ya = 0; e.passive.ya = 0;
e.xr = 4; e.xr = 4;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
return e; return e;
} }
Entity newZombieEntity(int lvl, int x, int y, int level){ Entity newZombieEntity(int lvl, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_ZOMBIE; e.type = ENTITY_ZOMBIE;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.hostile.lvl = lvl; e.hostile.lvl = lvl;
e.hostile.xa = 0; e.hostile.xa = 0;
e.hostile.ya = 0; e.hostile.ya = 0;
e.hostile.health = lvl * lvl * 10; e.hostile.health = lvl * lvl * 10;
e.hostile.dir = 0; e.hostile.dir = 0;
e.xr = 4; e.xr = 4;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
switch(lvl){ switch(lvl){
case 2: e.hostile.color = 0xFF8282CC; break; case 2: e.hostile.color = 0xFF8282CC; break;
case 3: e.hostile.color = 0xFFEFEFEF; break; case 3: e.hostile.color = 0xFFEFEFEF; break;
case 4: e.hostile.color = 0xFFAA6262; break; case 4: e.hostile.color = 0xFFAA6262; break;
default: e.hostile.color = 0xFF95DB95; break; default: e.hostile.color = 0xFF95DB95; break;
} }
return e; return e;
} }
Entity newSkeletonEntity(int lvl, int x, int y, int level){ Entity newSkeletonEntity(int lvl, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_SKELETON; e.type = ENTITY_SKELETON;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.hostile.lvl = lvl; e.hostile.lvl = lvl;
e.hostile.xa = 0; e.hostile.xa = 0;
e.hostile.ya = 0; e.hostile.ya = 0;
e.hostile.health = lvl * lvl * 10; e.hostile.health = lvl * lvl * 10;
e.hostile.dir = 0; e.hostile.dir = 0;
e.hostile.randAttackTime = 0; e.hostile.randAttackTime = 0;
e.xr = 4; e.xr = 4;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
switch(lvl){ switch(lvl){
case 2: e.hostile.color = 0xFFC4C4C4; break; case 2: e.hostile.color = 0xFFC4C4C4; break;
case 3: e.hostile.color = 0xFFA0A0A0; break; case 3: e.hostile.color = 0xFFA0A0A0; break;
case 4: e.hostile.color = 0xFF7A7A7A; break; case 4: e.hostile.color = 0xFF7A7A7A; break;
default: e.hostile.color = 0xFFFFFFFF; break; default: e.hostile.color = 0xFFFFFFFF; break;
} }
return e; return e;
} }
Entity newKnightEntity(int lvl, int x, int y, int level){ Entity newKnightEntity(int lvl, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_KNIGHT; e.type = ENTITY_KNIGHT;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.hostile.lvl = lvl; e.hostile.lvl = lvl;
e.hostile.xa = 0; e.hostile.xa = 0;
e.hostile.ya = 0; e.hostile.ya = 0;
e.hostile.health = lvl * lvl * 20; e.hostile.health = lvl * lvl * 20;
e.hostile.dir = 0; e.hostile.dir = 0;
e.xr = 4; e.xr = 4;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
switch(lvl){ switch(lvl){
case 2: e.hostile.color = 0xFF0000C6; break; case 2: e.hostile.color = 0xFF0000C6; break;
case 3: e.hostile.color = 0xFF00A3C6; break; case 3: e.hostile.color = 0xFF00A3C6; break;
case 4: e.hostile.color = 0xFF707070; break; case 4: e.hostile.color = 0xFF707070; break;
default: e.hostile.color = 0xFFFFFFFF; break; default: e.hostile.color = 0xFFFFFFFF; break;
} }
return e; return e;
} }
Entity newSlimeEntity(int lvl, int x, int y, int level){ Entity newSlimeEntity(int lvl, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_SLIME; e.type = ENTITY_SLIME;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.slime.lvl = lvl; e.slime.lvl = lvl;
e.slime.xa = 0; e.slime.xa = 0;
e.slime.ya = 0; e.slime.ya = 0;
e.slime.dir = 0; e.slime.dir = 0;
e.slime.health = lvl * lvl * 5; e.slime.health = lvl * lvl * 5;
e.xr = 4; e.xr = 4;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
switch(lvl){ switch(lvl){
case 2: e.slime.color = 0xFF8282CC; break; case 2: e.slime.color = 0xFF8282CC; break;
case 3: e.slime.color = 0xFFEFEFEF; break; case 3: e.slime.color = 0xFFEFEFEF; break;
case 4: e.slime.color = 0xFFAA6262; break; case 4: e.slime.color = 0xFFAA6262; break;
default: e.slime.color = 0xFF95DB95; break; default: e.slime.color = 0xFF95DB95; break;
} }
return e; return e;
} }
Entity newAirWizardEntity(int x, int y, int level){ Entity newAirWizardEntity(int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_AIRWIZARD; e.type = ENTITY_AIRWIZARD;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.wizard.dir = 0; e.wizard.dir = 0;
e.wizard.health = 2000; e.wizard.health = 2000;
e.wizard.attackDelay = 0; e.wizard.attackDelay = 0;
e.wizard.attackTime = 0; e.wizard.attackTime = 0;
e.wizard.attackType = 0; e.wizard.attackType = 0;
e.wizard.xa = 0; e.wizard.xa = 0;
e.wizard.ya = 0; e.wizard.ya = 0;
e.xr = 4; e.xr = 4;
e.yr = 3; e.yr = 3;
e.canPass = true; e.canPass = true;
return e; return e;
} }
Entity newSparkEntity(Entity* parent, float xa, float ya){ Entity newSparkEntity(Entity* parent, float xa, float ya){
Entity e; Entity e;
e.type = ENTITY_SPARK; e.type = ENTITY_SPARK;
e.level = parent->level; e.level = parent->level;
e.spark.age = 0; e.spark.age = 0;
e.spark.parent = parent; e.spark.parent = parent;
e.spark.xa = xa; e.spark.xa = xa;
e.spark.ya = ya; e.spark.ya = ya;
e.spark.xx = parent->x; e.spark.xx = parent->x;
e.spark.yy = parent->y; e.spark.yy = parent->y;
e.xr = 3; e.xr = 3;
e.yr = 3; e.yr = 3;
e.canPass = true; e.canPass = true;
return e; return e;
} }
Entity newDragonEntity(int x, int y, int level) { Entity newDragonEntity(int x, int y, int level) {
Entity e; Entity e;
e.type = ENTITY_DRAGON; e.type = ENTITY_DRAGON;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.dragon.dir = 0; e.dragon.dir = 0;
e.dragon.health = 2000; e.dragon.health = 2000;
e.dragon.attackDelay = 0; e.dragon.attackDelay = 0;
e.dragon.attackTime = 0; e.dragon.attackTime = 0;
e.dragon.attackType = 0; e.dragon.attackType = 0;
e.dragon.animTimer = 0; e.dragon.animTimer = 0;
e.dragon.xa = 0; e.dragon.xa = 0;
e.dragon.ya = 0; e.dragon.ya = 0;
e.xr = 8; e.xr = 8;
e.yr = 8; e.yr = 8;
e.canPass = false; e.canPass = false;
return e; return e;
} }
Entity newDragonFireEntity(Entity* parent, u8 type, int x, int y, float xa, float ya) { Entity newDragonFireEntity(Entity* parent, u8 type, int x, int y, float xa, float ya) {
Entity e; Entity e;
e.type = ENTITY_DRAGONPROJECTILE; e.type = ENTITY_DRAGONPROJECTILE;
e.level = parent->level; e.level = parent->level;
e.dragonFire.age = 0; e.dragonFire.age = 0;
e.dragonFire.type = type; e.dragonFire.type = type;
e.dragonFire.parent = parent; e.dragonFire.parent = parent;
e.dragonFire.xa = xa; e.dragonFire.xa = xa;
e.dragonFire.ya = ya; e.dragonFire.ya = ya;
e.dragonFire.xx = x; e.dragonFire.xx = x;
e.dragonFire.yy = y; e.dragonFire.yy = y;
e.x = (int) x; e.x = (int) x;
e.y = (int) y; e.y = (int) y;
e.xr = 3; e.xr = 3;
e.yr = 3; e.yr = 3;
e.canPass = true; e.canPass = true;
return e; return e;
} }
Entity newMagicPillarEntity(int x, int y, int level){ Entity newMagicPillarEntity(int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_MAGIC_PILLAR; e.type = ENTITY_MAGIC_PILLAR;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.xr = 3; e.xr = 3;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
return e; return e;
} }
Entity newTextParticleEntity(char * str, u32 color, int x, int y, int level){ Entity newTextParticleEntity(char * str, u32 color, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_TEXTPARTICLE; e.type = ENTITY_TEXTPARTICLE;
e.level = level; e.level = level;
e.textParticle.color = color; e.textParticle.color = color;
e.textParticle.age = 0; e.textParticle.age = 0;
e.textParticle.text = (char*)calloc(strlen(str),sizeof(char)); e.textParticle.text = (char*)calloc(strlen(str),sizeof(char));
strncpy(e.textParticle.text,str,strlen(str)); strncpy(e.textParticle.text,str,strlen(str));
e.x = x; e.x = x;
e.y = y; e.y = y;
e.canPass = true; e.canPass = true;
e.textParticle.xx = x; e.textParticle.xx = x;
e.textParticle.yy = y; e.textParticle.yy = y;
e.textParticle.zz = 2; e.textParticle.zz = 2;
@ -283,81 +283,81 @@ Entity newTextParticleEntity(char * str, u32 color, int x, int y, int level){
e.textParticle.ya = gaussrand(false) * 0.2; e.textParticle.ya = gaussrand(false) * 0.2;
e.textParticle.za = ((float)rand() / RAND_MAX) * 0.7 + 2; e.textParticle.za = ((float)rand() / RAND_MAX) * 0.7 + 2;
return e; return e;
} }
Entity newSmashParticleEntity(int x, int y, int level){ Entity newSmashParticleEntity(int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_SMASHPARTICLE; e.type = ENTITY_SMASHPARTICLE;
e.level = level; e.level = level;
e.smashParticle.age = 0; e.smashParticle.age = 0;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.canPass = true; e.canPass = true;
playSoundPositioned(snd_monsterHurt, e.level, e.x, e.y); //TODO: This is a wierd location for the effect playSoundPositioned(snd_monsterHurt, e.level, e.x, e.y); //TODO: This is a wierd location for the effect
return e; return e;
} }
Entity newArrowEntity(Entity* parent, int itemID, s8 xa, s8 ya, int level){ Entity newArrowEntity(Entity* parent, int itemID, s8 xa, s8 ya, int level){
Entity e; Entity e;
e.type = ENTITY_ARROW; e.type = ENTITY_ARROW;
e.level = level; e.level = level;
e.arrow.age = 0; e.arrow.age = 0;
e.arrow.parent = parent; e.arrow.parent = parent;
e.arrow.itemID = itemID; e.arrow.itemID = itemID;
e.arrow.xa = xa; e.arrow.xa = xa;
e.arrow.ya = ya; e.arrow.ya = ya;
e.x = parent->x; e.x = parent->x;
e.y = parent->y; e.y = parent->y;
e.xr = 2; e.xr = 2;
e.yr = 2; e.yr = 2;
e.canPass = false; e.canPass = false;
e.canSwim = true; e.canSwim = true;
return e; return e;
} }
Entity newGlowwormEntity(int x, int y, int level){ Entity newGlowwormEntity(int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_GLOWWORM; e.type = ENTITY_GLOWWORM;
e.level = level; e.level = level;
e.glowworm.xa = 0; e.glowworm.xa = 0;
e.glowworm.ya = 0; e.glowworm.ya = 0;
e.glowworm.randWalkTime = 0; e.glowworm.randWalkTime = 0;
e.glowworm.waitTime = 0; e.glowworm.waitTime = 0;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.canPass = true; e.canPass = true;
return e; return e;
} }
Entity newNPCEntity(int type, int x, int y, int level){ Entity newNPCEntity(int type, int x, int y, int level){
Entity e; Entity e;
e.type = ENTITY_NPC; e.type = ENTITY_NPC;
e.level = level; e.level = level;
e.x = x; e.x = x;
e.y = y; e.y = y;
e.hurtTime = 0; e.hurtTime = 0;
e.xKnockback = 0; e.xKnockback = 0;
e.yKnockback = 0; e.yKnockback = 0;
e.npc.type = type; e.npc.type = type;
e.xr = 4; e.xr = 4;
e.yr = 3; e.yr = 3;
e.canPass = false; e.canPass = false;
return e; return e;
} }
void addEntityToList(Entity e, EntityManager* em){ void addEntityToList(Entity e, EntityManager* em){
e.slotNum = em->lastSlot[e.level]; e.slotNum = em->lastSlot[e.level];
em->entities[e.level][em->lastSlot[e.level]] = e; em->entities[e.level][em->lastSlot[e.level]] = e;
++em->lastSlot[e.level]; ++em->lastSlot[e.level];
} }
void removeEntityFromList(Entity * e,int level,EntityManager* em){ void removeEntityFromList(Entity * e,int level,EntityManager* em){
int i; int i;
if(em->entities[level][e->slotNum].type == ENTITY_TEXTPARTICLE) free(em->entities[level][e->slotNum].textParticle.text); if(em->entities[level][e->slotNum].type == ENTITY_TEXTPARTICLE) free(em->entities[level][e->slotNum].textParticle.text);
for(i = e->slotNum; i < em->lastSlot[level];++i){ for(i = e->slotNum; i < em->lastSlot[level];++i){
em->entities[level][i] = em->entities[level][i + 1]; // Move the items down. em->entities[level][i] = em->entities[level][i + 1]; // Move the items down.
em->entities[level][i].slotNum = i; em->entities[level][i].slotNum = i;
} }
em->lastSlot[level]--; em->lastSlot[level]--;
em->entities[level][em->lastSlot[level]] = nullEntity; // Make the last slot null. em->entities[level][em->lastSlot[level]] = nullEntity; // Make the last slot null.
} }

View file

@ -30,89 +30,89 @@ typedef struct Entity Entity;
typedef struct _plrd PlayerData; //in order to not include Player.h and cause all sorts of problems typedef struct _plrd PlayerData; //in order to not include Player.h and cause all sorts of problems
typedef struct { typedef struct {
s8 ax; s8 ax;
s8 ay; s8 ay;
u8 dir; u8 dir;
s8 health; s8 health;
s8 stamina; s8 stamina;
s8 staminaRecharge; s8 staminaRecharge;
s8 staminaRechargeDelay; s8 staminaRechargeDelay;
s8 attackTimer; s8 attackTimer;
u8 spawnTrigger; u8 spawnTrigger;
bool isDead; bool isDead;
bool hasWon; bool hasWon;
bool hasWonSaved; bool hasWonSaved;
s8 endTimer; s8 endTimer;
s16 walkDist; s16 walkDist;
bool isCarrying; bool isCarrying;
bool isSwimming; bool isSwimming;
int swimTimer; int swimTimer;
int regenTimer; int regenTimer;
int strengthTimer; int strengthTimer;
int swimBreathTimer; int swimBreathTimer;
int speedTimer; int speedTimer;
int score; int score;
PlayerData *data; PlayerData *data;
} Player; } Player;
typedef struct { typedef struct {
float xa; float xa;
float ya; float ya;
float za; float za;
float xx; float xx;
float yy; float yy;
float zz; float zz;
s16 age; s16 age;
Item item; Item item;
} EntityItem; } EntityItem;
typedef struct { typedef struct {
s16 itemID; s16 itemID;
bool active; bool active;
s8 r; // light radius for lantern. s8 r; // light radius for lantern.
Inventory* inv; // Points to chest inventory. Inventory* inv; // Points to chest inventory.
} EntityFurniture; } EntityFurniture;
typedef struct { typedef struct {
u8 mtype; u8 mtype;
s8 xa; s8 xa;
s8 ya; s8 ya;
s16 health; s16 health;
s8 dir; s8 dir;
s8 randWalkTime; s8 randWalkTime;
s8 walkDist; s8 walkDist;
} PassiveMob; } PassiveMob;
typedef struct { typedef struct {
s8 xa; s8 xa;
s8 ya; s8 ya;
s16 health; s16 health;
s8 dir; s8 dir;
s8 lvl; s8 lvl;
s8 randWalkTime; s8 randWalkTime;
s8 walkDist; s8 walkDist;
s8 randAttackTime; s8 randAttackTime;
u32 color; u32 color;
} HostileMob; } HostileMob;
typedef struct { typedef struct {
s8 xa; s8 xa;
s8 ya; s8 ya;
s16 health; s16 health;
s8 lvl; s8 lvl;
s8 dir; s8 dir;
s8 jumpTime; s8 jumpTime;
u32 color; u32 color;
} Slime; } Slime;
typedef struct { typedef struct {
s8 xa; s8 xa;
s8 ya; s8 ya;
s16 health; s16 health;
s8 randWalkTime; s8 randWalkTime;
s8 walkDist; s8 walkDist;
s8 dir; s8 dir;
int attackDelay; int attackDelay;
int attackTime; int attackTime;
int attackType; int attackType;
@ -120,12 +120,12 @@ typedef struct {
} AirWizard; } AirWizard;
typedef struct { typedef struct {
Entity* parent; Entity* parent;
s16 age; s16 age;
float xa; float xa;
float ya; float ya;
float xx; float xx;
float yy; float yy;
} Spark; } Spark;
typedef struct { typedef struct {
@ -137,12 +137,12 @@ typedef struct {
} Arrow; } Arrow;
typedef struct { typedef struct {
s8 xa; s8 xa;
s8 ya; s8 ya;
s16 health; s16 health;
s8 randWalkTime; s8 randWalkTime;
s8 walkDist; s8 walkDist;
s8 dir; s8 dir;
int attackDelay; int attackDelay;
int attackTime; int attackTime;
int attackType; int attackType;
@ -150,19 +150,19 @@ typedef struct {
} Dragon; } Dragon;
typedef struct { typedef struct {
Entity* parent; Entity* parent;
u8 type; u8 type;
s16 age; s16 age;
float xa; float xa;
float ya; float ya;
float xx; float xx;
float yy; float yy;
} DragonFire; } DragonFire;
typedef struct { typedef struct {
s8 xa; s8 xa;
s8 ya; s8 ya;
s8 randWalkTime; s8 randWalkTime;
s8 waitTime; s8 waitTime;
} Glowworm; } Glowworm;
@ -171,56 +171,56 @@ typedef struct {
} NPC; } NPC;
typedef struct { typedef struct {
float xa; float xa;
float ya; float ya;
float za; float za;
float xx; float xx;
float yy; float yy;
float zz; float zz;
s16 age; s16 age;
char* text; char* text;
int color; int color;
} TextParticleEntity; } TextParticleEntity;
typedef struct { typedef struct {
s16 age; s16 age;
} SmashParticleEntity; } SmashParticleEntity;
struct Entity { struct Entity {
s16 x; s16 x;
s16 y; s16 y;
s8 xKnockback,yKnockback; s8 xKnockback,yKnockback;
u8 xr,yr; u8 xr,yr;
u8 type; u8 type;
u8 level; u8 level;
s8 hurtTime; s8 hurtTime;
s16 slotNum; // Read-only. Do not mess with this. s16 slotNum; // Read-only. Do not mess with this.
bool canPass; bool canPass;
bool canSwim; bool canSwim;
union { union {
Player p; Player p;
EntityItem entityItem; EntityItem entityItem;
EntityFurniture entityFurniture; EntityFurniture entityFurniture;
PassiveMob passive; PassiveMob passive;
HostileMob hostile; HostileMob hostile;
Slime slime; Slime slime;
AirWizard wizard; AirWizard wizard;
Spark spark; Spark spark;
Arrow arrow; Arrow arrow;
Glowworm glowworm; Glowworm glowworm;
Dragon dragon; Dragon dragon;
DragonFire dragonFire; DragonFire dragonFire;
NPC npc; NPC npc;
TextParticleEntity textParticle; TextParticleEntity textParticle;
SmashParticleEntity smashParticle; SmashParticleEntity smashParticle;
}; };
}; };
typedef struct { typedef struct {
Entity entities[6][1000]; Entity entities[6][1000];
s16 lastSlot[6]; s16 lastSlot[6];
Inventory invs[300]; Inventory invs[300];
s16 nextInv; s16 nextInv;
} EntityManager; } EntityManager;
EntityManager eManager; EntityManager eManager;
@ -246,6 +246,3 @@ Entity newGlowwormEntity(int x, int y, int level);
Entity newNPCEntity(int type, int x, int y, int level); Entity newNPCEntity(int type, int x, int y, int level);
void addEntityToList(Entity e, EntityManager* em); void addEntityToList(Entity e, EntityManager* em);
void removeEntityFromList(Entity * e,int level,EntityManager* em); void removeEntityFromList(Entity * e,int level,EntityManager* em);

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
#include "MapGen.h" #include "MapGen.h"
#include "Quests.h" #include "Quests.h"
#include "icons2_png.h" #include "icons_png.h"
#include "player_png.h" #include "player_png.h"
#include "Font_png.h" #include "Font_png.h"
#include "bottombg_png.h" #include "bottombg_png.h"
@ -142,15 +142,15 @@ bool quitGame;
s8 currentSelection; s8 currentSelection;
typedef struct _worldData { typedef struct _worldData {
u8 map[6][128*128]; u8 map[6][128*128];
u8 data[6][128*128]; u8 data[6][128*128];
u16 daytime; u16 daytime;
int day; int day;
u8 season; u8 season;
bool rain; bool rain;
u8 compassData[6][3]; u8 compassData[6][3];
} WorldData; } WorldData;
WorldData worldData; WorldData worldData;

View file

@ -17,53 +17,53 @@ bool stallAreYouSure;
//generates stairs up and creates compass data //generates stairs up and creates compass data
void generatePass2() { void generatePass2() {
int level, x, y; int level, x, y;
for (level = 0; level < 5; ++level) { for (level = 0; level < 5; ++level) {
for (x = 0; x < 128; ++x) { for (x = 0; x < 128; ++x) {
for (y = 0; y < 128; ++y) { for (y = 0; y < 128; ++y) {
//generate stairs up matching stairs down //generate stairs up matching stairs down
switch (worldData.map[level][x + y * 128]) { switch (worldData.map[level][x + y * 128]) {
case TILE_STAIRS_DOWN: case TILE_STAIRS_DOWN:
if(level < 4) { if(level < 4) {
worldData.map[level + 1][x + y * 128] = TILE_STAIRS_UP; worldData.map[level + 1][x + y * 128] = TILE_STAIRS_UP;
if (level == 0) { if (level == 0) {
worldData.map[level + 1][(x + 1) + y * 128] = TILE_HARDROCK; worldData.map[level + 1][(x + 1) + y * 128] = TILE_HARDROCK;
worldData.map[level + 1][x + (y + 1) * 128] = TILE_HARDROCK; worldData.map[level + 1][x + (y + 1) * 128] = TILE_HARDROCK;
worldData.map[level + 1][(x - 1) + y * 128] = TILE_HARDROCK; worldData.map[level + 1][(x - 1) + y * 128] = TILE_HARDROCK;
worldData.map[level + 1][x + (y - 1) * 128] = TILE_HARDROCK; worldData.map[level + 1][x + (y - 1) * 128] = TILE_HARDROCK;
worldData.map[level + 1][(x + 1) + (y + 1) * 128] = TILE_HARDROCK; worldData.map[level + 1][(x + 1) + (y + 1) * 128] = TILE_HARDROCK;
worldData.map[level + 1][(x - 1) + (y - 1) * 128] = TILE_HARDROCK; worldData.map[level + 1][(x - 1) + (y - 1) * 128] = TILE_HARDROCK;
worldData.map[level + 1][(x - 1) + (y + 1) * 128] = TILE_HARDROCK; worldData.map[level + 1][(x - 1) + (y + 1) * 128] = TILE_HARDROCK;
worldData.map[level + 1][(x + 1) + (y - 1) * 128] = TILE_HARDROCK; worldData.map[level + 1][(x + 1) + (y - 1) * 128] = TILE_HARDROCK;
} else { } else {
worldData.map[level + 1][(x + 1) + y * 128] = TILE_DIRT; worldData.map[level + 1][(x + 1) + y * 128] = TILE_DIRT;
worldData.map[level + 1][x + (y + 1) * 128] = TILE_DIRT; worldData.map[level + 1][x + (y + 1) * 128] = TILE_DIRT;
worldData.map[level + 1][(x - 1) + y * 128] = TILE_DIRT; worldData.map[level + 1][(x - 1) + y * 128] = TILE_DIRT;
worldData.map[level + 1][x + (y - 1) * 128] = TILE_DIRT; worldData.map[level + 1][x + (y - 1) * 128] = TILE_DIRT;
worldData.map[level + 1][(x + 1) + (y + 1) * 128] = TILE_DIRT; worldData.map[level + 1][(x + 1) + (y + 1) * 128] = TILE_DIRT;
worldData.map[level + 1][(x - 1) + (y - 1) * 128] = TILE_DIRT; worldData.map[level + 1][(x - 1) + (y - 1) * 128] = TILE_DIRT;
worldData.map[level + 1][(x - 1) + (y + 1) * 128] = TILE_DIRT; worldData.map[level + 1][(x - 1) + (y + 1) * 128] = TILE_DIRT;
worldData.map[level + 1][(x + 1) + (y - 1) * 128] = TILE_DIRT; worldData.map[level + 1][(x + 1) + (y - 1) * 128] = TILE_DIRT;
} }
} }
} }
//calculate compass data //calculate compass data
//choose one stair down and store for magic compass //choose one stair down and store for magic compass
switch (worldData.map[level][x + y * 128]) { switch (worldData.map[level][x + y * 128]) {
case TILE_STAIRS_DOWN: case TILE_STAIRS_DOWN:
case TILE_DUNGEON_ENTRANCE: case TILE_DUNGEON_ENTRANCE:
worldData.compassData[level][2] = worldData.compassData[level][2] + 1; worldData.compassData[level][2] = worldData.compassData[level][2] + 1;
if((worldData.compassData[level][2]==1) || (rand()%(worldData.compassData[level][2])==0)) { if((worldData.compassData[level][2]==1) || (rand()%(worldData.compassData[level][2])==0)) {
worldData.compassData[level][0] = x; worldData.compassData[level][0] = x;
worldData.compassData[level][1] = y; worldData.compassData[level][1] = y;
} }
} }
} }
} }
} }
} }
void initNewMap() { void initNewMap() {
@ -72,7 +72,7 @@ void initNewMap() {
createAndValidateUndergroundMap(128, 128, 1, 2, worldData.map[2], worldData.data[2]); createAndValidateUndergroundMap(128, 128, 1, 2, worldData.map[2], worldData.data[2]);
createAndValidateUndergroundMap(128, 128, 2, 3, worldData.map[3], worldData.data[3]); createAndValidateUndergroundMap(128, 128, 2, 3, worldData.map[3], worldData.data[3]);
createAndValidateUndergroundMap(128, 128, 3, 4, worldData.map[4], worldData.data[4]); createAndValidateUndergroundMap(128, 128, 3, 4, worldData.map[4], worldData.data[4]);
generatePass2(); generatePass2();
} }
void initMiniMap(PlayerData *pd) { void initMiniMap(PlayerData *pd) {
@ -83,297 +83,297 @@ void initMiniMap(PlayerData *pd) {
} }
void startGame(bool load, char *filename) { void startGame(bool load, char *filename) {
// Reset entity manager. // Reset entity manager.
memset(&eManager, 0, sizeof(eManager)); memset(&eManager, 0, sizeof(eManager));
// Reset players // Reset players
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
initPlayer(players+i); initPlayer(players+i);
} }
if (playerCount > 1) { if (playerCount > 1) {
shouldRenderDebug = false; shouldRenderDebug = false;
} }
if (!load) { if (!load) {
initNewMap(); initNewMap();
airWizardHealthDisplay = 2000; airWizardHealthDisplay = 2000;
int i; int i;
for (i = 0; i < 5; ++i) { for (i = 0; i < 5; ++i) {
trySpawn(500, i); trySpawn(500, i);
} }
addEntityToList(newAirWizardEntity(630, 820, 0), &eManager); addEntityToList(newAirWizardEntity(630, 820, 0), &eManager);
worldData.daytime = 6000; worldData.daytime = 6000;
worldData.day = 0; worldData.day = 0;
worldData.season = 0; worldData.season = 0;
worldData.rain = false; worldData.rain = false;
} else { } else {
if(!loadWorld(filename, &eManager, &worldData, players, playerCount)) { if(!loadWorld(filename, &eManager, &worldData, players, playerCount)) {
//TODO: What do? //TODO: What do?
networkDisconnect(); networkDisconnect();
sf2d_set_clear_color(0xFF); sf2d_set_clear_color(0xFF);
currentSelection = 0; currentSelection = 0;
currentMenu = MENU_TITLE; currentMenu = MENU_TITLE;
} }
} }
// Spawn players // Spawn players
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
if(!players[i].isSpawned) { if(!players[i].isSpawned) {
playerSpawn(players+i); playerSpawn(players+i);
} }
} }
// Init player maps // Init player maps
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
initMiniMap(players+i); initMiniMap(players+i);
} }
stallCounter = 0; stallCounter = 0;
} }
void syncedTick() { void syncedTick() {
int i; int i;
setListenerPosition(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y); setListenerPosition(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y);
//win/death menus //win/death menus
for(i=0; i<playerCount; i++) { for(i=0; i<playerCount; i++) {
if (players[i].entity.p.isDead) { if (players[i].entity.p.isDead) {
if (players[i].entity.p.endTimer < 1) { if (players[i].entity.p.endTimer < 1) {
players[i].ingameMenu = MENU_LOSE; players[i].ingameMenu = MENU_LOSE;
} }
--players[i].entity.p.endTimer; --players[i].entity.p.endTimer;
} else if (players[i].entity.p.hasWon) { } else if (players[i].entity.p.hasWon) {
if (players[i].entity.p.endTimer < 1) { if (players[i].entity.p.endTimer < 1) {
players[i].ingameMenu = MENU_WIN; players[i].ingameMenu = MENU_WIN;
} }
--players[i].entity.p.endTimer; --players[i].entity.p.endTimer;
} }
} }
//update worldData (daytime,season and weather) //update worldData (daytime,season and weather)
++worldData.daytime; ++worldData.daytime;
if(worldData.daytime>=24000) { if(worldData.daytime>=24000) {
worldData.daytime -= 24000; worldData.daytime -= 24000;
++worldData.day; ++worldData.day;
//TODO: maybe make season length not as hardcoded + make the transition better (fade to black and back maybe?) //TODO: maybe make season length not as hardcoded + make the transition better (fade to black and back maybe?)
if(worldData.day%7==0) { if(worldData.day%7==0) {
++worldData.season; ++worldData.season;
if(worldData.season==4) worldData.season = 0; if(worldData.season==4) worldData.season = 0;
} }
worldData.rain = false; worldData.rain = false;
if(worldData.season!=3 && rand()%5==0) worldData.rain = true; if(worldData.season!=3 && rand()%5==0) worldData.rain = true;
} }
//update music //update music
updateMusic(getLocalPlayer()->entity.level, worldData.daytime); updateMusic(getLocalPlayer()->entity.level, worldData.daytime);
//for every active level //for every active level
s8 level; s8 level;
for(level = 0; level < 6; level++) { for(level = 0; level < 6; level++) {
bool hasPlayer = false; bool hasPlayer = false;
for(i=0; i<playerCount; i++) { for(i=0; i<playerCount; i++) {
if(players[i].entity.level==level) { if(players[i].entity.level==level) {
hasPlayer = true; hasPlayer = true;
} }
} }
if(!hasPlayer) continue; if(!hasPlayer) continue;
//tick tiles //tick tiles
for (i = 0; i < 324; ++i) { for (i = 0; i < 324; ++i) {
int xx = rand() & 127; int xx = rand() & 127;
int yy = rand() & 127; int yy = rand() & 127;
tickTile(level, xx, yy); tickTile(level, xx, yy);
} }
} }
for(i=0; i<playerCount; i++) { for(i=0; i<playerCount; i++) {
ingameMenuTickTouch(players+i); ingameMenuTickTouch(players+i);
bool inmenu = false; bool inmenu = false;
if(players[i].ingameMenu != MENU_NONE) { if(players[i].ingameMenu != MENU_NONE) {
ingameMenuTick(players+i, players[i].ingameMenu); ingameMenuTick(players+i, players[i].ingameMenu);
inmenu = true; inmenu = true;
} }
tickPlayer(players+i, inmenu); tickPlayer(players+i, inmenu);
} }
//for every active level //for every active level
for(level = 0; level < 6; level++) { for(level = 0; level < 6; level++) {
if(level==5 && !dungeonActive()) continue; if(level==5 && !dungeonActive()) continue;
bool hasPlayer = false; bool hasPlayer = false;
for(i=0; i<playerCount; i++) { for(i=0; i<playerCount; i++) {
if(players[i].entity.level==level) { if(players[i].entity.level==level) {
hasPlayer = true; hasPlayer = true;
} }
} }
if(!hasPlayer) continue; if(!hasPlayer) continue;
//spawn entities //spawn entities
if(eManager.lastSlot[level]<80 && level != 5) { if(eManager.lastSlot[level]<80 && level != 5) {
trySpawn(1, level); trySpawn(1, level);
} }
//update entities //update entities
for (i = 0; i < eManager.lastSlot[level]; ++i) { for (i = 0; i < eManager.lastSlot[level]; ++i) {
Entity * e = &eManager.entities[level][i]; Entity * e = &eManager.entities[level][i];
PlayerData * p = getNearestPlayer(level, e->x, e->y); PlayerData * p = getNearestPlayer(level, e->x, e->y);
//should never happen, but just for safety to prevent hard crashes //should never happen, but just for safety to prevent hard crashes
if(p==NULL) continue; if(p==NULL) continue;
if ((e->type != ENTITY_ZOMBIE && e->type != ENTITY_SKELETON && e->type != ENTITY_KNIGHT && e->type != ENTITY_SLIME && e->type != ENTITY_PASSIVE && e->type != ENTITY_GLOWWORM) if ((e->type != ENTITY_ZOMBIE && e->type != ENTITY_SKELETON && e->type != ENTITY_KNIGHT && e->type != ENTITY_SLIME && e->type != ENTITY_PASSIVE && e->type != ENTITY_GLOWWORM)
|| (e->type == ENTITY_GLOWWORM && (worldData.daytime>6000 || worldData.daytime<18000)) || (e->type == ENTITY_GLOWWORM && (worldData.daytime>6000 || worldData.daytime<18000))
|| (e->x > p->entity.x - 160 && e->y > p->entity.y - 125 && e->x < p->entity.x + 160 && e->y < p->entity.y + 125)) { || (e->x > p->entity.x - 160 && e->y > p->entity.y - 125 && e->x < p->entity.x + 160 && e->y < p->entity.y + 125)) {
tickEntity(e); tickEntity(e);
} }
} }
} }
stallCounter = 0; stallCounter = 0;
} }
void tickGame() { void tickGame() {
synchronizerTick(&syncedTick); synchronizerTick(&syncedTick);
if(synchronizerIsRunning()) { if(synchronizerIsRunning()) {
stallCounter++; stallCounter++;
//game stalled -> most likely a player disconnected -> present option to exit game //game stalled -> most likely a player disconnected -> present option to exit game
if(stallCounter>=STALL_TIME) { if(stallCounter>=STALL_TIME) {
if(stallCounter==STALL_TIME) stallAreYouSure = false; if(stallCounter==STALL_TIME) stallAreYouSure = false;
//scan local inputs, because synchronizer only updates them when not stalled //scan local inputs, because synchronizer only updates them when not stalled
hidScanInput(); hidScanInput();
tickKeys(&localInputs, hidKeysHeld(), hidKeysDown()); tickKeys(&localInputs, hidKeysHeld(), hidKeysDown());
if (localInputs.k_accept.clicked) { if (localInputs.k_accept.clicked) {
if(stallAreYouSure) { if(stallAreYouSure) {
//create backup save //create backup save
if(playerLocalID==0) { if(playerLocalID==0) {
char backupSaveFileName[256+32]; char backupSaveFileName[256+32];
backupSaveFileName[0] = '\0'; backupSaveFileName[0] = '\0';
strncat(backupSaveFileName, currentFileName, strlen(currentFileName)-4); strncat(backupSaveFileName, currentFileName, strlen(currentFileName)-4);
strcat(backupSaveFileName, ".exit.msv"); strcat(backupSaveFileName, ".exit.msv");
saveWorld(backupSaveFileName, &eManager, &worldData, players, playerCount); saveWorld(backupSaveFileName, &eManager, &worldData, players, playerCount);
} }
exitGame(); exitGame();
} else { } else {
stallAreYouSure = true; stallAreYouSure = true;
} }
} }
if (localInputs.k_decline.clicked) { if (localInputs.k_decline.clicked) {
stallAreYouSure = false; stallAreYouSure = false;
} }
} }
} }
} }
//for rendering -> move to a better place //for rendering -> move to a better place
int xscr = 0, yscr = 0; int xscr = 0, yscr = 0;
void renderGame() { void renderGame() {
//Important: all code called from this function should never affect game state! //Important: all code called from this function should never affect game state!
sf2d_start_frame(GFX_TOP, GFX_LEFT); sf2d_start_frame(GFX_TOP, GFX_LEFT);
int xscr = getLocalPlayer()->entity.x - 100; int xscr = getLocalPlayer()->entity.x - 100;
int yscr = getLocalPlayer()->entity.y - 56; int yscr = getLocalPlayer()->entity.y - 56;
if (xscr < 16) if (xscr < 16)
xscr = 16; xscr = 16;
else if (xscr > 1832) else if (xscr > 1832)
xscr = 1832; xscr = 1832;
if (yscr < 16) if (yscr < 16)
yscr = 16; yscr = 16;
else if (yscr > 1912) else if (yscr > 1912)
yscr = 1912; yscr = 1912;
offsetX = xscr; offsetX = xscr;
offsetY = yscr; offsetY = yscr;
sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //RGBA8(12, 12, 12, 255)); //You might think "real" black would be better, but it actually looks better that way sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //RGBA8(12, 12, 12, 255)); //You might think "real" black would be better, but it actually looks better that way
renderLightsToStencil(getLocalPlayer(), false, false, true); renderLightsToStencil(getLocalPlayer(), false, false, true);
renderBackground(getLocalPlayer()->entity.level, xscr, yscr); renderBackground(getLocalPlayer()->entity.level, xscr, yscr);
renderEntities(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y, &eManager); renderEntities(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y, &eManager);
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
renderPlayer(players+i); renderPlayer(players+i);
} }
renderWeather(getLocalPlayer()->entity.level, xscr, yscr); renderWeather(getLocalPlayer()->entity.level, xscr, yscr);
resetStencilStuff(); resetStencilStuff();
renderDayNight(getLocalPlayer()); renderDayNight(getLocalPlayer());
offsetX = 0; offsetX = 0;
offsetY = 0; offsetY = 0;
if(shouldRenderDebug){ if(shouldRenderDebug){
sprintf(fpsstr, " FPS: %.0f, X:%d, Y:%d, E:%d", sf2d_get_fps(), getLocalPlayer()->entity.x, getLocalPlayer()->entity.y, eManager.lastSlot[getLocalPlayer()->entity.level]); sprintf(fpsstr, " FPS: %.0f, X:%d, Y:%d, E:%d", sf2d_get_fps(), getLocalPlayer()->entity.x, getLocalPlayer()->entity.y, eManager.lastSlot[getLocalPlayer()->entity.level]);
drawText(fpsstr, 2, 225); drawText(fpsstr, 2, 225);
} }
if(getLocalPlayer()->ingameMenu != MENU_NONE) { if(getLocalPlayer()->ingameMenu != MENU_NONE) {
ingameMenuRender(getLocalPlayer(), getLocalPlayer()->ingameMenu); ingameMenuRender(getLocalPlayer(), getLocalPlayer()->ingameMenu);
} }
//game stalled -> most likely a player disconnected -> present option to exit game //game stalled -> most likely a player disconnected -> present option to exit game
if(stallCounter>STALL_TIME) { if(stallCounter>STALL_TIME) {
renderFrame(1,1,24,14,0xFF1010AF); renderFrame(1,1,24,14,0xFF1010AF);
drawText("Waiting for a long time", (400 - (23 * 12))/2, 32); drawText("Waiting for a long time", (400 - (23 * 12))/2, 32);
char text[50]; char text[50];
sprintf(text, "Last response %is ago", stallCounter/60); sprintf(text, "Last response %is ago", stallCounter/60);
drawText(text, (400 - (strlen(text) * 12))/2, 64); drawText(text, (400 - (strlen(text) * 12))/2, 64);
if(playerLocalID==0) { if(playerLocalID==0) {
drawText("Press to leave the game", (400 - (25 * 12))/2, 160); drawText("Press to leave the game", (400 - (25 * 12))/2, 160);
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 157, 1); renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 157, 1);
drawText("A backup save will be created", (400 - (29 * 12))/2, 192); drawText("A backup save will be created", (400 - (29 * 12))/2, 192);
} else { } else {
drawText("Press to leave the game", (400 - (25 * 12))/2, 192); drawText("Press to leave the game", (400 - (25 * 12))/2, 192);
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 189, 1); renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 189, 1);
} }
if(stallAreYouSure){ if(stallAreYouSure){
renderFrame(6,5,19,10,0xFF10108F); renderFrame(6,5,19,10,0xFF10108F);
drawText("Are you sure?",122,96); drawText("Are you sure?",122,96);
drawText(" Yes", 164, 117); drawText(" Yes", 164, 117);
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1); renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1);
drawText(" No", 170, 133); drawText(" No", 170, 133);
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1); renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1);
} }
} }
sf2d_end_frame(); sf2d_end_frame();
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
if(!players[playerLocalID].mapShouldRender){ if(!players[playerLocalID].mapShouldRender){
sf2d_draw_texture(bottombg, 0, 0); sf2d_draw_texture(bottombg, 0, 0);
renderGui(getLocalPlayer()); renderGui(getLocalPlayer());
} else { } else {
renderZoomedMap(getLocalPlayer()); renderZoomedMap(getLocalPlayer());
} }
sf2d_end_frame(); sf2d_end_frame();
} }
void exitGame() { void exitGame() {
networkDisconnect(); networkDisconnect();
synchronizerReset(); synchronizerReset();
sf2d_set_clear_color(0xFF); sf2d_set_clear_color(0xFF);
currentSelection = 0; currentSelection = 0;
currentMenu = MENU_TITLE; currentMenu = MENU_TITLE;
playMusic(&music_menu); playMusic(&music_menu);
} }

View file

@ -10,102 +10,102 @@
char pOptions[][24] = {"Return to game", "Save Progress", "Exit to title"}; char pOptions[][24] = {"Return to game", "Save Progress", "Exit to title"};
void ingameMenuTick(PlayerData *pd, int menu) { void ingameMenuTick(PlayerData *pd, int menu) {
switch(menu) { switch(menu) {
case MENU_PAUSED: case MENU_PAUSED:
if(!pd->ingameMenuAreYouSure && !pd->ingameMenuAreYouSureSave){ if(!pd->ingameMenuAreYouSure && !pd->ingameMenuAreYouSureSave){
if (pd->ingameMenuTimer > 0) --pd->ingameMenuTimer; if (pd->ingameMenuTimer > 0) --pd->ingameMenuTimer;
if (pd->inputs.k_pause.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE; if (pd->inputs.k_pause.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
if (pd->inputs.k_up.clicked) { --pd->ingameMenuSelection; if(pd->ingameMenuSelection < 0) pd->ingameMenuSelection=2; } if (pd->inputs.k_up.clicked) { --pd->ingameMenuSelection; if(pd->ingameMenuSelection < 0) pd->ingameMenuSelection=2; }
if (pd->inputs.k_down.clicked) { ++pd->ingameMenuSelection; if(pd->ingameMenuSelection > 2) pd->ingameMenuSelection=0; } if (pd->inputs.k_down.clicked) { ++pd->ingameMenuSelection; if(pd->ingameMenuSelection > 2) pd->ingameMenuSelection=0; }
if (pd->inputs.k_accept.clicked){ if (pd->inputs.k_accept.clicked){
switch(pd->ingameMenuSelection){ switch(pd->ingameMenuSelection){
case 0: case 0:
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
break; break;
case 1: case 1:
if(!dungeonActive()) pd->ingameMenuAreYouSureSave = true; if(!dungeonActive()) pd->ingameMenuAreYouSureSave = true;
break; break;
case 2: case 2:
pd->ingameMenuAreYouSure = true; pd->ingameMenuAreYouSure = true;
break; break;
} }
} }
} else if(pd->ingameMenuAreYouSureSave) { } else if(pd->ingameMenuAreYouSureSave) {
if (pd->inputs.k_accept.clicked){ if (pd->inputs.k_accept.clicked){
pd->ingameMenuTimer = 60; pd->ingameMenuTimer = 60;
if(playerLocalID==0) { if(playerLocalID==0) {
saveWorld(currentFileName, &eManager, &worldData, players, playerCount); saveWorld(currentFileName, &eManager, &worldData, players, playerCount);
} }
pd->ingameMenuAreYouSureSave = false; pd->ingameMenuAreYouSureSave = false;
pd->ingameMenuAreYouSure = false; pd->ingameMenuAreYouSure = false;
} else if (pd->inputs.k_decline.clicked){ } else if (pd->inputs.k_decline.clicked){
pd->ingameMenuAreYouSureSave = false; pd->ingameMenuAreYouSureSave = false;
pd->ingameMenuAreYouSure = false; pd->ingameMenuAreYouSure = false;
} }
} else if(pd->ingameMenuAreYouSure) { } else if(pd->ingameMenuAreYouSure) {
if (pd->inputs.k_accept.clicked){ if (pd->inputs.k_accept.clicked){
pd->ingameMenuAreYouSure = false; pd->ingameMenuAreYouSure = false;
pd->ingameMenuAreYouSureSave = false; pd->ingameMenuAreYouSureSave = false;
exitGame(); exitGame();
} else if (pd->inputs.k_decline.clicked){ } else if (pd->inputs.k_decline.clicked){
pd->ingameMenuAreYouSure = false; pd->ingameMenuAreYouSure = false;
pd->ingameMenuAreYouSureSave = false; pd->ingameMenuAreYouSureSave = false;
} }
} }
break; break;
case MENU_INVENTORY: case MENU_INVENTORY:
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked){ if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked){
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
pd->activeItem = &noItem; pd->activeItem = &noItem;
pd->entity.p.isCarrying = false; pd->entity.p.isCarrying = false;
} }
if (pd->inputs.k_accept.clicked){ // Select item from inventory if (pd->inputs.k_accept.clicked){ // Select item from inventory
if(pd->inventory.lastSlot!=0){ if(pd->inventory.lastSlot!=0){
Item median = pd->inventory.items[pd->ingameMenuInvSel]; // create copy of item. Item median = pd->inventory.items[pd->ingameMenuInvSel]; // create copy of item.
removeItemFromInventory(pd->ingameMenuInvSel, &(pd->inventory)); // remove original removeItemFromInventory(pd->ingameMenuInvSel, &(pd->inventory)); // remove original
pushItemToInventoryFront(median, &(pd->inventory)); // add copy to front pushItemToInventoryFront(median, &(pd->inventory)); // add copy to front
playerSetActiveItem(pd, &(pd->inventory.items[0])); // active item = copy. playerSetActiveItem(pd, &(pd->inventory.items[0])); // active item = copy.
} }
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} }
if (pd->inputs.k_up.clicked) { --pd->ingameMenuInvSel; if(pd->ingameMenuInvSel < 0)pd->ingameMenuInvSel=pd->inventory.lastSlot-1; } if (pd->inputs.k_up.clicked) { --pd->ingameMenuInvSel; if(pd->ingameMenuInvSel < 0)pd->ingameMenuInvSel=pd->inventory.lastSlot-1; }
if (pd->inputs.k_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->inventory.lastSlot-1)pd->ingameMenuInvSel=0; } if (pd->inputs.k_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->inventory.lastSlot-1)pd->ingameMenuInvSel=0; }
break; break;
case MENU_CRAFTING: case MENU_CRAFTING:
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE; if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
if (pd->inputs.k_accept.clicked){ if (pd->inputs.k_accept.clicked){
if(craftItem(&(pd->currentRecipes), &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]), &(pd->inventory))){ if(craftItem(&(pd->currentRecipes), &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]), &(pd->inventory))){
playSoundPositioned(snd_craft, pd->entity.level, pd->entity.x, pd->entity.y); playSoundPositioned(snd_craft, pd->entity.level, pd->entity.x, pd->entity.y);
//reset active item pointer, because it could posibly point to garbage now //reset active item pointer, because it could posibly point to garbage now
pd->activeItem = &noItem; pd->activeItem = &noItem;
} }
} }
if (pd->inputs.k_up.clicked) { --pd->ingameMenuInvSel; if(pd->ingameMenuInvSel < 0)pd->ingameMenuInvSel=pd->currentRecipes.size-1; } if (pd->inputs.k_up.clicked) { --pd->ingameMenuInvSel; if(pd->ingameMenuInvSel < 0)pd->ingameMenuInvSel=pd->currentRecipes.size-1; }
if (pd->inputs.k_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->currentRecipes.size-1)pd->ingameMenuInvSel=0; } if (pd->inputs.k_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->currentRecipes.size-1)pd->ingameMenuInvSel=0; }
break; break;
case MENU_WIN: case MENU_WIN:
if (pd->inputs.k_accept.clicked){ if (pd->inputs.k_accept.clicked){
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
pd->entity.p.hasWon = false; pd->entity.p.hasWon = false;
} }
break; break;
case MENU_LOSE: case MENU_LOSE:
if (pd->inputs.k_accept.clicked){ if (pd->inputs.k_accept.clicked){
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
pd->entity.p.isDead = false; pd->entity.p.isDead = false;
pd->entity.p.health = 10; pd->entity.p.health = 10;
pd->entity.level = 1; pd->entity.level = 1;
playerSpawn(pd); playerSpawn(pd);
//TODO: This canceled to main menu, but what should I do in multiplayer? //TODO: This canceled to main menu, but what should I do in multiplayer?
} }
pd->entity.hurtTime = 10; pd->entity.hurtTime = 10;
break; break;
case MENU_CONTAINER: case MENU_CONTAINER:
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE; if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
if (pd->inputs.k_left.clicked) { if (pd->inputs.k_left.clicked) {
@ -146,7 +146,7 @@ void ingameMenuTick(PlayerData *pd, int menu) {
removeItemFromCurrentInv(pullItem); removeItemFromCurrentInv(pullItem);
if (pd->ingameMenuInvSel >= i1->lastSlot) pd->ingameMenuInvSel = i1->lastSlot - 1; if (pd->ingameMenuInvSel >= i1->lastSlot) pd->ingameMenuInvSel = i1->lastSlot - 1;
} }
break; break;
case MENU_DUNGEON: case MENU_DUNGEON:
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE; if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
@ -162,8 +162,8 @@ void ingameMenuTick(PlayerData *pd, int menu) {
enterDungeon(pd); enterDungeon(pd);
} else if(shouldRenderDebug) { } else if(shouldRenderDebug) {
enterDungeon(pd); enterDungeon(pd);
} }
} else { } else {
leaveDungeon(pd); leaveDungeon(pd);
} }
@ -172,55 +172,55 @@ void ingameMenuTick(PlayerData *pd, int menu) {
} }
break; break;
case MENU_NPC: case MENU_NPC:
tickNPCMenu(pd); tickNPCMenu(pd);
break; break;
case MENU_CHARACTER_CUSTOMIZE: case MENU_CHARACTER_CUSTOMIZE:
if (pd->inputs.k_up.clicked) { --pd->ingameMenuSelection; if(pd->ingameMenuSelection < 0) pd->ingameMenuSelection=6; } if (pd->inputs.k_up.clicked) { --pd->ingameMenuSelection; if(pd->ingameMenuSelection < 0) pd->ingameMenuSelection=6; }
if (pd->inputs.k_down.clicked) { ++pd->ingameMenuSelection; if(pd->ingameMenuSelection > 6) pd->ingameMenuSelection=0; } if (pd->inputs.k_down.clicked) { ++pd->ingameMenuSelection; if(pd->ingameMenuSelection > 6) pd->ingameMenuSelection=0; }
u8 wrap = 0; u8 wrap = 0;
wrap = wrap - 1; wrap = wrap - 1;
pd->entity.p.health = 10; pd->entity.p.health = 10;
pd->entity.hurtTime = 10; pd->entity.hurtTime = 10;
//head //head
if(pd->ingameMenuSelection==0) { if(pd->ingameMenuSelection==0) {
if (pd->inputs.k_left.clicked) { --pd->sprite.head; if(pd->sprite.head == wrap) pd->sprite.head=PLAYER_SPRITE_HEAD_COUNT-1; } if (pd->inputs.k_left.clicked) { --pd->sprite.head; if(pd->sprite.head == wrap) pd->sprite.head=PLAYER_SPRITE_HEAD_COUNT-1; }
if (pd->inputs.k_right.clicked) { ++pd->sprite.head; if(pd->sprite.head > PLAYER_SPRITE_HEAD_COUNT-1) pd->sprite.head=0; } if (pd->inputs.k_right.clicked) { ++pd->sprite.head; if(pd->sprite.head > PLAYER_SPRITE_HEAD_COUNT-1) pd->sprite.head=0; }
//eyes //eyes
} else if(pd->ingameMenuSelection==1) { } else if(pd->ingameMenuSelection==1) {
if (pd->inputs.k_left.clicked) { --pd->sprite.eyes; if(pd->sprite.eyes == wrap) pd->sprite.eyes=PLAYER_SPRITE_EYES_COUNT-1; } if (pd->inputs.k_left.clicked) { --pd->sprite.eyes; if(pd->sprite.eyes == wrap) pd->sprite.eyes=PLAYER_SPRITE_EYES_COUNT-1; }
if (pd->inputs.k_right.clicked) { ++pd->sprite.eyes; if(pd->sprite.eyes > PLAYER_SPRITE_EYES_COUNT-1) pd->sprite.eyes=0; } if (pd->inputs.k_right.clicked) { ++pd->sprite.eyes; if(pd->sprite.eyes > PLAYER_SPRITE_EYES_COUNT-1) pd->sprite.eyes=0; }
//body //body
} else if(pd->ingameMenuSelection==2) { } else if(pd->ingameMenuSelection==2) {
if (pd->inputs.k_left.clicked) { --pd->sprite.body; if(pd->sprite.body == wrap) pd->sprite.body=PLAYER_SPRITE_BODY_COUNT-1; } if (pd->inputs.k_left.clicked) { --pd->sprite.body; if(pd->sprite.body == wrap) pd->sprite.body=PLAYER_SPRITE_BODY_COUNT-1; }
if (pd->inputs.k_right.clicked) { ++pd->sprite.body; if(pd->sprite.body > PLAYER_SPRITE_BODY_COUNT-1) pd->sprite.body=0; } if (pd->inputs.k_right.clicked) { ++pd->sprite.body; if(pd->sprite.body > PLAYER_SPRITE_BODY_COUNT-1) pd->sprite.body=0; }
//arms //arms
} else if(pd->ingameMenuSelection==3) { } else if(pd->ingameMenuSelection==3) {
if (pd->inputs.k_left.clicked) { --pd->sprite.arms; if(pd->sprite.arms == wrap) pd->sprite.arms=PLAYER_SPRITE_ARMS_COUNT-1; } if (pd->inputs.k_left.clicked) { --pd->sprite.arms; if(pd->sprite.arms == wrap) pd->sprite.arms=PLAYER_SPRITE_ARMS_COUNT-1; }
if (pd->inputs.k_right.clicked) { ++pd->sprite.arms; if(pd->sprite.arms > PLAYER_SPRITE_ARMS_COUNT-1) pd->sprite.arms=0; } if (pd->inputs.k_right.clicked) { ++pd->sprite.arms; if(pd->sprite.arms > PLAYER_SPRITE_ARMS_COUNT-1) pd->sprite.arms=0; }
//legs //legs
} else if(pd->ingameMenuSelection==4) { } else if(pd->ingameMenuSelection==4) {
if (pd->inputs.k_left.clicked) { --pd->sprite.legs; if(pd->sprite.legs == wrap) pd->sprite.legs=PLAYER_SPRITE_LEGS_COUNT-1; } if (pd->inputs.k_left.clicked) { --pd->sprite.legs; if(pd->sprite.legs == wrap) pd->sprite.legs=PLAYER_SPRITE_LEGS_COUNT-1; }
if (pd->inputs.k_right.clicked) { ++pd->sprite.legs; if(pd->sprite.legs > PLAYER_SPRITE_LEGS_COUNT-1) pd->sprite.legs=0; } if (pd->inputs.k_right.clicked) { ++pd->sprite.legs; if(pd->sprite.legs > PLAYER_SPRITE_LEGS_COUNT-1) pd->sprite.legs=0; }
//rotation //rotation
} else if(pd->ingameMenuSelection==5) { } else if(pd->ingameMenuSelection==5) {
if (pd->inputs.k_left.clicked) { --pd->entity.p.dir; if(pd->entity.p.dir == wrap) pd->entity.p.dir=3; } if (pd->inputs.k_left.clicked) { --pd->entity.p.dir; if(pd->entity.p.dir == wrap) pd->entity.p.dir=3; }
if (pd->inputs.k_right.clicked) { ++pd->entity.p.dir; if(pd->entity.p.dir > 3) pd->entity.p.dir=0; } if (pd->inputs.k_right.clicked) { ++pd->entity.p.dir; if(pd->entity.p.dir > 3) pd->entity.p.dir=0; }
//done //done
} else if(pd->ingameMenuSelection==6) { } else if(pd->ingameMenuSelection==6) {
if(pd->inputs.k_accept.clicked) { if(pd->inputs.k_accept.clicked) {
//TODO: are you sure dialog? //TODO: are you sure dialog?
pd->ingameMenu = 0; pd->ingameMenu = 0;
pd->ingameMenuSelection = 0; pd->ingameMenuSelection = 0;
pd->sprite.choosen = true; pd->sprite.choosen = true;
} }
} }
break; break;
} }
} }
@ -229,279 +229,279 @@ bool rev = true;
char scoreText[15]; char scoreText[15];
void ingameMenuRender(PlayerData *pd, int menu) { void ingameMenuRender(PlayerData *pd, int menu) {
int i; int i;
switch(menu) { switch(menu) {
case MENU_PAUSED: case MENU_PAUSED:
renderFrame(1,1,24,14,0xFF1010AF); renderFrame(1,1,24,14,0xFF1010AF);
drawText("Paused",164,32); drawText("Paused",164,32);
for(i = 3; i >= 0; --i){ for(i = 3; i >= 0; --i){
char* msg = pOptions[i]; char* msg = pOptions[i];
u32 color = 0xFF7F7F7F; u32 color = 0xFF7F7F7F;
if(i == pd->ingameMenuSelection) color = 0xFFFFFFFF; if(i == pd->ingameMenuSelection) color = 0xFFFFFFFF;
if((i == 1 && dungeonActive())) { if((i == 1 && dungeonActive())) {
color = 0xFF7F7FFF; color = 0xFF7F7FFF;
if(i == pd->ingameMenuSelection) color = 0xFFAFAFFF; if(i == pd->ingameMenuSelection) color = 0xFFAFAFFF;
} }
drawTextColor(msg,(400 - (strlen(msg) * 12))/2, (i * 24) + 88, color); drawTextColor(msg,(400 - (strlen(msg) * 12))/2, (i * 24) + 88, color);
} }
if(pd->ingameMenuTimer > 0) drawTextColor("Game Saved!", (400-(11*12))/2, 64,0xFF20FF20); if(pd->ingameMenuTimer > 0) drawTextColor("Game Saved!", (400-(11*12))/2, 64,0xFF20FF20);
if(pd->ingameMenuAreYouSure || pd->ingameMenuAreYouSureSave){ if(pd->ingameMenuAreYouSure || pd->ingameMenuAreYouSureSave){
if(pd->ingameMenuAreYouSure)renderFrame(6,5,19,10,0xFF10108F); if(pd->ingameMenuAreYouSure)renderFrame(6,5,19,10,0xFF10108F);
else renderFrame(6,5,19,10,0xFF108F10); else renderFrame(6,5,19,10,0xFF108F10);
drawText("Are you sure?",122,96); drawText("Are you sure?",122,96);
drawText(" Yes", 164, 117); drawText(" Yes", 164, 117);
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1); renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1);
drawText(" No", 170, 133); drawText(" No", 170, 133);
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1); renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1);
} }
break; break;
case MENU_WIN: case MENU_WIN:
renderFrame(5,3,21,12,0xFFFF1010); renderFrame(5,3,21,12,0xFFFF1010);
if(!rev){ opacity+=5; if(opacity == 255) rev = true; } if(!rev){ opacity+=5; if(opacity == 255) rev = true; }
else { opacity-=5; if(opacity == 100) rev = false; } else { opacity-=5; if(opacity == 100) rev = false; }
sprintf(scoreText,"Score: %d", pd->score); sprintf(scoreText,"Score: %d", pd->score);
drawTextColor("You Win!",158,76,0x0000AFAF + (opacity << 24)); drawTextColor("You Win!",158,76,0x0000AFAF + (opacity << 24));
drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100); drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100);
drawText("Press to continue", 96, 150); drawText("Press to continue", 96, 150);
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1); renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1);
//printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input); //printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input);
break; break;
case MENU_LOSE: case MENU_LOSE:
renderFrame(5,3,21,12,0xFFFF1010); renderFrame(5,3,21,12,0xFFFF1010);
if(!rev){ opacity+=5; if(opacity == 255) rev = true; } if(!rev){ opacity+=5; if(opacity == 255) rev = true; }
else { opacity-=5; if(opacity == 100) rev = false; } else { opacity-=5; if(opacity == 100) rev = false; }
sprintf(scoreText,"Score: %d", pd->score); sprintf(scoreText,"Score: %d", pd->score);
drawTextColor("You DIED!",158,76,0x000000AF + (opacity << 24)); drawTextColor("You DIED!",158,76,0x000000AF + (opacity << 24));
drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100); drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100);
drawText("Press to continue", 96, 150); drawText("Press to continue", 96, 150);
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1); renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1);
//printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input); //printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input);
break; break;
case MENU_INVENTORY: case MENU_INVENTORY:
renderFrame(1,1,24,14,0xFFFF1010); renderFrame(1,1,24,14,0xFFFF1010);
drawTextColor("Inventory",24+1,14+1,0xFF000000); drawTextColor("Inventory",24+1,14+1,0xFF000000);
drawTextColor("Inventory",24,14,0xFF6FE2E2); drawTextColor("Inventory",24,14,0xFF6FE2E2);
renderItemList(&(pd->inventory), 1,1,24,14, pd->ingameMenuInvSel); renderItemList(&(pd->inventory), 1,1,24,14, pd->ingameMenuInvSel);
break; break;
case MENU_CRAFTING: case MENU_CRAFTING:
renderFrame(15,1,24,4,0xFFFF1010); renderFrame(15,1,24,4,0xFFFF1010);
drawTextColor("Have",248+1,14+1,0xFF000000); drawTextColor("Have",248+1,14+1,0xFF000000);
drawTextColor("Have",248,14,0xFF6FE2E2); drawTextColor("Have",248,14,0xFF6FE2E2);
renderFrame(15,5,24,14,0xFFFF1010); renderFrame(15,5,24,14,0xFFFF1010);
drawTextColor("Cost",248+1,78+1,0xFF000000); drawTextColor("Cost",248+1,78+1,0xFF000000);
drawTextColor("Cost",248,78,0xFF6FE2E2); drawTextColor("Cost",248,78,0xFF6FE2E2);
renderFrame(1,1,14,14,0xFFFF1010); renderFrame(1,1,14,14,0xFFFF1010);
drawTextColor(pd->currentCraftTitle,24+1,14+1,0xFF000000); drawTextColor(pd->currentCraftTitle,24+1,14+1,0xFF000000);
drawTextColor(pd->currentCraftTitle,24,14,0xFF6FE2E2); drawTextColor(pd->currentCraftTitle,24,14,0xFF6FE2E2);
renderRecipes(&(pd->currentRecipes), 1, 1, 14, 14, pd->ingameMenuInvSel); renderRecipes(&(pd->currentRecipes), 1, 1, 14, 14, pd->ingameMenuInvSel);
Recipe* rec = &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]); Recipe* rec = &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]);
renderItemIcon(rec->itemResult,rec->itemAmountLevel,128,16); renderItemIcon(rec->itemResult,rec->itemAmountLevel,128,16);
char craftText[12]; char craftText[12];
sprintf(craftText, "%d", countItemInv(rec->itemResult, rec->itemAmountLevel, &(pd->inventory))); sprintf(craftText, "%d", countItemInv(rec->itemResult, rec->itemAmountLevel, &(pd->inventory)));
drawText(craftText,274,34); drawText(craftText,274,34);
if(rec->numOfCosts > 0){ if(rec->numOfCosts > 0){
int i; int i;
for(i = 0; i < rec->numOfCosts; i++){ for(i = 0; i < rec->numOfCosts; i++){
int amnt = countItemInv(rec->costs[i].costItem,0, &(pd->inventory)); int amnt = countItemInv(rec->costs[i].costItem,0, &(pd->inventory));
int ttlCst = rec->costs[i].costAmount; int ttlCst = rec->costs[i].costAmount;
int col = 0xFFFFFFFF; if(amnt<ttlCst) col = 0xFF7F7F7F; int col = 0xFFFFFFFF; if(amnt<ttlCst) col = 0xFF7F7F7F;
renderItemIcon(rec->costs[i].costItem,1,128,48+(i*8)); renderItemIcon(rec->costs[i].costItem,1,128,48+(i*8));
sprintf(craftText,"%d/%d",amnt,ttlCst); sprintf(craftText,"%d/%d",amnt,ttlCst);
drawTextColor(craftText,274,96+(i*18),col); drawTextColor(craftText,274,96+(i*18),col);
} }
} }
break;
case MENU_CONTAINER:
if (pd->curChestEntityR == 1){ offsetX = 48; offsetY = 0;}
else {offsetX = 0; offsetY = 0;}
renderFrame(1,1,15,14,0xFFFF1010);
drawTextColor("Chest",24+1,14+1,0xFF000000);
drawTextColor("Chest",24,14,0xFF6FE2E2);
renderItemList(pd->curChestEntity->entityFurniture.inv,1,1,15,14,
pd->curChestEntityR == 0 ? pd->ingameMenuInvSel : -pd->ingameMenuInvSelOther - 1);
renderFrame(16,1,30,14,0xFFFF1010);
drawTextColor("Inventory",264+1,14+1,0xFF000000);
drawTextColor("Inventory",264,14,0xFF6FE2E2);
renderItemList(&(pd->inventory),16,1,30,14,
pd->curChestEntityR == 1 ? pd->ingameMenuInvSel : -pd->ingameMenuInvSelOther - 1);
offsetX = 0;offsetY = 0;
break;
case MENU_DUNGEON:
renderFrame(1,1,24,14,0xFFFF1010);
if(pd->entity.level!=5) {
drawTextColor("Dungeon Entrance",24+1,14+1,0xFF000000);
drawTextColor("Dungeon Entrance",24,14,0xFF6FE2E2);
drawText("Warning: ", 32, 32);
drawText("You need a Dungeon Key to ", 32, 56);
drawText("enter and cannot save while ", 32, 72);
drawText("being in the Dungeon! ", 32, 88);
drawText("After leaving you will need ", 32, 112);
drawText("a new Dungeon Key for ", 32, 128);
drawText("entering another Dungeon! ", 32, 144);
drawText(" Enter", 148, 171);
} else {
drawTextColor("Dungeon Exit",24+1,14+1,0xFF000000);
drawTextColor("Dungeon Exit",24,14,0xFF6FE2E2);
drawText("Warning: ", 32, 32);
drawText("The Dungeon and everything ", 32, 56);
drawText("in it will disappear when ", 32, 72);
drawText("you leave it! ", 32, 88);
drawText("You will need a new Dungeon ", 32, 112);
drawText("Key for entering another ", 32, 128);
drawText("Dungeon again! ", 32, 144);
drawText(" Leave", 148, 171);
}
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 150, 168, 1);
drawText(" Stay", 148, 195);
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 150, 192, 1);
break; break;
case MENU_NPC: case MENU_CONTAINER:
renderNPCMenu(&(pd->npcMenuData)); if (pd->curChestEntityR == 1){ offsetX = 48; offsetY = 0;}
break; else {offsetX = 0; offsetY = 0;}
case MENU_CHARACTER_CUSTOMIZE: renderFrame(1,1,15,14,0xFFFF1010);
renderFrame(1,1,24,14,0xFFFF1010); drawTextColor("Chest",24+1,14+1,0xFF000000);
drawTextColor("Character",24+1,14+1,0xFF000000); drawTextColor("Chest",24,14,0xFF6FE2E2);
drawTextColor("Character",24,14,0xFF6FE2E2); renderItemList(pd->curChestEntity->entityFurniture.inv,1,1,15,14,
pd->curChestEntityR == 0 ? pd->ingameMenuInvSel : -pd->ingameMenuInvSelOther - 1);
renderFrame(16,1,30,14,0xFFFF1010);
drawTextColor("Inventory",264+1,14+1,0xFF000000);
drawTextColor("Inventory",264,14,0xFF6FE2E2);
renderItemList(&(pd->inventory),16,1,30,14,
pd->curChestEntityR == 1 ? pd->ingameMenuInvSel : -pd->ingameMenuInvSelOther - 1);
offsetX = 0;offsetY = 0;
break;
drawText("Head: ", 32, 56); case MENU_DUNGEON:
drawText("Eyes: ", 32, 72); renderFrame(1,1,24,14,0xFFFF1010);
drawText("Body: ", 32, 88); if(pd->entity.level!=5) {
drawText("Arms: ", 32, 104); drawTextColor("Dungeon Entrance",24+1,14+1,0xFF000000);
drawText("Legs: ", 32, 120); drawTextColor("Dungeon Entrance",24,14,0xFF6FE2E2);
drawText("Rot.: ", 32, 144);
//for the dynamic part drawText("Warning: ", 32, 32);
char display[30]; drawText("You need a Dungeon Key to ", 32, 56);
drawText("enter and cannot save while ", 32, 72);
drawText("being in the Dungeon! ", 32, 88);
drawText("After leaving you will need ", 32, 112);
drawText("a new Dungeon Key for ", 32, 128);
drawText("entering another Dungeon! ", 32, 144);
sprintf(display, pd->ingameMenuSelection==0 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.head+1, PLAYER_SPRITE_HEAD_COUNT); drawText(" Enter", 148, 171);
drawText(display, 96, 56); } else {
sprintf(display, pd->ingameMenuSelection==1 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.eyes+1, PLAYER_SPRITE_EYES_COUNT); drawTextColor("Dungeon Exit",24+1,14+1,0xFF000000);
drawText(display, 96, 72); drawTextColor("Dungeon Exit",24,14,0xFF6FE2E2);
sprintf(display, pd->ingameMenuSelection==2 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.body+1, PLAYER_SPRITE_BODY_COUNT);
drawText(display, 96, 88);
sprintf(display, pd->ingameMenuSelection==3 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.arms+1, PLAYER_SPRITE_ARMS_COUNT);
drawText(display, 96, 104);
sprintf(display, pd->ingameMenuSelection==4 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.legs+1, PLAYER_SPRITE_LEGS_COUNT);
drawText(display, 96, 120);
sprintf(display, pd->ingameMenuSelection==5 ? "< %02i/%02i >" : " %02i/%02i ", pd->entity.p.dir+1, 4);
drawText(display, 96, 144);
sprintf(display, pd->ingameMenuSelection==6 ? "< Done >" : " Done ");
drawText(display, 96, 172);
int oox = offsetX; drawText("Warning: ", 32, 32);
int ooy = offsetY; drawText("The Dungeon and everything ", 32, 56);
int osx = playerScale; drawText("in it will disappear when ", 32, 72);
drawText("you leave it! ", 32, 88);
drawText("You will need a new Dungeon ", 32, 112);
drawText("Key for entering another ", 32, 128);
drawText("Dungeon again! ", 32, 144);
renderFrame(13,3,22,12,0xFF909090); drawText(" Leave", 148, 171);
//move player sprite to 0/0 }
offsetX = pd->entity.x - 8;
offsetY = pd->entity.y - 8;
//move to where I want it
offsetX -= 108;
offsetY -= 28;
playerScale = 8;
renderPlayer(pd);
offsetX = oox; renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 150, 168, 1);
offsetY = ooy; drawText(" Stay", 148, 195);
playerScale = osx; renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 150, 192, 1);
break; break;
}
case MENU_NPC:
renderNPCMenu(&(pd->npcMenuData));
break;
case MENU_CHARACTER_CUSTOMIZE:
renderFrame(1,1,24,14,0xFFFF1010);
drawTextColor("Character",24+1,14+1,0xFF000000);
drawTextColor("Character",24,14,0xFF6FE2E2);
drawText("Head: ", 32, 56);
drawText("Eyes: ", 32, 72);
drawText("Body: ", 32, 88);
drawText("Arms: ", 32, 104);
drawText("Legs: ", 32, 120);
drawText("Rot.: ", 32, 144);
//for the dynamic part
char display[30];
sprintf(display, pd->ingameMenuSelection==0 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.head+1, PLAYER_SPRITE_HEAD_COUNT);
drawText(display, 96, 56);
sprintf(display, pd->ingameMenuSelection==1 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.eyes+1, PLAYER_SPRITE_EYES_COUNT);
drawText(display, 96, 72);
sprintf(display, pd->ingameMenuSelection==2 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.body+1, PLAYER_SPRITE_BODY_COUNT);
drawText(display, 96, 88);
sprintf(display, pd->ingameMenuSelection==3 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.arms+1, PLAYER_SPRITE_ARMS_COUNT);
drawText(display, 96, 104);
sprintf(display, pd->ingameMenuSelection==4 ? "< %02i/%02i >" : " %02i/%02i ", pd->sprite.legs+1, PLAYER_SPRITE_LEGS_COUNT);
drawText(display, 96, 120);
sprintf(display, pd->ingameMenuSelection==5 ? "< %02i/%02i >" : " %02i/%02i ", pd->entity.p.dir+1, 4);
drawText(display, 96, 144);
sprintf(display, pd->ingameMenuSelection==6 ? "< Done >" : " Done ");
drawText(display, 96, 172);
int oox = offsetX;
int ooy = offsetY;
int osx = playerScale;
renderFrame(13,3,22,12,0xFF909090);
//move player sprite to 0/0
offsetX = pd->entity.x - 8;
offsetY = pd->entity.y - 8;
//move to where I want it
offsetX -= 108;
offsetY -= 28;
playerScale = 8;
renderPlayer(pd);
offsetX = oox;
offsetY = ooy;
playerScale = osx;
break;
}
} }
//touch menu //touch menu
void tickTouchMap(PlayerData *pd){ void tickTouchMap(PlayerData *pd){
if(pd->mapShouldRender){ if(pd->mapShouldRender){
if(pd->inputs.k_touch.px > 0 || pd->inputs.k_touch.py > 0){ if(pd->inputs.k_touch.px > 0 || pd->inputs.k_touch.py > 0){
// Plus/Minus zoom button // Plus/Minus zoom button
if(pd->inputs.k_touch.py > 204 && pd->inputs.k_touch.py < 232){ if(pd->inputs.k_touch.py > 204 && pd->inputs.k_touch.py < 232){
if(pd->inputs.k_touch.px > 284 && pd->inputs.k_touch.px < 312){ if(pd->inputs.k_touch.px > 284 && pd->inputs.k_touch.px < 312){
if(pd->mapZoomLevel > 4) return; if(pd->mapZoomLevel > 4) return;
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){ if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
pd->mapZoomLevel += 2; pd->mapZoomLevel += 2;
pd->mapScrollX -= (50 * (pd->mapZoomLevel/2)); pd->mapScrollX -= (50 * (pd->mapZoomLevel/2));
pd->mapScrollY -= (40 * (pd->mapZoomLevel/2)); pd->mapScrollY -= (40 * (pd->mapZoomLevel/2));
pd->touchIsChangingSize = true; pd->touchIsChangingSize = true;
sprintf(pd->mapText, "x%d", pd->mapZoomLevel); sprintf(pd->mapText, "x%d", pd->mapZoomLevel);
} }
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel); if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
else if(pd->mapScrollX > 0) pd->mapScrollX = 0; else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel); if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
else if(pd->mapScrollY > 0) pd->mapScrollY = 0; else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
return; return;
} else if(pd->inputs.k_touch.px > 256 && pd->inputs.k_touch.px < 284){ } else if(pd->inputs.k_touch.px > 256 && pd->inputs.k_touch.px < 284){
if(pd->mapZoomLevel < 4) return; if(pd->mapZoomLevel < 4) return;
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){ if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
pd->mapScrollX += (50 * (pd->mapZoomLevel/2)); pd->mapScrollX += (50 * (pd->mapZoomLevel/2));
pd->mapScrollY += (40 * (pd->mapZoomLevel/2)); pd->mapScrollY += (40 * (pd->mapZoomLevel/2));
pd->mapZoomLevel -= 2; pd->mapZoomLevel -= 2;
pd->touchIsChangingSize = true; pd->touchIsChangingSize = true;
sprintf(pd->mapText, "x%d", pd->mapZoomLevel); sprintf(pd->mapText, "x%d", pd->mapZoomLevel);
} }
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel); if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
else if(pd->mapScrollX > 0) pd->mapScrollX = 0; else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel); if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
else if(pd->mapScrollY > 0) pd->mapScrollY = 0; else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
return; return;
} }
} else if(pd->inputs.k_touch.py > 8 && pd->inputs.k_touch.py < 40 && pd->inputs.k_touch.px > 284 && pd->inputs.k_touch.px < 312){ } else if(pd->inputs.k_touch.py > 8 && pd->inputs.k_touch.py < 40 && pd->inputs.k_touch.px > 284 && pd->inputs.k_touch.px < 312){
// Exit Button // Exit Button
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){ if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
pd->mapShouldRender = false; pd->mapShouldRender = false;
return; return;
} }
} }
if(!pd->touchIsDraggingMap){ if(!pd->touchIsDraggingMap){
pd->touchLastX = pd->inputs.k_touch.px; pd->touchLastX = pd->inputs.k_touch.px;
pd->touchLastY = pd->inputs.k_touch.py; pd->touchLastY = pd->inputs.k_touch.py;
} }
if(pd->mapZoomLevel > 2){ if(pd->mapZoomLevel > 2){
int dx = pd->touchLastX - pd->inputs.k_touch.px; int dx = pd->touchLastX - pd->inputs.k_touch.px;
if(dx > 1 || dx < -1){ if(dx > 1 || dx < -1){
pd->mapScrollX -= dx; pd->mapScrollX -= dx;
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel); if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
else if(pd->mapScrollX > 0) pd->mapScrollX = 0; else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
} }
pd->touchLastX = pd->inputs.k_touch.px; pd->touchLastX = pd->inputs.k_touch.px;
} }
int dy = pd->touchLastY - pd->inputs.k_touch.py; int dy = pd->touchLastY - pd->inputs.k_touch.py;
if(dy > 1 || dy < -1){ if(dy > 1 || dy < -1){
pd->mapScrollY -= dy; pd->mapScrollY -= dy;
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel); if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
else if(pd->mapScrollY > 0) pd->mapScrollY = 0; else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
} }
pd->touchLastY = pd->inputs.k_touch.py; pd->touchLastY = pd->inputs.k_touch.py;
pd->touchIsDraggingMap = true; pd->touchIsDraggingMap = true;
} else { } else {
pd->touchIsDraggingMap = false; pd->touchIsDraggingMap = false;
pd->touchIsChangingSize = false; pd->touchIsChangingSize = false;
} }
} else { } else {
// touch minimap to bring up zoomed map. // touch minimap to bring up zoomed map.
if(pd->inputs.k_touch.py > 100 && pd->inputs.k_touch.py < 228 && pd->inputs.k_touch.px > 10 && pd->inputs.k_touch.px < 142){ if(pd->inputs.k_touch.py > 100 && pd->inputs.k_touch.py < 228 && pd->inputs.k_touch.px > 10 && pd->inputs.k_touch.px < 142){
pd->mapShouldRender = true; pd->mapShouldRender = true;
} }
} }
} }
void tickTouchQuickSelect(PlayerData *pd) { void tickTouchQuickSelect(PlayerData *pd) {
@ -523,6 +523,6 @@ void tickTouchQuickSelect(PlayerData *pd) {
} }
void ingameMenuTickTouch(PlayerData *pd) { void ingameMenuTickTouch(PlayerData *pd) {
tickTouchMap(pd); tickTouchMap(pd);
tickTouchQuickSelect(pd); tickTouchQuickSelect(pd);
} }

View file

@ -1,55 +1,55 @@
#include "Input.h" #include "Input.h"
void toggleKey(Key* key, bool held, bool down){ void toggleKey(Key* key, bool held, bool down){
key->down = held; key->down = held;
key->clicked = down; key->clicked = down;
} }
void tickKeys(Inputs *inputs, u32 held, u32 down){ void tickKeys(Inputs *inputs, u32 held, u32 down){
hidTouchRead(&(inputs->k_touch)); // Update touch position hidTouchRead(&(inputs->k_touch)); // Update touch position
toggleKey(&(inputs->k_up), held & localInputs.k_up.input, down & localInputs.k_up.input); toggleKey(&(inputs->k_up), held & localInputs.k_up.input, down & localInputs.k_up.input);
toggleKey(&(inputs->k_down), held & localInputs.k_down.input, down & localInputs.k_down.input); toggleKey(&(inputs->k_down), held & localInputs.k_down.input, down & localInputs.k_down.input);
toggleKey(&(inputs->k_left), held & localInputs.k_left.input, down & localInputs.k_left.input); toggleKey(&(inputs->k_left), held & localInputs.k_left.input, down & localInputs.k_left.input);
toggleKey(&(inputs->k_right), held & localInputs.k_right.input, down & localInputs.k_right.input); toggleKey(&(inputs->k_right), held & localInputs.k_right.input, down & localInputs.k_right.input);
toggleKey(&(inputs->k_pause), held & localInputs.k_pause.input, down & localInputs.k_pause.input); toggleKey(&(inputs->k_pause), held & localInputs.k_pause.input, down & localInputs.k_pause.input);
toggleKey(&(inputs->k_attack), held & localInputs.k_attack.input, down & localInputs.k_attack.input); toggleKey(&(inputs->k_attack), held & localInputs.k_attack.input, down & localInputs.k_attack.input);
toggleKey(&(inputs->k_menu), held & localInputs.k_menu.input, down & localInputs.k_menu.input); toggleKey(&(inputs->k_menu), held & localInputs.k_menu.input, down & localInputs.k_menu.input);
toggleKey(&(inputs->k_accept), held & localInputs.k_accept.input, down & localInputs.k_accept.input); toggleKey(&(inputs->k_accept), held & localInputs.k_accept.input, down & localInputs.k_accept.input);
toggleKey(&(inputs->k_decline), held & localInputs.k_decline.input, down & localInputs.k_decline.input); toggleKey(&(inputs->k_decline), held & localInputs.k_decline.input, down & localInputs.k_decline.input);
toggleKey(&(inputs->k_delete), held & localInputs.k_delete.input, down & localInputs.k_delete.input); toggleKey(&(inputs->k_delete), held & localInputs.k_delete.input, down & localInputs.k_delete.input);
toggleKey(&(inputs->k_menuNext), held & localInputs.k_menuNext.input, down & localInputs.k_menuNext.input); toggleKey(&(inputs->k_menuNext), held & localInputs.k_menuNext.input, down & localInputs.k_menuNext.input);
toggleKey(&(inputs->k_menuPrev), held & localInputs.k_menuPrev.input, down & localInputs.k_menuPrev.input); toggleKey(&(inputs->k_menuPrev), held & localInputs.k_menuPrev.input, down & localInputs.k_menuPrev.input);
} }
void resetKeys(Inputs *inputs) { void resetKeys(Inputs *inputs) {
(inputs->k_touch).px = -1; (inputs->k_touch).px = -1;
(inputs->k_touch).py = -1; (inputs->k_touch).py = -1;
toggleKey(&(inputs->k_up), false, false); toggleKey(&(inputs->k_up), false, false);
toggleKey(&(inputs->k_down), false, false); toggleKey(&(inputs->k_down), false, false);
toggleKey(&(inputs->k_left), false, false); toggleKey(&(inputs->k_left), false, false);
toggleKey(&(inputs->k_right), false, false); toggleKey(&(inputs->k_right), false, false);
toggleKey(&(inputs->k_pause), false, false); toggleKey(&(inputs->k_pause), false, false);
toggleKey(&(inputs->k_attack), false, false); toggleKey(&(inputs->k_attack), false, false);
toggleKey(&(inputs->k_menu), false, false); toggleKey(&(inputs->k_menu), false, false);
toggleKey(&(inputs->k_accept), false, false); toggleKey(&(inputs->k_accept), false, false);
toggleKey(&(inputs->k_decline), false, false); toggleKey(&(inputs->k_decline), false, false);
toggleKey(&(inputs->k_delete), false, false); toggleKey(&(inputs->k_delete), false, false);
toggleKey(&(inputs->k_menuNext), false, false); toggleKey(&(inputs->k_menuNext), false, false);
toggleKey(&(inputs->k_menuPrev), false, false); toggleKey(&(inputs->k_menuPrev), false, false);
} }
void resetClicked(Inputs *inputs) { void resetClicked(Inputs *inputs) {
inputs->k_up.clicked = false; inputs->k_up.clicked = false;
inputs->k_down.clicked = false; inputs->k_down.clicked = false;
inputs->k_left.clicked = false; inputs->k_left.clicked = false;
inputs->k_right.clicked = false; inputs->k_right.clicked = false;
inputs->k_pause.clicked = false; inputs->k_pause.clicked = false;
inputs->k_attack.clicked = false; inputs->k_attack.clicked = false;
inputs->k_menu.clicked = false; inputs->k_menu.clicked = false;
inputs->k_accept.clicked = false; inputs->k_accept.clicked = false;
inputs->k_decline.clicked = false; inputs->k_decline.clicked = false;
inputs->k_delete.clicked = false; inputs->k_delete.clicked = false;
inputs->k_menuNext.clicked = false; inputs->k_menuNext.clicked = false;
inputs->k_menuPrev.clicked = false; inputs->k_menuPrev.clicked = false;
} }

View file

@ -9,20 +9,20 @@ typedef struct {
} Key; } Key;
typedef struct { typedef struct {
Key k_null; Key k_null;
Key k_up; Key k_up;
Key k_down; Key k_down;
Key k_left; Key k_left;
Key k_right; Key k_right;
Key k_attack; Key k_attack;
Key k_menu; Key k_menu;
Key k_pause; Key k_pause;
Key k_accept; Key k_accept;
Key k_decline; Key k_decline;
Key k_delete; Key k_delete;
Key k_menuNext; Key k_menuNext;
Key k_menuPrev; Key k_menuPrev;
touchPosition k_touch; touchPosition k_touch;
} Inputs; } Inputs;
Inputs localInputs; Inputs localInputs;

View file

@ -3,167 +3,167 @@
char currentName[16]; char currentName[16];
bool isItemEmpty(Item* item) { bool isItemEmpty(Item* item) {
if(item->id < 6 || item->id > 100 || item->onlyOne == true) return false; if(item->id < 6 || item->id > 100 || item->onlyOne == true) return false;
if(item->countLevel < 1) return true; if(item->countLevel < 1) return true;
return false; return false;
} }
void pushItemToInventoryFront(Item item, Inventory * inv) { void pushItemToInventoryFront(Item item, Inventory * inv) {
if(inv->lastSlot < 300) ++inv->lastSlot; if(inv->lastSlot < 300) ++inv->lastSlot;
int i; int i;
for(i = inv->lastSlot;i > 0;--i){ for(i = inv->lastSlot;i > 0;--i){
inv->items[i] = inv->items[i-1]; // Move the items up the list. inv->items[i] = inv->items[i-1]; // Move the items up the list.
inv->items[i].slotNum = i; inv->items[i].slotNum = i;
} }
item.invPtr = (int*)inv; item.invPtr = (int*)inv;
inv->items[0] = item; inv->items[0] = item;
inv->items[0].slotNum = 0; inv->items[0].slotNum = 0;
} }
void addItemToInventory(Item item, Inventory * inv) { void addItemToInventory(Item item, Inventory * inv) {
if(!item.onlyOne){ if(!item.onlyOne){
int i; int i;
for(i = 0;i < inv->lastSlot;++i){ //Search inventory if item already exists. for(i = 0;i < inv->lastSlot;++i){ //Search inventory if item already exists.
if(inv->items[i].id == item.id){ if(inv->items[i].id == item.id){
inv->items[i].countLevel+=item.countLevel; inv->items[i].countLevel+=item.countLevel;
return; return;
} }
} }
} }
item.slotNum = inv->lastSlot; item.slotNum = inv->lastSlot;
item.invPtr = (int*)inv; item.invPtr = (int*)inv;
inv->items[inv->lastSlot] = item; inv->items[inv->lastSlot] = item;
++inv->lastSlot; ++inv->lastSlot;
} }
void removeItemFromCurrentInv(Item* item) { void removeItemFromCurrentInv(Item* item) {
removeItemFromInventory(item->slotNum, (Inventory*)item->invPtr); removeItemFromInventory(item->slotNum, (Inventory*)item->invPtr);
} }
Item nullItem; Item nullItem;
void removeItemFromInventory(int slot, Inventory * inv) { void removeItemFromInventory(int slot, Inventory * inv) {
int i; int i;
for(i = slot;i < inv->lastSlot - 1;++i){ for(i = slot;i < inv->lastSlot - 1;++i){
inv->items[i] = inv->items[i + 1]; // Move the items down. inv->items[i] = inv->items[i + 1]; // Move the items down.
inv->items[i].slotNum--; inv->items[i].slotNum--;
} }
--inv->lastSlot; --inv->lastSlot;
inv->items[inv->lastSlot] = nullItem; // Make the last slot null. inv->items[inv->lastSlot] = nullItem; // Make the last slot null.
} }
Item newItem(int id, int cLevel) { Item newItem(int id, int cLevel) {
Item item; Item item;
item.id = id; item.id = id;
if(id != ITEM_NULL){ if(id != ITEM_NULL){
if(cLevel > 999) cLevel = 999; if(cLevel > 999) cLevel = 999;
item.countLevel = cLevel; item.countLevel = cLevel;
if(id < 7 || (id > 27 && id < 51) || id > 100) item.onlyOne = true; // Tools + Furniture. if(id < 7 || (id > 27 && id < 51) || id > 100) item.onlyOne = true; // Tools + Furniture.
else item.onlyOne = false; else item.onlyOne = false;
} }
item.chestPtr = NULL; item.chestPtr = NULL;
return item; return item;
} }
Item* getItemFromInventory(int itemID, Inventory * inv) { Item* getItemFromInventory(int itemID, Inventory * inv) {
int i; int i;
for(i = 0;i < inv->lastSlot;++i){ for(i = 0;i < inv->lastSlot;++i){
if(inv->items[i].id == itemID){ if(inv->items[i].id == itemID){
return &inv->items[i]; return &inv->items[i];
} }
} }
return (Item*)NULL; return (Item*)NULL;
} }
int countItemInv(int itemID, int level, Inventory* inv) { int countItemInv(int itemID, int level, Inventory* inv) {
int i, count = 0; int i, count = 0;
for(i = 0;i < inv->lastSlot;++i){ for(i = 0;i < inv->lastSlot;++i){
if(inv->items[i].id == itemID){ if(inv->items[i].id == itemID){
if(inv->items[i].onlyOne){ if(inv->items[i].onlyOne){
if(level == inv->items[i].countLevel) count++; if(level == inv->items[i].countLevel) count++;
} else count += inv->items[i].countLevel; } else count += inv->items[i].countLevel;
} }
} }
return count; return count;
} }
char* getItemName(int itemID, int countLevel) { char* getItemName(int itemID, int countLevel) {
switch(itemID){ switch(itemID){
case TOOL_SHOVEL: case TOOL_SHOVEL:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Shovel"; case 1: return "Rock Shovel";
case 2: return "Iron Shovel"; case 2: return "Iron Shovel";
case 3: return "Gold Shovel"; case 3: return "Gold Shovel";
case 4: return "Gem Shovel"; case 4: return "Gem Shovel";
default: return "Wood Shovel"; default: return "Wood Shovel";
} }
case TOOL_HOE: case TOOL_HOE:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Hoe"; case 1: return "Rock Hoe";
case 2: return "Iron Hoe"; case 2: return "Iron Hoe";
case 3: return "Gold Hoe"; case 3: return "Gold Hoe";
case 4: return "Gem Hoe"; case 4: return "Gem Hoe";
default: return "Wood Hoe"; default: return "Wood Hoe";
} }
case TOOL_SWORD: case TOOL_SWORD:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Sword"; case 1: return "Rock Sword";
case 2: return "Iron Sword"; case 2: return "Iron Sword";
case 3: return "Gold Sword"; case 3: return "Gold Sword";
case 4: return "Gem Sword"; case 4: return "Gem Sword";
default: return "Wood Sword"; default: return "Wood Sword";
} }
case TOOL_PICKAXE: case TOOL_PICKAXE:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Pickaxe"; case 1: return "Rock Pickaxe";
case 2: return "Iron Pickaxe"; case 2: return "Iron Pickaxe";
case 3: return "Gold Pickaxe"; case 3: return "Gold Pickaxe";
case 4: return "Gem Pickaxe"; case 4: return "Gem Pickaxe";
default: return "Wood Pickaxe"; default: return "Wood Pickaxe";
} }
case TOOL_AXE: case TOOL_AXE:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Axe"; case 1: return "Rock Axe";
case 2: return "Iron Axe"; case 2: return "Iron Axe";
case 3: return "Gold Axe"; case 3: return "Gold Axe";
case 4: return "Gem Axe"; case 4: return "Gem Axe";
default: return "Wood Axe"; default: return "Wood Axe";
} }
case ITEM_ANVIL: return "Anvil"; case ITEM_ANVIL: return "Anvil";
case ITEM_CHEST: return "Chest"; case ITEM_CHEST: return "Chest";
case ITEM_OVEN: return "Oven"; case ITEM_OVEN: return "Oven";
case ITEM_FURNACE: return "Furnace"; case ITEM_FURNACE: return "Furnace";
case ITEM_WORKBENCH: return "Workbench"; case ITEM_WORKBENCH: return "Workbench";
case ITEM_POTION_MAKER: return "Potion Maker"; case ITEM_POTION_MAKER: return "Potion Maker";
case ITEM_LANTERN: return "Lantern"; case ITEM_LANTERN: return "Lantern";
case ITEM_POWGLOVE: return "Power Glove"; case ITEM_POWGLOVE: return "Power Glove";
case ITEM_FLOWER: sprintf(currentName,"%d Flower", countLevel); return currentName; case ITEM_FLOWER: sprintf(currentName,"%d Flower", countLevel); return currentName;
case ITEM_WOOD: sprintf(currentName,"%d Wood", countLevel); return currentName; case ITEM_WOOD: sprintf(currentName,"%d Wood", countLevel); return currentName;
case ITEM_STONE: sprintf(currentName,"%d Stone", countLevel); return currentName; case ITEM_STONE: sprintf(currentName,"%d Stone", countLevel); return currentName;
case ITEM_SAND: sprintf(currentName,"%d Sand", countLevel); return currentName; case ITEM_SAND: sprintf(currentName,"%d Sand", countLevel); return currentName;
case ITEM_DIRT: sprintf(currentName,"%d Dirt", countLevel); return currentName; case ITEM_DIRT: sprintf(currentName,"%d Dirt", countLevel); return currentName;
case ITEM_CLOUD: sprintf(currentName,"%d Cloud", countLevel); return currentName; case ITEM_CLOUD: sprintf(currentName,"%d Cloud", countLevel); return currentName;
case ITEM_ACORN: sprintf(currentName,"%d Acorn", countLevel); return currentName; case ITEM_ACORN: sprintf(currentName,"%d Acorn", countLevel); return currentName;
case ITEM_CACTUS: sprintf(currentName,"%d Cactus", countLevel); return currentName; case ITEM_CACTUS: sprintf(currentName,"%d Cactus", countLevel); return currentName;
case ITEM_SEEDS: sprintf(currentName,"%d Seeds", countLevel); return currentName; case ITEM_SEEDS: sprintf(currentName,"%d Seeds", countLevel); return currentName;
case ITEM_WHEAT: sprintf(currentName,"%d Wheat", countLevel); return currentName; case ITEM_WHEAT: sprintf(currentName,"%d Wheat", countLevel); return currentName;
case ITEM_FLESH: sprintf(currentName,"%d Flesh", countLevel); return currentName; case ITEM_FLESH: sprintf(currentName,"%d Flesh", countLevel); return currentName;
case ITEM_BREAD: sprintf(currentName,"%d Bread", countLevel); return currentName; case ITEM_BREAD: sprintf(currentName,"%d Bread", countLevel); return currentName;
case ITEM_APPLE: sprintf(currentName,"%d Apple", countLevel); return currentName; case ITEM_APPLE: sprintf(currentName,"%d Apple", countLevel); return currentName;
case ITEM_GOLD_APPLE: sprintf(currentName,"%d Golden Apple", countLevel); return currentName; case ITEM_GOLD_APPLE: sprintf(currentName,"%d Golden Apple", countLevel); return currentName;
case ITEM_STRENGTH_POTION: sprintf(currentName,"%d Strength Potion", countLevel); return currentName; case ITEM_STRENGTH_POTION: sprintf(currentName,"%d Strength Potion", countLevel); return currentName;
case ITEM_SPEED_POTION: sprintf(currentName,"%d Speed Potion", countLevel); return currentName; case ITEM_SPEED_POTION: sprintf(currentName,"%d Speed Potion", countLevel); return currentName;
case ITEM_REGEN_POTION: sprintf(currentName,"%d Regen Potion", countLevel); return currentName; case ITEM_REGEN_POTION: sprintf(currentName,"%d Regen Potion", countLevel); return currentName;
case ITEM_SWIM_BREATH_POTION: sprintf(currentName,"%d Swim Potion", countLevel); return currentName; case ITEM_SWIM_BREATH_POTION: sprintf(currentName,"%d Swim Potion", countLevel); return currentName;
case ITEM_COAL: sprintf(currentName,"%d Coal", countLevel); return currentName; case ITEM_COAL: sprintf(currentName,"%d Coal", countLevel); return currentName;
case ITEM_IRONORE: sprintf(currentName,"%d Iron ore", countLevel); return currentName; case ITEM_IRONORE: sprintf(currentName,"%d Iron ore", countLevel); return currentName;
case ITEM_GOLDORE: sprintf(currentName,"%d Gold ore", countLevel); return currentName; case ITEM_GOLDORE: sprintf(currentName,"%d Gold ore", countLevel); return currentName;
case ITEM_IRONINGOT: sprintf(currentName,"%d Iron ingot", countLevel); return currentName; case ITEM_IRONINGOT: sprintf(currentName,"%d Iron ingot", countLevel); return currentName;
case ITEM_GOLDINGOT: sprintf(currentName,"%d Gold ingot", countLevel); return currentName; case ITEM_GOLDINGOT: sprintf(currentName,"%d Gold ingot", countLevel); return currentName;
case ITEM_GLASS: sprintf(currentName,"%d Glass", countLevel); return currentName; case ITEM_GLASS: sprintf(currentName,"%d Glass", countLevel); return currentName;
case ITEM_GEM: sprintf(currentName,"%d Gem", countLevel); return currentName; case ITEM_GEM: sprintf(currentName,"%d Gem", countLevel); return currentName;
case ITEM_SLIME: sprintf(currentName,"%d Slime", countLevel); return currentName; case ITEM_SLIME: sprintf(currentName,"%d Slime", countLevel); return currentName;
case ITEM_LOOM: return "Loom"; case ITEM_LOOM: return "Loom";
case ITEM_ENCHANTER: return "Enchanter"; case ITEM_ENCHANTER: return "Enchanter";
@ -190,92 +190,92 @@ char* getItemName(int itemID, int countLevel) {
case ITEM_DRAGON_EGG: sprintf(currentName,"%d Dragon Egg", countLevel); return currentName; case ITEM_DRAGON_EGG: sprintf(currentName,"%d Dragon Egg", countLevel); return currentName;
case ITEM_DRAGON_SCALE: sprintf(currentName,"%d Dragon Scale", countLevel); return currentName; case ITEM_DRAGON_SCALE: sprintf(currentName,"%d Dragon Scale", countLevel); return currentName;
case ITEM_BOOKSHELVES: sprintf(currentName,"%d Bookshelves", countLevel); return currentName; case ITEM_BOOKSHELVES: sprintf(currentName,"%d Bookshelves", countLevel); return currentName;
case ITEM_MAGIC_DUST: sprintf(currentName,"%d Magic Dust", countLevel); return currentName; case ITEM_MAGIC_DUST: sprintf(currentName,"%d Magic Dust", countLevel); return currentName;
case ITEM_COIN: sprintf(currentName,"%d Coins", countLevel); return currentName; case ITEM_COIN: sprintf(currentName,"%d Coins", countLevel); return currentName;
case TOOL_BUCKET: case TOOL_BUCKET:
switch(countLevel){ switch(countLevel){
case 1: return "Water Bucket"; case 1: return "Water Bucket";
case 2: return "Lava Bucket"; case 2: return "Lava Bucket";
default: return "Empty Bucket"; default: return "Empty Bucket";
} }
case TOOL_BOW: return "Bow"; case TOOL_BOW: return "Bow";
case TOOL_MAGIC_COMPASS: return "Magic Compass"; case TOOL_MAGIC_COMPASS: return "Magic Compass";
default: return ""; // null default: return ""; // null
} }
} }
char* getBasicItemName(int itemID, int countLevel) { char* getBasicItemName(int itemID, int countLevel) {
switch(itemID){ switch(itemID){
case TOOL_SHOVEL: case TOOL_SHOVEL:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Shovel"; case 1: return "Rock Shovel";
case 2: return "Iron Shovel"; case 2: return "Iron Shovel";
case 3: return "Gold Shovel"; case 3: return "Gold Shovel";
case 4: return "Gem Shovel"; case 4: return "Gem Shovel";
default: return "Wood Shovel"; default: return "Wood Shovel";
} }
case TOOL_HOE: case TOOL_HOE:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Hoe"; case 1: return "Rock Hoe";
case 2: return "Iron Hoe"; case 2: return "Iron Hoe";
case 3: return "Gold Hoe"; case 3: return "Gold Hoe";
case 4: return "Gem Hoe"; case 4: return "Gem Hoe";
default: return "Wood Hoe"; default: return "Wood Hoe";
} }
case TOOL_SWORD: case TOOL_SWORD:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Sword"; case 1: return "Rock Sword";
case 2: return "Iron Sword"; case 2: return "Iron Sword";
case 3: return "Gold Sword"; case 3: return "Gold Sword";
case 4: return "Gem Sword"; case 4: return "Gem Sword";
default: return "Wood Sword"; default: return "Wood Sword";
} }
case TOOL_PICKAXE: case TOOL_PICKAXE:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Pickaxe"; case 1: return "Rock Pickaxe";
case 2: return "Iron Pickaxe"; case 2: return "Iron Pickaxe";
case 3: return "Gold Pickaxe"; case 3: return "Gold Pickaxe";
case 4: return "Gem Pickaxe"; case 4: return "Gem Pickaxe";
default: return "Wood Pickaxe"; default: return "Wood Pickaxe";
} }
case TOOL_AXE: case TOOL_AXE:
switch(countLevel){ switch(countLevel){
case 1: return "Rock Axe"; case 1: return "Rock Axe";
case 2: return "Iron Axe"; case 2: return "Iron Axe";
case 3: return "Gold Axe"; case 3: return "Gold Axe";
case 4: return "Gem Axe"; case 4: return "Gem Axe";
default: return "Wood Axe"; default: return "Wood Axe";
} }
case ITEM_ANVIL: return "Anvil"; case ITEM_ANVIL: return "Anvil";
case ITEM_CHEST: return "Chest"; case ITEM_CHEST: return "Chest";
case ITEM_OVEN: return "Oven"; case ITEM_OVEN: return "Oven";
case ITEM_FURNACE: return "Furnace"; case ITEM_FURNACE: return "Furnace";
case ITEM_WORKBENCH: return "Workbench"; case ITEM_WORKBENCH: return "Workbench";
case ITEM_POTION_MAKER: return "Potion Maker"; case ITEM_POTION_MAKER: return "Potion Maker";
case ITEM_LANTERN: return "Lantern"; case ITEM_LANTERN: return "Lantern";
case ITEM_POWGLOVE: return "Power Glove"; case ITEM_POWGLOVE: return "Power Glove";
case ITEM_FLOWER: return "Flower"; case ITEM_FLOWER: return "Flower";
case ITEM_WOOD: return "Wood"; case ITEM_WOOD: return "Wood";
case ITEM_STONE: return "Stone"; case ITEM_STONE: return "Stone";
case ITEM_SAND: return "Sand"; case ITEM_SAND: return "Sand";
case ITEM_DIRT: return "Dirt"; case ITEM_DIRT: return "Dirt";
case ITEM_CLOUD: return "Cloud"; case ITEM_CLOUD: return "Cloud";
case ITEM_ACORN: return "Acorn"; case ITEM_ACORN: return "Acorn";
case ITEM_CACTUS: return "Cactus"; case ITEM_CACTUS: return "Cactus";
case ITEM_SEEDS: return "Seeds"; case ITEM_SEEDS: return "Seeds";
case ITEM_WHEAT: return "Wheat"; case ITEM_WHEAT: return "Wheat";
case ITEM_FLESH: return "Flesh"; case ITEM_FLESH: return "Flesh";
case ITEM_BREAD: return "Bread"; case ITEM_BREAD: return "Bread";
case ITEM_APPLE: return "Apple"; case ITEM_APPLE: return "Apple";
case ITEM_GOLD_APPLE: return "Gold Apple"; case ITEM_GOLD_APPLE: return "Gold Apple";
case ITEM_COAL: return "Coal"; case ITEM_COAL: return "Coal";
case ITEM_IRONORE: return "Iron ore"; case ITEM_IRONORE: return "Iron ore";
case ITEM_GOLDORE: return "Gold ore"; case ITEM_GOLDORE: return "Gold ore";
case ITEM_IRONINGOT: return "Iron ingot"; case ITEM_IRONINGOT: return "Iron ingot";
case ITEM_GOLDINGOT: return "Gold ingot"; case ITEM_GOLDINGOT: return "Gold ingot";
case ITEM_GLASS: return "Glass"; case ITEM_GLASS: return "Glass";
case ITEM_GEM: return "Gem"; case ITEM_GEM: return "Gem";
case ITEM_SLIME: return "Slime"; case ITEM_SLIME: return "Slime";
case ITEM_LOOM: return "Loom"; case ITEM_LOOM: return "Loom";
case ITEM_ENCHANTER: return "Enchanter"; case ITEM_ENCHANTER: return "Enchanter";
@ -302,21 +302,21 @@ char* getBasicItemName(int itemID, int countLevel) {
case ITEM_DRAGON_EGG: return "Dragon Egg"; case ITEM_DRAGON_EGG: return "Dragon Egg";
case ITEM_DRAGON_SCALE: return "Dragon Scale"; case ITEM_DRAGON_SCALE: return "Dragon Scale";
case ITEM_BOOKSHELVES: return "Bookshelves"; case ITEM_BOOKSHELVES: return "Bookshelves";
case ITEM_MAGIC_DUST: return "Magic Dust"; case ITEM_MAGIC_DUST: return "Magic Dust";
case ITEM_COIN: return "Coin"; case ITEM_COIN: return "Coin";
case ITEM_STRENGTH_POTION: return "Strength Potion"; case ITEM_STRENGTH_POTION: return "Strength Potion";
case ITEM_SPEED_POTION: return "Speed Potion"; case ITEM_SPEED_POTION: return "Speed Potion";
case ITEM_REGEN_POTION: return "Regen Potion"; case ITEM_REGEN_POTION: return "Regen Potion";
case ITEM_SWIM_BREATH_POTION: return "Water Potion"; case ITEM_SWIM_BREATH_POTION: return "Water Potion";
case TOOL_BUCKET: case TOOL_BUCKET:
switch(countLevel){ switch(countLevel){
case 1: return "Water Bucket"; case 1: return "Water Bucket";
case 2: return "Lava Bucket"; case 2: return "Lava Bucket";
default: return "Empty Bucket"; default: return "Empty Bucket";
} }
case TOOL_BOW: return "Bow"; case TOOL_BOW: return "Bow";
case TOOL_MAGIC_COMPASS: return "Magic Compass"; case TOOL_MAGIC_COMPASS: return "Magic Compass";
default: return ""; // null default: return ""; // null
} }
} }

View file

@ -87,17 +87,17 @@
typedef struct Inventory Inventory; typedef struct Inventory Inventory;
typedef struct { typedef struct {
s16 id; s16 id;
s16 countLevel; // Count for items, Level for tools. s16 countLevel; // Count for items, Level for tools.
s16 slotNum; // Read-only. Do not mess with this. s16 slotNum; // Read-only. Do not mess with this.
bool onlyOne; bool onlyOne;
int* invPtr; // pointer to current inventory. int* invPtr; // pointer to current inventory.
Inventory * chestPtr; // pointer to chest inventory for chest item. Inventory * chestPtr; // pointer to chest inventory for chest item.
} Item; } Item;
struct Inventory { struct Inventory {
Item items[300]; // Maximum of 300 slots in every inventory. Item items[300]; // Maximum of 300 slots in every inventory.
s16 lastSlot; // lastSlot can also be used to read the size of the inventory. s16 lastSlot; // lastSlot can also be used to read the size of the inventory.
}; };
bool isItemEmpty(Item* item); bool isItemEmpty(Item* item);

View file

@ -7,7 +7,7 @@ u8 randomTile[] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 2};
int randomTileSize = 10; int randomTileSize = 10;
float nextFloat(){ float nextFloat(){
return (float)rand()/RAND_MAX; return (float)rand()/RAND_MAX;
} }
double sample(double * values, int x, int y) { double sample(double * values, int x, int y) {
@ -15,66 +15,66 @@ double sample(double * values, int x, int y) {
} }
double * Noise(int width, int height, int featureSize) { double * Noise(int width, int height, int featureSize) {
w = width; w = width;
h = height; h = height;
double * values = malloc(sizeof(double) * w * h); double * values = malloc(sizeof(double) * w * h);
int x, y; int x, y;
for(x = 0; x < w; x+=featureSize){ for(x = 0; x < w; x+=featureSize){
for(y = 0; y < w; y+=featureSize){ for(y = 0; y < w; y+=featureSize){
values[(x & (w - 1)) + (y & (h - 1)) * w] = nextFloat() * 2 - 1; values[(x & (w - 1)) + (y & (h - 1)) * w] = nextFloat() * 2 - 1;
} }
} }
int stepSize = featureSize; int stepSize = featureSize;
double scale = 1.0 / w; double scale = 1.0 / w;
double scaleMod = 1; double scaleMod = 1;
do { do {
int halfStep = stepSize / 2; int halfStep = stepSize / 2;
for(x = 0; x < w; x+=stepSize){ for(x = 0; x < w; x+=stepSize){
for(y = 0; y < w; y+=stepSize){ for(y = 0; y < w; y+=stepSize){
double a = sample(values,x, y); double a = sample(values,x, y);
double b = sample(values,x + stepSize, y); double b = sample(values,x + stepSize, y);
double c = sample(values,x, y + stepSize); double c = sample(values,x, y + stepSize);
double d = sample(values,x + stepSize, y + stepSize); double d = sample(values,x + stepSize, y + stepSize);
double e = (a + b + c + d) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale; double e = (a + b + c + d) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale;
values[((x + halfStep) & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = e; values[((x + halfStep) & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = e;
} }
} }
for(x = 0; x < w; x+=stepSize){ for(x = 0; x < w; x+=stepSize){
for(y = 0; y < w; y+=stepSize){ for(y = 0; y < w; y+=stepSize){
double a = sample(values,x, y); double a = sample(values,x, y);
double b = sample(values,x + stepSize, y); double b = sample(values,x + stepSize, y);
double c = sample(values,x, y + stepSize); double c = sample(values,x, y + stepSize);
double d = sample(values,x + halfStep, y + halfStep); double d = sample(values,x + halfStep, y + halfStep);
double e = sample(values,x + halfStep, y - halfStep); double e = sample(values,x + halfStep, y - halfStep);
double f = sample(values,x - halfStep, y + halfStep); double f = sample(values,x - halfStep, y + halfStep);
double H = (a + b + d + e) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5; double H = (a + b + d + e) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5;
double g = (a + c + d + f) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5; double g = (a + c + d + f) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5;
values[((x + halfStep) & (w - 1)) + (y & (h - 1)) * w] = H; values[((x + halfStep) & (w - 1)) + (y & (h - 1)) * w] = H;
values[(x & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = g; values[(x & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = g;
} }
} }
stepSize /= 2; stepSize /= 2;
scale *= (scaleMod + 0.8); scale *= (scaleMod + 0.8);
scaleMod *= 0.3; scaleMod *= 0.3;
} while (stepSize > 1); } while (stepSize > 1);
return values; return values;
} }
//TODO: Will need to reset entity manager if generation is retried //TODO: Will need to reset entity manager if generation is retried
void createAndValidateTopMap(int w, int h, int level, u8 * map, u8 * data) { void createAndValidateTopMap(int w, int h, int level, u8 * map, u8 * data) {
do { do {
//reset Entities //reset Entities
(&eManager)->lastSlot[level] = 0; (&eManager)->lastSlot[level] = 0;
(&eManager)->entities[level][0] = nullEntity; (&eManager)->entities[level][0] = nullEntity;
createTopMap(w, h, level, map, data); createTopMap(w, h, level, map, data);
int count[256]={[0 ... 255] = 0}; int count[256]={[0 ... 255] = 0};
int i; int i;
for (i = 0; i < w * h; ++i) count[map[i] & 0xff]++; for (i = 0; i < w * h; ++i) count[map[i] & 0xff]++;
if (count[TILE_ROCK & 0xff] < 100) continue; if (count[TILE_ROCK & 0xff] < 100) continue;
if (count[TILE_SAND & 0xff] < 100) continue; if (count[TILE_SAND & 0xff] < 100) continue;
if (count[TILE_GRASS & 0xff] < 100) continue; if (count[TILE_GRASS & 0xff] < 100) continue;
@ -88,21 +88,21 @@ void createAndValidateTopMap(int w, int h, int level, u8 * map, u8 * data) {
void createAndValidateUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) { void createAndValidateUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) {
do { do {
//reset Entities //reset Entities
(&eManager)->lastSlot[level] = 0; (&eManager)->lastSlot[level] = 0;
(&eManager)->entities[level][0] = nullEntity; (&eManager)->entities[level][0] = nullEntity;
createUndergroundMap(w, h, depthLevel, level, map, data); createUndergroundMap(w, h, depthLevel, level, map, data);
int count[256]={[0 ... 255] = 0}; int count[256]={[0 ... 255] = 0};
int i = 0; int i = 0;
for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++;
if (count[TILE_ROCK & 0xff] < 100) continue; if (count[TILE_ROCK & 0xff] < 100) continue;
if (count[TILE_DIRT & 0xff] < 100) continue; if (count[TILE_DIRT & 0xff] < 100) continue;
switch(depthLevel){ switch(depthLevel){
case 1: if (count[TILE_IRONORE & 0xff] < 20) continue; break; case 1: if (count[TILE_IRONORE & 0xff] < 20) continue; break;
case 2: if (count[TILE_GOLDORE & 0xff] < 20 || count[TILE_MYCELIUM & 0xff] < 40) continue; break; case 2: if (count[TILE_GOLDORE & 0xff] < 20 || count[TILE_MYCELIUM & 0xff] < 40) continue; break;
case 3: if (count[TILE_GEMORE & 0xff] < 20) continue; break; case 3: if (count[TILE_GEMORE & 0xff] < 20) continue; break;
} }
if (depthLevel < 3) if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue; if (depthLevel < 3) if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue;
return; return;
@ -112,14 +112,14 @@ void createAndValidateUndergroundMap(int w, int h, int depthLevel, int level, u8
void createAndValidateDungeonMap(int w, int h, int level, u8 * map, u8 * data) { void createAndValidateDungeonMap(int w, int h, int level, u8 * map, u8 * data) {
do { do {
//reset Entities //reset Entities
(&eManager)->lastSlot[level] = 0; (&eManager)->lastSlot[level] = 0;
(&eManager)->entities[level][0] = nullEntity; (&eManager)->entities[level][0] = nullEntity;
createDungeonMap(w, h, level, map, data); createDungeonMap(w, h, level, map, data);
int count[256]={[0 ... 255] = 0}; int count[256]={[0 ... 255] = 0};
int i = 0; int i = 0;
for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++;
if (count[TILE_DUNGEON_WALL & 0xff] < 100) continue; if (count[TILE_DUNGEON_WALL & 0xff] < 100) continue;
if (count[TILE_DUNGEON_FLOOR & 0xff] < 100) continue; if (count[TILE_DUNGEON_FLOOR & 0xff] < 100) continue;
@ -130,14 +130,14 @@ void createAndValidateDungeonMap(int w, int h, int level, u8 * map, u8 * data) {
void createAndValidateSkyMap(int w, int h, int level, u8 * map, u8 * data) { void createAndValidateSkyMap(int w, int h, int level, u8 * map, u8 * data) {
do { do {
//reset Entities //reset Entities
(&eManager)->lastSlot[level] = 0; (&eManager)->lastSlot[level] = 0;
(&eManager)->entities[level][0] = nullEntity; (&eManager)->entities[level][0] = nullEntity;
createSkyMap(w, h, level, map, data); createSkyMap(w, h, level, map, data);
int count[256]={[0 ... 255] = 0}; int count[256]={[0 ... 255] = 0};
int i = 0; int i = 0;
for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++;
if (count[TILE_CLOUD & 0xff] < 1600) continue; if (count[TILE_CLOUD & 0xff] < 1600) continue;
if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue; if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue;
@ -157,8 +157,8 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) {
int x,y,i,j,k,xx,yy; int x,y,i,j,k,xx,yy;
for(x = 0; x < w; ++x){ for(x = 0; x < w; ++x){
for(y = 0; y < w; ++y){ for(y = 0; y < w; ++y){
int i = x + y * w; int i = x + y * w;
double val = fabs(noise1[i] - noise2[i]) * 3 - 2; double val = fabs(noise1[i] - noise2[i]) * 3 - 2;
double mval = fabs(mnoise1[i] - mnoise2[i]); double mval = fabs(mnoise1[i] - mnoise2[i]);
@ -180,10 +180,10 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) {
} else { } else {
map[i] = TILE_GRASS; map[i] = TILE_GRASS;
} }
} }
} }
for (i = 0; i < w * h / 2800; ++i) { for (i = 0; i < w * h / 2800; ++i) {
int xs = rand()%w; int xs = rand()%w;
int ys = rand()%h; int ys = rand()%h;
for (k = 0; k < 10; ++k) { for (k = 0; k < 10; ++k) {
@ -192,18 +192,18 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) {
for (j = 0; j < 100; ++j) { for (j = 0; j < 100; ++j) {
int xo = x + (rand()%5) - (rand()%5); int xo = x + (rand()%5) - (rand()%5);
int yo = y + (rand()%5) - (rand()%5); int yo = y + (rand()%5) - (rand()%5);
for (yy = yo - 1;yy <= yo + 1; ++yy){ for (yy = yo - 1;yy <= yo + 1; ++yy){
for(xx = xo - 1; xx <= xo + 1; ++xx){ for(xx = xo - 1; xx <= xo + 1; ++xx){
if (xx >= 0 && yy >= 0 && xx < w && yy < h) if (map[xx + yy * w] == TILE_GRASS) map[xx + yy * w] = TILE_SAND; if (xx >= 0 && yy >= 0 && xx < w && yy < h) if (map[xx + yy * w] == TILE_GRASS) map[xx + yy * w] = TILE_SAND;
} }
} }
} }
} }
} }
createVillage(w, h, level, map, data); createVillage(w, h, level, map, data);
for (i = 0; i < w * h / 400; ++i) { for (i = 0; i < w * h / 400; ++i) {
x = rand()%w; x = rand()%w;
y = rand()%h; y = rand()%h;
for (j = 0; j < 200; ++j) { for (j = 0; j < 200; ++j) {
@ -217,7 +217,7 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) {
} }
} }
for (i = 0; i < w * h / 800; ++i) { for (i = 0; i < w * h / 800; ++i) {
x = rand()%w; x = rand()%w;
y = rand()%h; y = rand()%h;
for (j = 0; j < 30;++j) { for (j = 0; j < 30;++j) {
@ -243,13 +243,13 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) {
} }
} }
int sCount, attempts = 0; int sCount, attempts = 0;
for (sCount = 0; sCount < 4;) { for (sCount = 0; sCount < 4;) {
xx = rand()%w; xx = rand()%w;
yy = rand()%h; yy = rand()%h;
if (xx >= 0 && yy >= 0 && xx < w && yy < h) { if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_ROCK) if (map[xx + yy * w] == TILE_ROCK)
{ {
map[xx + yy * w] = TILE_STAIRS_DOWN; map[xx + yy * w] = TILE_STAIRS_DOWN;
map[xx + (yy+1) * w] = TILE_ROCK; map[xx + (yy+1) * w] = TILE_ROCK;
map[(xx+1) + yy * w] = TILE_ROCK; map[(xx+1) + yy * w] = TILE_ROCK;
@ -259,17 +259,17 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) {
map[(xx+1) + (yy+1) * w] = TILE_ROCK; map[(xx+1) + (yy+1) * w] = TILE_ROCK;
map[(xx+1) + (yy-1) * w] = TILE_ROCK; map[(xx+1) + (yy-1) * w] = TILE_ROCK;
map[(xx-1) + (yy+1) * w] = TILE_ROCK; map[(xx-1) + (yy+1) * w] = TILE_ROCK;
++sCount; ++sCount;
} }
} }
if(attempts < (w*h/100)) ++attempts; else break; if(attempts < (w*h/100)) ++attempts; else break;
} }
free(mnoise1); free(mnoise1);
free(mnoise2); free(mnoise2);
free(mnoise3); free(mnoise3);
free(noise1); free(noise1);
free(noise2); free(noise2);
return; return;
} }
void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) { void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) {
@ -291,8 +291,8 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8
int x,y,i,j,k,xx,yy; int x,y,i,j,k,xx,yy;
for(x = 0; x < w; ++x){ for(x = 0; x < w; ++x){
for(y = 0; y < w; ++y){ for(y = 0; y < w; ++y){
int i = x + y * w; int i = x + y * w;
double val = fabs(noise1[i] - noise2[i]) * 3 - 2; double val = fabs(noise1[i] - noise2[i]) * 3 - 2;
@ -324,43 +324,43 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8
} else { } else {
map[i] = TILE_ROCK; map[i] = TILE_ROCK;
} }
} }
} }
//generate dwarf house //generate dwarf house
if(depthLevel==3) { if(depthLevel==3) {
createDwarfHouse(w, h, level, map, data); createDwarfHouse(w, h, level, map, data);
//generate mushroom patches //generate mushroom patches
} else if(depthLevel==2) { } else if(depthLevel==2) {
for (i = 0; i < w * h / 5400; ++i) { for (i = 0; i < w * h / 5400; ++i) {
int xs = rand()%w; int xs = rand()%w;
int ys = rand()%h; int ys = rand()%h;
for (k = 0; k < 10; ++k) { for (k = 0; k < 10; ++k) {
x = xs + (rand()%13) - 6; x = xs + (rand()%13) - 6;
y = ys + (rand()%13) - 6; y = ys + (rand()%13) - 6;
for (j = 0; j < 100; ++j) { for (j = 0; j < 100; ++j) {
int xo = x + (rand()%5) - (rand()%5); int xo = x + (rand()%5) - (rand()%5);
int yo = y + (rand()%5) - (rand()%5); int yo = y + (rand()%5) - (rand()%5);
for (yy = yo - 1;yy <= yo + 1; ++yy){ for (yy = yo - 1;yy <= yo + 1; ++yy){
for(xx = xo - 1; xx <= xo + 1; ++xx){ for(xx = xo - 1; xx <= xo + 1; ++xx){
if (xx >= 0 && yy >= 0 && xx < w && yy < h) { if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_DIRT) { if (map[xx + yy * w] == TILE_DIRT) {
map[xx + yy * w] = TILE_MYCELIUM; map[xx + yy * w] = TILE_MYCELIUM;
if(rand()%20==0) { if(rand()%20==0) {
map[xx + yy * w] = TILE_MUSHROOM_BROWN + rand()%2; //BROWN or RED (=BROWN+1) map[xx + yy * w] = TILE_MUSHROOM_BROWN + rand()%2; //BROWN or RED (=BROWN+1)
data[xx + yy * w] = rand()%2; data[xx + yy * w] = rand()%2;
} }
} }
} }
} }
} }
} }
} }
} }
} }
//generate ores //generate ores
for (i = 0; i < w * h / 400; ++i) { for (i = 0; i < w * h / 400; ++i) {
int x = rand()%w; int x = rand()%w;
int y = rand()%h; int y = rand()%h;
for(j = 0; j < 30; ++j) { for(j = 0; j < 30; ++j) {
@ -374,14 +374,14 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8
} }
} }
//generate stairs down //generate stairs down
if (depthLevel < 3){ if (depthLevel < 3){
int sCount, attempts = 0; int sCount, attempts = 0;
for (sCount = 0; sCount < 4;) { for (sCount = 0; sCount < 4;) {
int xx = rand()%w; int xx = rand()%w;
int yy = rand()%h; int yy = rand()%h;
if (xx >= 0 && yy >= 0 && xx < w && yy < h) { if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == TILE_ROCK){ if (map[xx + yy * w] == TILE_ROCK){
map[xx + yy * w] = TILE_STAIRS_DOWN; map[xx + yy * w] = TILE_STAIRS_DOWN;
map[xx + (yy+1) * w] = TILE_ROCK; map[xx + (yy+1) * w] = TILE_ROCK;
map[(xx+1) + yy * w] = TILE_ROCK; map[(xx+1) + yy * w] = TILE_ROCK;
@ -392,43 +392,43 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8
map[(xx+1) + (yy-1) * w] = TILE_ROCK; map[(xx+1) + (yy-1) * w] = TILE_ROCK;
map[(xx-1) + (yy+1) * w] = TILE_ROCK; map[(xx-1) + (yy+1) * w] = TILE_ROCK;
++sCount; ++sCount;
} }
} }
if(attempts < (w*h/100)) ++attempts; else break; if(attempts < (w*h/100)) ++attempts; else break;
} }
} }
//generate dungeon entrance //generate dungeon entrance
if(depthLevel==3) { if(depthLevel==3) {
map[w/2+0 + (h/2+0) * w] = TILE_DUNGEON_ENTRANCE; map[w/2+0 + (h/2+0) * w] = TILE_DUNGEON_ENTRANCE;
map[w/2-1 + (h/2+0) * w] = TILE_DIRT; map[w/2-1 + (h/2+0) * w] = TILE_DIRT;
map[w/2+1 + (h/2+0) * w] = TILE_DIRT; map[w/2+1 + (h/2+0) * w] = TILE_DIRT;
map[w/2+0 + (h/2-1) * w] = TILE_DIRT; map[w/2+0 + (h/2-1) * w] = TILE_DIRT;
map[w/2+1 + (h/2+1) * w] = TILE_DIRT; map[w/2+1 + (h/2+1) * w] = TILE_DIRT;
map[w/2-1 + (h/2-1) * w] = TILE_DUNGEON_WALL; map[w/2-1 + (h/2-1) * w] = TILE_DUNGEON_WALL;
map[w/2-1 + (h/2+1) * w] = TILE_DUNGEON_WALL; map[w/2-1 + (h/2+1) * w] = TILE_DUNGEON_WALL;
map[w/2+1 + (h/2-1) * w] = TILE_DUNGEON_WALL; map[w/2+1 + (h/2-1) * w] = TILE_DUNGEON_WALL;
map[w/2+1 + (h/2+1) * w] = TILE_DUNGEON_WALL; map[w/2+1 + (h/2+1) * w] = TILE_DUNGEON_WALL;
} }
free(mnoise1); free(mnoise1);
free(mnoise2); free(mnoise2);
free(mnoise3); free(mnoise3);
free(nnoise1); free(nnoise1);
free(nnoise2); free(nnoise2);
free(nnoise3); free(nnoise3);
free(wnoise1); free(wnoise1);
free(wnoise2); free(wnoise2);
free(wnoise3); free(wnoise3);
free(noise1); free(noise1);
free(noise2); free(noise2);
} }
void createDungeonMap(int w, int h, int level, u8 * map, u8 * data) { void createDungeonMap(int w, int h, int level, u8 * map, u8 * data) {
hasNPC = false; hasNPC = false;
int i, x, y; int i, x, y;
for(x = 0; x < w; ++x){ for(x = 0; x < w; ++x){
@ -438,10 +438,10 @@ void createDungeonMap(int w, int h, int level, u8 * map, u8 * data) {
//Startroom //Startroom
if (x >= (w/2-5) && x <= (w/2+5) && y >= (h/2-5) && y <= (h/2+5) ) { if (x >= (w/2-5) && x <= (w/2+5) && y >= (h/2-5) && y <= (h/2+5) ) {
map[i] = TILE_DUNGEON_FLOOR; map[i] = TILE_DUNGEON_FLOOR;
data[i] = randomTile[rand()%randomTileSize]; data[i] = randomTile[rand()%randomTileSize];
} else { } else {
map[i] = TILE_DUNGEON_WALL; map[i] = TILE_DUNGEON_WALL;
data[i] = 0; data[i] = 0;
} }
} }
} }
@ -460,7 +460,7 @@ void createDungeonMap(int w, int h, int level, u8 * map, u8 * data) {
if (map[i]==255) { if (map[i]==255) {
map[i] = TILE_DUNGEON_FLOOR; map[i] = TILE_DUNGEON_FLOOR;
data[i] = randomTile[rand()%randomTileSize]; data[i] = randomTile[rand()%randomTileSize];
} }
} }
} }
@ -541,186 +541,186 @@ void createSkyMap(int w, int h, int level, u8 * map, u8 * data) {
//"Subgenerators" //"Subgenerators"
void findFeatureLocation(int fw, int fh, int * accepted, int aLength, int maxTries, int w, int h, u8 * map, u8 * data) { void findFeatureLocation(int fw, int fh, int * accepted, int aLength, int maxTries, int w, int h, u8 * map, u8 * data) {
int leastNonFitting = fw * fh; int leastNonFitting = fw * fh;
int tries; int tries;
//find the location with the least non fitting tiles out of some randomly tried ones //find the location with the least non fitting tiles out of some randomly tried ones
for(tries=0; tries<maxTries; ++tries) { for(tries=0; tries<maxTries; ++tries) {
int x = rand()%(w-fw); int x = rand()%(w-fw);
int y = rand()%(h-fh); int y = rand()%(h-fh);
int nonFitting = 0; int nonFitting = 0;
int xp; int xp;
int yp; int yp;
int i; int i;
int a; int a;
bool fits; bool fits;
for(xp=x; xp<x+fw; ++xp) { for(xp=x; xp<x+fw; ++xp) {
for(yp=y; yp<y+fh; ++yp) { for(yp=y; yp<y+fh; ++yp) {
i = xp + yp * w; i = xp + yp * w;
fits = false; fits = false;
for(a=0; a<aLength; ++a) { for(a=0; a<aLength; ++a) {
if(map[i]==accepted[a]) { if(map[i]==accepted[a]) {
fits = true; fits = true;
break; break;
} }
} }
if(!fits) { if(!fits) {
nonFitting++; nonFitting++;
} }
} }
} }
if(nonFitting<leastNonFitting) { if(nonFitting<leastNonFitting) {
featureX = x; featureX = x;
featureY = y; featureY = y;
leastNonFitting = nonFitting; leastNonFitting = nonFitting;
} }
} }
} }
void createVillageHouse(int hid, int x, int y, int hw, int hh, int ex, int ey, int w, int h, int level, u8 * map, u8 * data) { void createVillageHouse(int hid, int x, int y, int hw, int hh, int ex, int ey, int w, int h, int level, u8 * map, u8 * data) {
//create wall and floor //create wall and floor
int xp = x; int xp = x;
int yp = y; int yp = y;
for(xp=x; xp<x+hw; ++xp) { for(xp=x; xp<x+hw; ++xp) {
for(yp=y; yp<y+hh; ++yp) { for(yp=y; yp<y+hh; ++yp) {
if(xp==x || xp==x+hw-1 || yp==y || yp==y+hh-1) map[xp + yp * w] = TILE_WOOD_WALL; if(xp==x || xp==x+hw-1 || yp==y || yp==y+hh-1) map[xp + yp * w] = TILE_WOOD_WALL;
else map[xp + yp * w] = TILE_WOOD_FLOOR; else map[xp + yp * w] = TILE_WOOD_FLOOR;
} }
} }
//recreate entrance //recreate entrance
map[ex + ey * w] = TILE_WOOD_FLOOR; map[ex + ey * w] = TILE_WOOD_FLOOR;
//create npcs //create npcs
if(hid==0) { if(hid==0) {
addEntityToList(newNPCEntity(NPC_GIRL, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager); addEntityToList(newNPCEntity(NPC_GIRL, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager);
} else if(hid==1) { } else if(hid==1) {
addEntityToList(newNPCEntity(NPC_PRIEST, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager); addEntityToList(newNPCEntity(NPC_PRIEST, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager);
} else if(hid==2) { } else if(hid==2) {
addEntityToList(newNPCEntity(NPC_FARMER, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager); addEntityToList(newNPCEntity(NPC_FARMER, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager);
//TODO: maybe create farm? //TODO: maybe create farm?
for(xp=x; xp<x+hw; ++xp) { for(xp=x; xp<x+hw; ++xp) {
map[xp + yp * w] = TILE_WHEAT; map[xp + yp * w] = TILE_WHEAT;
map[xp + (yp+1) * w] = TILE_WHEAT; map[xp + (yp+1) * w] = TILE_WHEAT;
} }
} }
//add Latern Entity //add Latern Entity
int loffx = -12; int loffx = -12;
int loffy = -12; int loffy = -12;
if(hid==2) loffx = 12; if(hid==2) loffx = 12;
addEntityToList(newFurnitureEntity(ITEM_LANTERN, NULL, ((x+hw/2) << 4) + loffx, ((y+hh/2) << 4) + loffy, level), &eManager); addEntityToList(newFurnitureEntity(ITEM_LANTERN, NULL, ((x+hw/2) << 4) + loffx, ((y+hh/2) << 4) + loffy, level), &eManager);
} }
void createVillage(int w, int h, int level, u8 * map, u8 * data) { void createVillage(int w, int h, int level, u8 * map, u8 * data) {
int vw = 17; int vw = 17;
int vh = 17; int vh = 17;
int accepted[] = {TILE_GRASS}; int accepted[] = {TILE_GRASS};
findFeatureLocation(vw, vh, accepted, 1, 500, w, h, map, data); findFeatureLocation(vw, vh, accepted, 1, 500, w, h, map, data);
int x = featureX; int x = featureX;
int y = featureY; int y = featureY;
int cx = x + vw/2; int cx = x + vw/2;
int cy = y + vh/2; int cy = y + vh/2;
int px; int px;
int py; int py;
int hw; int hw;
int hh; int hh;
int hx; int hx;
int hy; int hy;
int ex; int ex;
int ey; int ey;
//"well" in the middle //"well" in the middle
map[(cx-1) + (cy-1) * w] = TILE_SAND; map[(cx-1) + (cy-1) * w] = TILE_SAND;
map[(cx+0) + (cy-1) * w] = TILE_SAND; map[(cx+0) + (cy-1) * w] = TILE_SAND;
map[(cx+1) + (cy-1) * w] = TILE_SAND; map[(cx+1) + (cy-1) * w] = TILE_SAND;
map[(cx-1) + (cy+0) * w] = TILE_SAND; map[(cx-1) + (cy+0) * w] = TILE_SAND;
map[(cx+0) + (cy+0) * w] = TILE_WATER; map[(cx+0) + (cy+0) * w] = TILE_WATER;
map[(cx+1) + (cy+0) * w] = TILE_SAND; map[(cx+1) + (cy+0) * w] = TILE_SAND;
map[(cx-1) + (cy+1) * w] = TILE_SAND; map[(cx-1) + (cy+1) * w] = TILE_SAND;
map[(cx+0) + (cy+1) * w] = TILE_SAND; map[(cx+0) + (cy+1) * w] = TILE_SAND;
map[(cx+1) + (cy+1) * w] = TILE_SAND; map[(cx+1) + (cy+1) * w] = TILE_SAND;
//"paths" outwards leading to the "houses" //"paths" outwards leading to the "houses"
//left //left
px = cx-1; px = cx-1;
py = cy-1 + rand()%3; py = cy-1 + rand()%3;
while(px>x) { while(px>x) {
map[px + py * w] = TILE_SAND; map[px + py * w] = TILE_SAND;
--px; --px;
} }
hw = 4 + rand()%2; hw = 4 + rand()%2;
hh = 4 + rand()%2; hh = 4 + rand()%2;
hx = px + 1; hx = px + 1;
hy = py - hh + 2 + rand()%(hh-2); hy = py - hh + 2 + rand()%(hh-2);
ex = px + hw; ex = px + hw;
ey = py; ey = py;
createVillageHouse(0, hx, hy, hw, hh, ex, ey, w, h, level, map, data); createVillageHouse(0, hx, hy, hw, hh, ex, ey, w, h, level, map, data);
//top //top
px = cx-1 + rand()%3; px = cx-1 + rand()%3;
py = cy-1; py = cy-1;
while(py>y) { while(py>y) {
map[px + py * w] = TILE_SAND; map[px + py * w] = TILE_SAND;
--py; --py;
} }
hw = 5 + rand()%2; hw = 5 + rand()%2;
hh = 4 + rand()%2; hh = 4 + rand()%2;
hx = px - hw + 2 + rand()%(hw-2); hx = px - hw + 2 + rand()%(hw-2);
hy = py + 1; hy = py + 1;
ex = px; ex = px;
ey = py+hh; ey = py+hh;
createVillageHouse(1, hx, hy, hw, hh, ex, ey, w, h, level, map, data); createVillageHouse(1, hx, hy, hw, hh, ex, ey, w, h, level, map, data);
//right //right
px = cx+1; px = cx+1;
py = cy-1 + rand()%3; py = cy-1 + rand()%3;
while(px<x+vw) { while(px<x+vw) {
map[px + py * w] = TILE_SAND; map[px + py * w] = TILE_SAND;
++px; ++px;
} }
hw = 4 + rand()%2; hw = 4 + rand()%2;
hh = 4 + rand()%2; hh = 4 + rand()%2;
hx = px - hw; hx = px - hw;
hy = py - hh + 2 + rand()%(hh-2); hy = py - hh + 2 + rand()%(hh-2);
ex = px - hw; ex = px - hw;
ey = py; ey = py;
createVillageHouse(2, hx, hy, hw, hh, ex, ey, w, h, level, map, data); createVillageHouse(2, hx, hy, hw, hh, ex, ey, w, h, level, map, data);
} }
void createDwarfHouse(int w, int h, int level, u8 * map, u8 * data) { void createDwarfHouse(int w, int h, int level, u8 * map, u8 * data) {
int vw = 7; int vw = 7;
int vh = 7; int vh = 7;
int accepted[] = {TILE_ROCK}; int accepted[] = {TILE_ROCK};
findFeatureLocation(vw, vh, accepted, 1, 500, w, h, map, data); findFeatureLocation(vw, vh, accepted, 1, 500, w, h, map, data);
int x = featureX; int x = featureX;
int y = featureY; int y = featureY;
int xp; int xp;
int yp; int yp;
for(xp=x; xp<x+vw; ++xp) { for(xp=x; xp<x+vw; ++xp) {
for(yp=y; yp<y+vh; ++yp) { for(yp=y; yp<y+vh; ++yp) {
if(xp==x || xp==x+vw-1 || yp==y || yp==y+vh-1) map[xp + yp * w] = TILE_STONE_WALL; if(xp==x || xp==x+vw-1 || yp==y || yp==y+vh-1) map[xp + yp * w] = TILE_STONE_WALL;
else map[xp + yp * w] = TILE_DIRT; else map[xp + yp * w] = TILE_DIRT;
} }
} }
//entrance //entrance
xp = x+vw/2; xp = x+vw/2;
map[xp + (yp-1) * w] = TILE_DIRT; map[xp + (yp-1) * w] = TILE_DIRT;
//pillars //pillars
map[(x+2) + (y+2) * w] = TILE_STONE_WALL; map[(x+2) + (y+2) * w] = TILE_STONE_WALL;
map[(x+vw-1-2) + (y+2) * w] = TILE_STONE_WALL; map[(x+vw-1-2) + (y+2) * w] = TILE_STONE_WALL;
addEntityToList(newNPCEntity(NPC_DWARF, ((x+vw/2) << 4) + 8, (y+vh/2) << 4, level), &eManager); addEntityToList(newNPCEntity(NPC_DWARF, ((x+vw/2) << 4) + 8, (y+vh/2) << 4, level), &eManager);
addEntityToList(newFurnitureEntity(ITEM_LANTERN, NULL, (x+1+1) << 4, (y+1+3) << 4, level), &eManager); addEntityToList(newFurnitureEntity(ITEM_LANTERN, NULL, (x+1+1) << 4, (y+1+3) << 4, level), &eManager);
@ -774,7 +774,7 @@ void createDungeonRoom(int w, int h, bool dragon, int level, u8 * map, u8 * data
i = xr + yr * w; i = xr + yr * w;
map[i] = TILE_DUNGEON_FLOOR; map[i] = TILE_DUNGEON_FLOOR;
data[i] = randomTile[rand()%randomTileSize]; data[i] = randomTile[rand()%randomTileSize];
} }
} }
@ -838,17 +838,17 @@ void createDungeonRoom(int w, int h, bool dragon, int level, u8 * map, u8 * data
if(lava && xr > x+1 && xr < x+wr-2 && yr > y+1 && yr < y+hr-2) { if(lava && xr > x+1 && xr < x+wr-2 && yr > y+1 && yr < y+hr-2) {
map[i] = TILE_LAVA; map[i] = TILE_LAVA;
data[i] = 0; data[i] = 0;
} else if(pillars && xr > x && xr < x+wr-1 && yr > y && yr < y+hr-1 && xr%2 == 0 && yr%2 == 0) { } else if(pillars && xr > x && xr < x+wr-1 && yr > y && yr < y+hr-1 && xr%2 == 0 && yr%2 == 0) {
map[i] = TILE_DUNGEON_WALL; map[i] = TILE_DUNGEON_WALL;
data[i] = 0; data[i] = 0;
} else if(books && (xr>x && xr<x+wr-1 && yr>y && yr<y+hr-1 && yr%2==0)) { } else if(books && (xr>x && xr<x+wr-1 && yr>y && yr<y+hr-1 && yr%2==0)) {
map[i] = TILE_BOOKSHELVES; map[i] = TILE_BOOKSHELVES;
data[i] = rand()%3; data[i] = rand()%3;
if(!hasNPC && rand()%50) { if(!hasNPC && rand()%50) {
hasNPC = true; hasNPC = true;
addEntityToList(newNPCEntity(NPC_LIBRARIAN, (xr << 4) + 8, ((yr+1) << 4) + 8, level), &eManager); addEntityToList(newNPCEntity(NPC_LIBRARIAN, (xr << 4) + 8, ((yr+1) << 4) + 8, level), &eManager);
} }
} else { } else {
//add magic pillars for dragon barrier //add magic pillars for dragon barrier
if(xr==x+wr/2 && yr==y+hr/2) { if(xr==x+wr/2 && yr==y+hr/2) {
@ -875,4 +875,3 @@ void createDungeonRoom(int w, int h, bool dragon, int level, u8 * map, u8 * data
break; break;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -4,257 +4,257 @@ u8 pageNum = 0;
u8 maxPageNum = 7; u8 maxPageNum = 7;
u32 biasedCirclePad(u32 in){ u32 biasedCirclePad(u32 in){
if(in & KEY_CPAD_UP) return KEY_CPAD_UP; if(in & KEY_CPAD_UP) return KEY_CPAD_UP;
else if(in & KEY_CPAD_DOWN) return KEY_CPAD_DOWN; else if(in & KEY_CPAD_DOWN) return KEY_CPAD_DOWN;
else if(in & KEY_CPAD_LEFT) return KEY_CPAD_LEFT; else if(in & KEY_CPAD_LEFT) return KEY_CPAD_LEFT;
else if(in & KEY_CPAD_RIGHT) return KEY_CPAD_RIGHT; else if(in & KEY_CPAD_RIGHT) return KEY_CPAD_RIGHT;
else return (in & -in); else return (in & -in);
} }
u32 biasedMenuXY(u32 in){ u32 biasedMenuXY(u32 in){
if(in & KEY_X) return KEY_X; if(in & KEY_X) return KEY_X;
else if(in & KEY_Y) return KEY_Y; else if(in & KEY_Y) return KEY_Y;
else return (in & -in); else return (in & -in);
} }
/** Oh my god, this was so damn tedious to make. */ /** Oh my god, this was so damn tedious to make. */
void renderTutorialPage(bool topScreen){ void renderTutorialPage(bool topScreen){
if(topScreen){ if(topScreen){
drawTextColor("How to Play",(400-11*12)/2,12,0xFF00AFAF); drawTextColor("How to Play",(400-11*12)/2,12,0xFF00AFAF);
switch(pageNum){ switch(pageNum){
case 0: // Moving the character case 0: // Moving the character
drawTextColor("Movement",(400-8*12)/2,40,0xFF007FBF); drawTextColor("Movement",(400-8*12)/2,40,0xFF007FBF);
drawText("Press to move up",92,90); drawText("Press to move up",92,90);
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 164, 88, 1); renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 164, 88, 1);
drawText("Press to move down",80,120); drawText("Press to move down",80,120);
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 152, 118, 1); renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 152, 118, 1);
drawText("Press to move left",80,150); drawText("Press to move left",80,150);
renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 152, 148, 1); renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 152, 148, 1);
drawText("Press to move right",74,180); drawText("Press to move right",74,180);
renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 146, 178, 1); renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 146, 178, 1);
break; break;
case 1: // Attacking case 1: // Attacking
drawTextColor("Attacking",(400-9*12)/2,40,0xFF007FBF); drawTextColor("Attacking",(400-9*12)/2,40,0xFF007FBF);
drawText("Press to Attack",98,80); drawText("Press to Attack",98,80);
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 168, 78, 1); renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 168, 78, 1);
drawText("Attack with an item to use it",26,120); drawText("Attack with an item to use it",26,120);
drawText("Use the axe to cut down trees",26,140); drawText("Use the axe to cut down trees",26,140);
drawText("Use the sword to attack enemies",14,160); drawText("Use the sword to attack enemies",14,160);
drawText("Use the shovel to dig ground",32,180); drawText("Use the shovel to dig ground",32,180);
drawText("Use the pickaxe to mine rock/ore",8,200); drawText("Use the pickaxe to mine rock/ore",8,200);
break; break;
case 2: // Inventory case 2: // Inventory
drawTextColor("Inventory",(400-9*12)/2,40,0xFF007FBF); drawTextColor("Inventory",(400-9*12)/2,40,0xFF007FBF);
drawText("Press to open the menu",56,80); drawText("Press to open the menu",56,80);
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 78, 1); renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 78, 1);
drawText("Press to scroll up",80,110); drawText("Press to scroll up",80,110);
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 152, 108, 1); renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 152, 108, 1);
drawText("Press to scroll down",68,140); drawText("Press to scroll down",68,140);
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 140, 138, 1); renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 140, 138, 1);
drawText("Press to select an item",50,170); drawText("Press to select an item",50,170);
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 168, 1); renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 168, 1);
drawText("Press to close the menu",50,200); drawText("Press to close the menu",50,200);
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 120, 198, 1); renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 120, 198, 1);
break; break;
case 3: // Furniture case 3: // Furniture
drawTextColor("Furniture",(400-9*12)/2,40,0xFF007FBF); drawTextColor("Furniture",(400-9*12)/2,40,0xFF007FBF);
drawText("Use furniture for item crafting",(400-31*12)/2,74); drawText("Use furniture for item crafting",(400-31*12)/2,74);
drawText("Press to open the menu",56,100); drawText("Press to open the menu",56,100);
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 98, 1); renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 98, 1);
drawText("while infront of the furniture",(400-30*12)/2,116); drawText("while infront of the furniture",(400-30*12)/2,116);
drawText("Use the lantern item to light",(400-29*12)/2,144); drawText("Use the lantern item to light",(400-29*12)/2,144);
drawText("up underground areas",(400-20*12)/2,160); drawText("up underground areas",(400-20*12)/2,160);
drawText("Use the power glove item to",(400-27*12)/2,184); drawText("Use the power glove item to",(400-27*12)/2,184);
drawText("pick up furniture",(400-17*12)/2,200); drawText("pick up furniture",(400-17*12)/2,200);
break; break;
case 4: // Crafting case 4: // Crafting
drawTextColor("Crafting",(400-8*12)/2,40,0xFF007FBF); drawTextColor("Crafting",(400-8*12)/2,40,0xFF007FBF);
drawText("Create new items and tools",(400-26*12)/2,74); drawText("Create new items and tools",(400-26*12)/2,74);
drawText("Go up to a furniture item and",(400-29*12)/2,104); drawText("Go up to a furniture item and",(400-29*12)/2,104);
drawText("Press to open the menu",56,120); drawText("Press to open the menu",56,120);
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 118, 1); renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 118, 1);
drawText("Gather up the required materials",(400-32*12)/2,150); drawText("Gather up the required materials",(400-32*12)/2,150);
drawText("and then press to craft it",(400-28*12)/2,166); drawText("and then press to craft it",(400-28*12)/2,166);
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 210, 164, 1); renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 210, 164, 1);
break; break;
case 5: // Farming case 5: // Farming
drawTextColor("Farming",(400-7*12)/2,40,0xFF007FBF); drawTextColor("Farming",(400-7*12)/2,40,0xFF007FBF);
drawText("Grow wheat to make bread",(400-24*12)/2,74); drawText("Grow wheat to make bread",(400-24*12)/2,74);
drawText("Dig up grass to gather seeds",(400-28*12)/2,94); drawText("Dig up grass to gather seeds",(400-28*12)/2,94);
drawText("Use the hoe to till ground",(400-26*12)/2,114); drawText("Use the hoe to till ground",(400-26*12)/2,114);
drawText("Harvest wheat when it is yellow",(400-31*12)/2,134); drawText("Harvest wheat when it is yellow",(400-31*12)/2,134);
drawText("Use the oven to bake bread",(400-26*12)/2,154); drawText("Use the oven to bake bread",(400-26*12)/2,154);
drawText("It takes 4 wheat to craft bread",(400-31*12)/2,174); drawText("It takes 4 wheat to craft bread",(400-31*12)/2,174);
break; break;
case 6: // Mining case 6: // Mining
drawTextColor("Mining",(400-6*12)/2,40,0xFF007FBF); drawTextColor("Mining",(400-6*12)/2,40,0xFF007FBF);
drawText("Use a pickaxe tool for mining",(400-29*12)/2,74); drawText("Use a pickaxe tool for mining",(400-29*12)/2,74);
drawText("Mine rocks for stone",(400-20*12)/2,94); drawText("Mine rocks for stone",(400-20*12)/2,94);
drawText("Mine iron ore for iron",(400-22*12)/2,114); drawText("Mine iron ore for iron",(400-22*12)/2,114);
drawText("Mine gold ore for gold",(400-22*12)/2,134); drawText("Mine gold ore for gold",(400-22*12)/2,134);
drawText("Mine gem ore to get gems",(400-24*12)/2,154); drawText("Mine gem ore to get gems",(400-24*12)/2,154);
drawText("It takes 4 ore and 1 coal to",(400-28*12)/2,190); drawText("It takes 4 ore and 1 coal to",(400-28*12)/2,190);
drawText("make an ingot inside a furnace",(400-30*12)/2,210); drawText("make an ingot inside a furnace",(400-30*12)/2,210);
break; break;
case 7: // Potion Brewing case 7: // Potion Brewing
drawTextColor("Brewing",(400-6*12)/2,40,0xFF007FBF); drawTextColor("Brewing",(400-6*12)/2,40,0xFF007FBF);
drawText("Create potions.",(400-13*12)/2,74); drawText("Create potions.",(400-13*12)/2,74);
drawText("The potions give you abilities",(400-29*12)/2,94); drawText("The potions give you abilities",(400-29*12)/2,94);
drawText("Like speed and strength",(400-22*12)/2,114); drawText("Like speed and strength",(400-22*12)/2,114);
drawText("They are hard to obtain",(400-22*12)/2,134); drawText("They are hard to obtain",(400-22*12)/2,134);
break; break;
} }
} else { } else {
switch(pageNum){ switch(pageNum){
case 0: // Moving the character case 0: // Moving the character
render16(30,56,16,112,0);//Player up render16(30,56,16,112,0);//Player up
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 30,40, 2); renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 30,40, 2);
render16(60,56,0,112,0);//Player down render16(60,56,0,112,0);//Player down
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 60,40, 2); renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 60,40, 2);
render16(90,56,48,112,1);//Player left render16(90,56,48,112,1);//Player left
renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 90,40, 2); renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 90,40, 2);
render16(120,56,48,112,0);//Player right render16(120,56,48,112,0);//Player right
renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 120,40, 2); renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 120,40, 2);
break; break;
case 1: // Attacking case 1: // Attacking
render16(60,56,0,112,0);//Player-down render16(60,56,0,112,0);//Player-down
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 80, 56, 2); renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 80, 56, 2);
renderc(60,68,16,160,16,8,2);//Slash renderc(60,68,16,160,16,8,2);//Slash
menuRenderTilePit(12,20,256,0);// grass pit menuRenderTilePit(12,20,256,0);// grass pit
render16(12+8,20+4,256,48,0);//Tree render16(12+8,20+4,256,48,0);//Tree
renderc(12+9,20+14,16,160,16,8,0);//Slash renderc(12+9,20+14,16,160,16,8,0);//Slash
render(12+9+4,20+14,192,144,0);//Axe render(12+9+4,20+14,192,144,0);//Axe
render16(12+9,20+18,16,112,0);//Player-up render16(12+9,20+18,16,112,0);//Player-up
menuRenderTilePit(122,62,320,0);// sand pit menuRenderTilePit(122,62,320,0);// sand pit
render16(130,70,256,16,0);// hole render16(130,70,256,16,0);// hole
render16(116,70,48,112,0);//Player-right render16(116,70,48,112,0);//Player-right
renderb(136,76,16,152,0,sandColor);// Sand item renderb(136,76,16,152,0,sandColor);// Sand item
renderc(128,70,40,160,8,16,0);//Slash renderc(128,70,40,160,8,16,0);//Slash
render(130,74,0,144,0);//Shovel render(130,74,0,144,0);//Shovel
break; break;
case 2: // Inventory case 2: // Inventory
renderFrame(4,4,17,11,0xFFFF1010); renderFrame(4,4,17,11,0xFFFF1010);
renderItemStuffWithText(ITEM_APPLE,5,false,80,78); renderItemStuffWithText(ITEM_APPLE,5,false,80,78);
renderItemStuffWithText(ITEM_SLIME,11,false,80,94); renderItemStuffWithText(ITEM_SLIME,11,false,80,94);
renderItemStuffWithText(TOOL_SWORD,4,true,80,110); renderItemStuffWithText(TOOL_SWORD,4,true,80,110);
renderItemStuffWithText(ITEM_IRONORE,3,false,80,126); renderItemStuffWithText(ITEM_IRONORE,3,false,80,126);
renderItemStuffWithText(ITEM_IRONINGOT,11,false,80,142); renderItemStuffWithText(ITEM_IRONINGOT,11,false,80,142);
sf2d_draw_rectangle(64, 110, 12, 12, 0xFF); sf2d_draw_rectangle(64, 110, 12, 12, 0xFF);
drawText(">", 64, 110); drawText(">", 64, 110);
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 44, 92, 1); renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 44, 92, 1);
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 44, 108, 1); renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 44, 108, 1);
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 44, 125, 1); renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 44, 125, 1);
break; break;
case 3: // Furniture case 3: // Furniture
sf2d_draw_rectangle(64, 48, 192, 32, grassColor); sf2d_draw_rectangle(64, 48, 192, 32, grassColor);
renderc(32,24,64,128,96,16,0);//Furniture entities renderc(32,24,64,128,96,16,0);//Furniture entities
renderFurniture(ITEM_WORKBENCH, 50,60); renderFurniture(ITEM_WORKBENCH, 50,60);
render16(50,46,0,112,0);//Player-down render16(50,46,0,112,0);//Player-down
renderc(50,58,16,160,16,8,2);//Slash renderc(50,58,16,160,16,8,2);//Slash
render(54,58,56,152,0);//Power glove render(54,58,56,152,0);//Power glove
render16(92,56,0,128,0);//Player(Carrying) render16(92,56,0,128,0);//Player(Carrying)
render16(92,44,128,128,0);//Workbench render16(92,44,128,128,0);//Workbench
break; break;
case 4: // Crafting case 4: // Crafting
renderFrame(11,3,19,6,0xFFFF1010); renderFrame(11,3,19,6,0xFFFF1010);
renderFrame(11,7,19,12,0xFFFF1010); renderFrame(11,7,19,12,0xFFFF1010);
renderFrame(1,3,10,12,0xFFFF1010); renderFrame(1,3,10,12,0xFFFF1010);
renderItemStuffWithText(TOOL_AXE,0,true,28,64); renderItemStuffWithText(TOOL_AXE,0,true,28,64);
renderItemIcon(TOOL_AXE, 0, 94, 32); renderItemIcon(TOOL_AXE, 0, 94, 32);
drawText("0", 206, 66); drawText("0", 206, 66);
renderItemIcon(ITEM_WOOD, 0, 94, 64); renderItemIcon(ITEM_WOOD, 0, 94, 64);
drawText("16/5", 206, 130); drawText("16/5", 206, 130);
break; break;
case 5: // Farming (Bottom screen) case 5: // Farming (Bottom screen)
renderc(24,16,352,48,112,16,0); // Wheat Stages renderc(24,16,352,48,112,16,0); // Wheat Stages
render16(20,40,352,48,0); // Farm Tile render16(20,40,352,48,0); // Farm Tile
render16(36,40,448,48,0); // Wheat Tile render16(36,40,448,48,0); // Wheat Tile
render16(52,40,448,48,0); // Wheat Tile render16(52,40,448,48,0); // Wheat Tile
render16(20,54,16,112,0); // Player (Up) render16(20,54,16,112,0); // Player (Up)
renderc(20,50,16,160,16,8,0); // Slash (Up) renderc(20,50,16,160,16,8,0); // Slash (Up)
render(19,45,40,152,0); // Seeds render(19,45,40,152,0); // Seeds
render(26,39,48,152,0); // Wheat1 render(26,39,48,152,0); // Wheat1
render(29,44,48,152,0); // Wheat2 render(29,44,48,152,0); // Wheat2
renderc(72,40,352,48,32,16,0); // Farm Tile + Seeded Wheat Tile renderc(72,40,352,48,32,16,0); // Farm Tile + Seeded Wheat Tile
render16(72,54,16,112,0); // Player (Up) render16(72,54,16,112,0); // Player (Up)
renderc(72,50,16,160,16,8,0); // Slash (Up) renderc(72,50,16,160,16,8,0); // Slash (Up)
render(76,48,40,152,0); // Seeds render(76,48,40,152,0); // Seeds
sf2d_draw_rectangle(216, 80, 32, 32, dirtColor[1]); // Dirt color for grass sf2d_draw_rectangle(216, 80, 32, 32, dirtColor[1]); // Dirt color for grass
render16(108, 40, 256, 0, 0); // Grass render16(108, 40, 256, 0, 0); // Grass
render16(124, 40,352,48,0); // Farm Tile render16(124, 40,352,48,0); // Farm Tile
render16(108,54,16,112,0); // Player (Up) render16(108,54,16,112,0); // Player (Up)
renderc(108,50,16,160,16,8,0); // Slash (Up) renderc(108,50,16,160,16,8,0); // Slash (Up)
render(112,48,72,144,0); // Gem Hoe render(112,48,72,144,0); // Gem Hoe
sf2d_draw_rectangle(112, 156, 32, 32, dirtColor[1]); // Dirt color for grass sf2d_draw_rectangle(112, 156, 32, 32, dirtColor[1]); // Dirt color for grass
render16(56, 78, 256, 0, 0); // Grass render16(56, 78, 256, 0, 0); // Grass
sf2d_draw_rectangle(80, 156, 32, 32, dirtColor[1]); // Dirt color sf2d_draw_rectangle(80, 156, 32, 32, dirtColor[1]); // Dirt color
render16(40, 78, 336, 80, 0); // Dirt Dots render16(40, 78, 336, 80, 0); // Dirt Dots
render(44, 82, 40,152,0); // Seeds render(44, 82, 40,152,0); // Seeds
render16(24,78,48,112,0); // Player (Right) render16(24,78,48,112,0); // Player (Right)
renderc(36,78,40,160,8,16,0); // Slash (Right) renderc(36,78,40,160,8,16,0); // Slash (Right)
render(38,82,32,144,0); // Gem Shovel render(38,82,32,144,0); // Gem Shovel
render(82,78,48,152,0); // Wheat render(82,78,48,152,0); // Wheat
render(90,78,48,152,0); // Wheat render(90,78,48,152,0); // Wheat
render(82,86,48,152,0); // Wheat render(82,86,48,152,0); // Wheat
render(90,86,48,152,0); // Wheat render(90,86,48,152,0); // Wheat
drawText(">",203,164); drawText(">",203,164);
render16(108,76,96,128,0); // Oven render16(108,76,96,128,0); // Oven
drawText(">",246,164); drawText(">",246,164);
render(132,82,72,152,0); // Bread render(132,82,72,152,0); // Bread
break; break;
case 6: //Mining case 6: //Mining
render16(23,32,464,48,0); // iron ore render16(23,32,464,48,0); // iron ore
render16(23,52,480,48,0); // gold ore render16(23,52,480,48,0); // gold ore
render16(23,72,496,48,0); // gem ore render16(23,72,496,48,0); // gem ore
renderb(41,38,88,152,0,ironColor); // Iron ore item renderb(41,38,88,152,0,ironColor); // Iron ore item
renderb(41,58,88,152,0,goldColor); // Gold ore item renderb(41,58,88,152,0,goldColor); // Gold ore item
render(41,78,112,152,0); // Gem item render(41,78,112,152,0); // Gem item
drawText(">",104,74); drawText(">",104,74);
drawText(">",104,114); drawText(">",104,114);
drawText(">",104,154); drawText(">",104,154);
render16(60,32,112,128,0); // Furnace render16(60,32,112,128,0); // Furnace
render16(60,52,112,128,0); // Furnace render16(60,52,112,128,0); // Furnace
render16(60,72,240,128,0); // Enchanter render16(60,72,240,128,0); // Enchanter
drawText(">",160,74); drawText(">",160,74);
drawText(">",160,114); drawText(">",160,114);
drawText(">",160,154); drawText(">",160,154);
renderb(88,36,96,152,0,ironColor); // Iron ingot item renderb(88,36,96,152,0,ironColor); // Iron ingot item
renderb(88,56,96,152,0,goldColor); // Gold ingot item renderb(88,56,96,152,0,goldColor); // Gold ingot item
renderb(88,76,152,144,0,goldColor); // Gem Pickaxe renderb(88,76,152,144,0,goldColor); // Gem Pickaxe
drawText(">",200,74); drawText(">",200,74);
drawText(">",200,114); drawText(">",200,114);
render16(106,32,64,128,0); // Anvil render16(106,32,64,128,0); // Anvil
render16(106,52,64,128,0); // Anvil render16(106,52,64,128,0); // Anvil
drawText(">",244,74); drawText(">",244,74);
drawText(">",244,114); drawText(">",244,114);
render(130,36,136,144,0); // Iron Pickaxe render(130,36,136,144,0); // Iron Pickaxe
render(130,56,144,144,0); // Gold Pickaxe render(130,56,144,144,0); // Gold Pickaxe
break; break;
case 7: // Brewing case 7: // Brewing
render16(65, 56, 240, 96, 0); render16(65, 56, 240, 96, 0);
break; break;
} }
drawText(pageText,(320-(strlen(pageText))*12)/2,12); drawText(pageText,(320-(strlen(pageText))*12)/2,12);
if(pageNum > 0){ if(pageNum > 0){
drawText("<",2,16); drawText("<",2,16);
renderButtonIcon(localInputs.k_menuPrev.input & -localInputs.k_menuPrev.input, 8, 2, 2); renderButtonIcon(localInputs.k_menuPrev.input & -localInputs.k_menuPrev.input, 8, 2, 2);
} }
if(pageNum < maxPageNum){ if(pageNum < maxPageNum){
drawText(">",306,16); drawText(">",306,16);
renderButtonIcon(localInputs.k_menuNext.input & -localInputs.k_menuNext.input, 136, 2, 2); renderButtonIcon(localInputs.k_menuNext.input & -localInputs.k_menuNext.input, 136, 2, 2);
} }
drawText("Press to exit",(320-(15*12))/2,218); drawText("Press to exit",(320-(15*12))/2,218);
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 140, 216, 1); renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 140, 216, 1);
} }
} }

View file

@ -46,38 +46,38 @@ void clearSendAckedBuffer();
bool sendAck(u16 target, u16 ack); bool sendAck(u16 target, u16 ack);
void networkThreadMain(void *arg) { void networkThreadMain(void *arg) {
while(networkRunThread) { while(networkRunThread) {
if(udsRunning && isConnected) { if(udsRunning && isConnected) {
networkUpdateStatus(); networkUpdateStatus();
networkHandleRecieve(); networkHandleRecieve();
networkHandleSend(); networkHandleSend();
} }
//TODO: Set meaningfull value, WARNING: Setting this near 1ms (1000*1000) will make everything super laggy, higher values actually work better! //TODO: Set meaningfull value, WARNING: Setting this near 1ms (1000*1000) will make everything super laggy, higher values actually work better!
svcSleepThread(10000 * 1000); svcSleepThread(10000 * 1000);
} }
} }
void networkUpdateStatus() { void networkUpdateStatus() {
/*for(int i=0; i<10; i++) { /*for(int i=0; i<10; i++) {
Result ret = udsGetConnectionStatus(&networkStatus); Result ret = udsGetConnectionStatus(&networkStatus);
if(!R_FAILED(ret)) { if(!R_FAILED(ret)) {
return; return;
} }
}*/ }*/
if(udsWaitConnectionStatusEvent(false, false)) { if(udsWaitConnectionStatusEvent(false, false)) {
udsGetConnectionStatus(&networkStatus); udsGetConnectionStatus(&networkStatus);
} }
} }
void networkHandleRecieve() { void networkHandleRecieve() {
bool recieved = false; bool recieved = false;
do { do {
recieved = false; recieved = false;
size_t actualSize = 0; size_t actualSize = 0;
u16 sourceNetworkNodeID; u16 sourceNetworkNodeID;
u32 ackToSend = 0; u32 ackToSend = 0;
memset(networkBuffer, 0, networkBufferSize); memset(networkBuffer, 0, networkBufferSize);
@ -87,170 +87,170 @@ void networkHandleRecieve() {
//actualSize will be 0 if no packet is available //actualSize will be 0 if no packet is available
} else if(actualSize) { } else if(actualSize) {
void *readPointer = networkBuffer; void *readPointer = networkBuffer;
//ack frame //ack frame
if(actualSize==sizeof(u16)) { if(actualSize==sizeof(u16)) {
networkSeqSendConf[sourceNetworkNodeID] = *((u16*) readPointer); networkSeqSendConf[sourceNetworkNodeID] = *((u16*) readPointer);
clearSendAckedBuffer(); clearSendAckedBuffer();
//normal frame //normal frame
} else { } else {
while(actualSize>0) { while(actualSize>0) {
//read seqID and size //read seqID and size
u16 seqID = *((u16*) readPointer); u16 seqID = *((u16*) readPointer);
readPointer += sizeof(u16); readPointer += sizeof(u16);
actualSize -= sizeof(u16); actualSize -= sizeof(u16);
u16 size = *((u16*) readPointer); u16 size = *((u16*) readPointer);
readPointer += sizeof(u16); readPointer += sizeof(u16);
actualSize -= sizeof(u16); actualSize -= sizeof(u16);
//if the seq id was expected handle the packet //if the seq id was expected handle the packet
u16 nextID = networkGetExpectedSeqFrom(sourceNetworkNodeID); u16 nextID = networkGetExpectedSeqFrom(sourceNetworkNodeID);
if(seqID==nextID) { if(seqID==nextID) {
networkSeqRecvLast[sourceNetworkNodeID] = seqID; networkSeqRecvLast[sourceNetworkNodeID] = seqID;
ackToSend = seqID; ackToSend = seqID;
//handle data - TODO: WARNING: Do not send sizeof(u16) packets or else they will get confused with this one //handle data - TODO: WARNING: Do not send sizeof(u16) packets or else they will get confused with this one
if(size==sizeof(u16)) { if(size==sizeof(u16)) {
networkConnectedMask = *((u16*) readPointer); networkConnectedMask = *((u16*) readPointer);
} else { } else {
processPacket(readPointer, size); processPacket(readPointer, size);
} }
} else if(networkSeqIsLowerThan(seqID, nextID)) { } else if(networkSeqIsLowerThan(seqID, nextID)) {
ackToSend = seqID; ackToSend = seqID;
} }
readPointer += size; readPointer += size;
actualSize -= size; actualSize -= size;
} }
if(ackToSend!=0) { if(ackToSend!=0) {
if(sendAck(sourceNetworkNodeID, ackToSend)) { if(sendAck(sourceNetworkNodeID, ackToSend)) {
} }
} }
} }
recieved = true; recieved = true;
} }
} while(recieved); } while(recieved);
} }
void networkHandleSend() { void networkHandleSend() {
if(networkSendBufferStartPos!=networkSendBufferEndPos) { if(networkSendBufferStartPos!=networkSendBufferEndPos) {
LightLock_Lock(&sendBufferLock); LightLock_Lock(&sendBufferLock);
//determine send size //determine send size
size_t currentSize = 0; size_t currentSize = 0;
while(networkSendBufferStartPos+currentSize<networkSendBufferWrapPos && networkSendBufferStartPos+currentSize!=networkSendBufferEndPos) { while(networkSendBufferStartPos+currentSize<networkSendBufferWrapPos && networkSendBufferStartPos+currentSize!=networkSendBufferEndPos) {
//size of "header info" (seqid,size) //size of "header info" (seqid,size)
size_t extraSize = sizeof(u16) + sizeof(u16); size_t extraSize = sizeof(u16) + sizeof(u16);
//data size //data size
extraSize += *((u16*) ((networkSendBuffer+networkSendBufferStartPos+currentSize) + sizeof(u16))); extraSize += *((u16*) ((networkSendBuffer+networkSendBufferStartPos+currentSize) + sizeof(u16)));
//if next packet can fit in frame include it //if next packet can fit in frame include it
if(currentSize+extraSize < UDS_DATAFRAME_MAXSIZE) { if(currentSize+extraSize < UDS_DATAFRAME_MAXSIZE) {
currentSize += extraSize; currentSize += extraSize;
} else { } else {
break; break;
} }
} }
//send frame //send frame
if(currentSize>0) { if(currentSize>0) {
//TODO: Once we have our own custom mask, no longer broadcast, but send directly because bcast doesn't always reach everyone? //TODO: Once we have our own custom mask, no longer broadcast, but send directly because bcast doesn't always reach everyone?
if(networkConnectedMask==0) { if(networkConnectedMask==0) {
//send frame //send frame
Result ret = udsSendTo(UDS_BROADCAST_NETWORKNODEID, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize); Result ret = udsSendTo(UDS_BROADCAST_NETWORKNODEID, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize);
if(UDS_CHECK_SENDTO_FATALERROR(ret)) { if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
//TODO: what do? //TODO: what do?
} else if(R_FAILED(ret)) { } else if(R_FAILED(ret)) {
//TODO: what do? //TODO: what do?
} }
} else { } else {
for(int i=1; i<=UDS_MAXNODES; i++) { for(int i=1; i<=UDS_MAXNODES; i++) {
if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) { if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) {
//send frame //send frame
Result ret = udsSendTo(i, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize); Result ret = udsSendTo(i, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize);
if(UDS_CHECK_SENDTO_FATALERROR(ret)) { if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
//TODO: what do? //TODO: what do?
} else if(R_FAILED(ret)) { } else if(R_FAILED(ret)) {
//TODO: what do? //TODO: what do?
} }
} }
} }
} }
} }
LightLock_Unlock(&sendBufferLock); LightLock_Unlock(&sendBufferLock);
} }
} }
void clearSendAckedBuffer() { void clearSendAckedBuffer() {
//find last ack recieved from all com partners //find last ack recieved from all com partners
u16 ackID = 0; u16 ackID = 0;
for(int i=1; i<=UDS_MAXNODES; i++) { for(int i=1; i<=UDS_MAXNODES; i++) {
if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) { if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) {
if(networkSeqSendConf[i]==0) { if(networkSeqSendConf[i]==0) {
ackID = 0; ackID = 0;
return; return;
} }
if(ackID==0) { if(ackID==0) {
ackID = networkSeqSendConf[i]; ackID = networkSeqSendConf[i];
} else if(networkSeqSendConf[i]<100) { } else if(networkSeqSendConf[i]<100) {
if(ackID > networkSeqSendConf[i] && ackID<65535-100) ackID = networkSeqSendConf[i]; if(ackID > networkSeqSendConf[i] && ackID<65535-100) ackID = networkSeqSendConf[i];
} else if(networkSeqSendConf[i]>65535-100) { } else if(networkSeqSendConf[i]>65535-100) {
if(ackID > networkSeqSendConf[i] || ackID<100) ackID = networkSeqSendConf[i]; if(ackID > networkSeqSendConf[i] || ackID<100) ackID = networkSeqSendConf[i];
} else { } else {
if(ackID > networkSeqSendConf[i]) ackID = networkSeqSendConf[i]; if(ackID > networkSeqSendConf[i]) ackID = networkSeqSendConf[i];
} }
} }
} }
if(ackID==0) return; if(ackID==0) return;
LightLock_Lock(&sendBufferLock); LightLock_Lock(&sendBufferLock);
//clear buffer of acknowledgt packets //clear buffer of acknowledgt packets
while(networkSendBufferStartPos!=networkSendBufferEndPos) { while(networkSendBufferStartPos!=networkSendBufferEndPos) {
//find current seqid and size //find current seqid and size
u16 seqID = *((u16*) (networkSendBuffer+networkSendBufferStartPos)); u16 seqID = *((u16*) (networkSendBuffer+networkSendBufferStartPos));
u16 size = *((u16*) (networkSendBuffer+networkSendBufferStartPos+sizeof(u16))); u16 size = *((u16*) (networkSendBuffer+networkSendBufferStartPos+sizeof(u16)));
if(seqID<=ackID || (ackID<100 && seqID>65535-100)) { if(seqID<=ackID || (ackID<100 && seqID>65535-100)) {
size_t currentSize = sizeof(u16)*2 + size; size_t currentSize = sizeof(u16)*2 + size;
//adjust buffer "pointers" //adjust buffer "pointers"
networkSendBufferStartPos += currentSize; networkSendBufferStartPos += currentSize;
if(networkSendBufferStartPos==networkSendBufferEndPos) { if(networkSendBufferStartPos==networkSendBufferEndPos) {
networkSendBufferStartPos = 0; networkSendBufferStartPos = 0;
networkSendBufferEndPos = 0; networkSendBufferEndPos = 0;
networkSendBufferWrapPos = 0; networkSendBufferWrapPos = 0;
} }
//wrap //wrap
if(networkSendBufferStartPos==networkSendBufferWrapPos) { if(networkSendBufferStartPos==networkSendBufferWrapPos) {
networkSendBufferStartPos = 0; networkSendBufferStartPos = 0;
networkSendBufferWrapPos = networkSendBufferEndPos; networkSendBufferWrapPos = networkSendBufferEndPos;
} }
} else { } else {
break; break;
} }
} }
LightLock_Unlock(&sendBufferLock); LightLock_Unlock(&sendBufferLock);
} }
bool sendAck(u16 target, u16 ack) { bool sendAck(u16 target, u16 ack) {
Result ret = udsSendTo(target, NETWORK_CHANNEL, UDS_SENDFLAG_Default, &ack, sizeof(u16)); Result ret = udsSendTo(target, NETWORK_CHANNEL, UDS_SENDFLAG_Default, &ack, sizeof(u16));
if(UDS_CHECK_SENDTO_FATALERROR(ret)) { if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
//TODO: what do? //TODO: what do?
return false; return false;
} else if(R_FAILED(ret)) { } else if(R_FAILED(ret)) {
//TODO: what do? //TODO: what do?
return false; return false;
} else { } else {
return true; return true;
} }
} }
void networkInit() { void networkInit() {
@ -264,79 +264,79 @@ void networkInit() {
scannedNetworks = NULL; scannedNetworks = NULL;
isConnected = false; isConnected = false;
isServer = false; isServer = false;
networkConnectedMask = 0; networkConnectedMask = 0;
networkWriteBuffer = malloc(NETWORK_MAXDATASIZE); networkWriteBuffer = malloc(NETWORK_MAXDATASIZE);
if(networkWriteBuffer==NULL) { if(networkWriteBuffer==NULL) {
networkExit(); networkExit();
return; return;
} }
networkBufferSize = 0x4000; networkBufferSize = 0x4000;
networkBuffer = malloc(networkBufferSize); networkBuffer = malloc(networkBufferSize);
if(networkBuffer==NULL) { if(networkBuffer==NULL) {
networkExit(); networkExit();
return; return;
} }
networkSendBufferStartPos = 0; networkSendBufferStartPos = 0;
networkSendBufferEndPos = 0; networkSendBufferEndPos = 0;
networkSendBufferWrapPos = 0; networkSendBufferWrapPos = 0;
networkSendBuffer = malloc(NETWORK_SENDBUFFERSIZE); networkSendBuffer = malloc(NETWORK_SENDBUFFERSIZE);
if(networkSendBuffer==NULL) { if(networkSendBuffer==NULL) {
networkExit(); networkExit();
return; return;
} }
networkSeqSendNext = 1; networkSeqSendNext = 1;
for(int i=0; i<UDS_MAXNODES+1; i++) { for(int i=0; i<UDS_MAXNODES+1; i++) {
networkSeqSendConf[i] = 0; networkSeqSendConf[i] = 0;
networkSeqRecvLast[i] = 0; networkSeqRecvLast[i] = 0;
} }
networkAckBuffer = malloc(sizeof(u16)+sizeof(u16)+sizeof(u16)); networkAckBuffer = malloc(sizeof(u16)+sizeof(u16)+sizeof(u16));
if(networkAckBuffer==NULL) { if(networkAckBuffer==NULL) {
networkExit(); networkExit();
return; return;
} }
LightLock_Init(&sendBufferLock); LightLock_Init(&sendBufferLock);
s32 prio = 0; s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
//NOTE: It is important the networkThread is prioritized over the main thread (so substract 1) or else nothing will work //NOTE: It is important the networkThread is prioritized over the main thread (so substract 1) or else nothing will work
networkRunThread = true; networkRunThread = true;
networkThread = threadCreate(networkThreadMain, NULL, NETWORK_STACKSIZE, prio-1, -2, false); networkThread = threadCreate(networkThreadMain, NULL, NETWORK_STACKSIZE, prio-1, -2, false);
} }
} }
void networkExit() { void networkExit() {
//Additionally to shutting down the service, clear any left over memory! //Additionally to shutting down the service, clear any left over memory!
if(udsRunning) { if(udsRunning) {
udsRunning = false; udsRunning = false;
if(networkRunThread) { if(networkRunThread) {
networkRunThread = false; networkRunThread = false;
threadJoin(networkThread, U64_MAX); threadJoin(networkThread, U64_MAX);
threadFree(networkThread); threadFree(networkThread);
} }
//cleanup any dynamically reserved memory //cleanup any dynamically reserved memory
if(scannedNetworks!=NULL) free(scannedNetworks); if(scannedNetworks!=NULL) free(scannedNetworks);
scannedNetworks = NULL; scannedNetworks = NULL;
if(networkWriteBuffer!=NULL) free(networkWriteBuffer); if(networkWriteBuffer!=NULL) free(networkWriteBuffer);
networkWriteBuffer = NULL; networkWriteBuffer = NULL;
if(networkBuffer!=NULL) free(networkBuffer); if(networkBuffer!=NULL) free(networkBuffer);
networkBuffer = NULL; networkBuffer = NULL;
if(networkSendBuffer!=NULL) free(networkSendBuffer); if(networkSendBuffer!=NULL) free(networkSendBuffer);
networkSendBuffer = NULL; networkSendBuffer = NULL;
if(networkAckBuffer!=NULL) free(networkAckBuffer); if(networkAckBuffer!=NULL) free(networkAckBuffer);
networkAckBuffer = NULL; networkAckBuffer = NULL;
networkDisconnect(); networkDisconnect();
@ -360,12 +360,12 @@ bool networkHost() {
if(R_FAILED(ret)) { if(R_FAILED(ret)) {
return false; return false;
} else { } else {
if(udsWaitConnectionStatusEvent(false, false)) {} if(udsWaitConnectionStatusEvent(false, false)) {}
udsGetConnectionStatus(&networkStatus); udsGetConnectionStatus(&networkStatus);
udsSetNewConnectionsBlocked(false, true, false); udsSetNewConnectionsBlocked(false, true, false);
isConnected = true; isConnected = true;
isServer = true; isServer = true;
networkConnectedMask = 0; networkConnectedMask = 0;
return true; return true;
} }
} }
@ -373,7 +373,7 @@ bool networkHost() {
} }
void networkHostStopConnections() { void networkHostStopConnections() {
udsSetNewConnectionsBlocked(true, true, false); udsSetNewConnectionsBlocked(true, true, false);
} }
void networkScan() { void networkScan() {
@ -423,11 +423,11 @@ bool networkConnect(int pos) {
if(R_FAILED(ret)) { if(R_FAILED(ret)) {
return false; return false;
} else { } else {
if(udsWaitConnectionStatusEvent(false, false)) {} if(udsWaitConnectionStatusEvent(false, false)) {}
udsGetConnectionStatus(&networkStatus); udsGetConnectionStatus(&networkStatus);
isConnected = true; isConnected = true;
isServer = false; isServer = false;
networkConnectedMask = 0; networkConnectedMask = 0;
return true; return true;
} }
} }
@ -439,24 +439,24 @@ void networkDisconnect() {
if(udsRunning && isConnected) { if(udsRunning && isConnected) {
isConnected = false; isConnected = false;
LightLock_Lock(&sendBufferLock); LightLock_Lock(&sendBufferLock);
//reset send buffer //reset send buffer
networkSendBufferStartPos = 0; networkSendBufferStartPos = 0;
networkSendBufferEndPos = 0; networkSendBufferEndPos = 0;
networkSendBufferWrapPos = 0; networkSendBufferWrapPos = 0;
//reset ack status //reset ack status
networkSeqSendNext = 1; networkSeqSendNext = 1;
for(int i=0; i<UDS_MAXNODES+1; i++) { for(int i=0; i<UDS_MAXNODES+1; i++) {
networkSeqSendConf[i] = 0; networkSeqSendConf[i] = 0;
networkSeqRecvLast[i] = 0; networkSeqRecvLast[i] = 0;
} }
LightLock_Unlock(&sendBufferLock); LightLock_Unlock(&sendBufferLock);
//With new changes citra now crashes HOST with "cannot be a router if we are not a host" when exiting game with more than 2 people //With new changes citra now crashes HOST with "cannot be a router if we are not a host" when exiting game with more than 2 people
svcSleepThread(220000 * 1000); //HACK: prevent citra crash (>20*networkthreadsleep) (wait unti no more stuff gets send) svcSleepThread(220000 * 1000); //HACK: prevent citra crash (>20*networkthreadsleep) (wait unti no more stuff gets send)
//TODO //TODO
if(isServer) { if(isServer) {
//TODO: Clients need to cleanup too, how can I tell they got disconnected //TODO: Clients need to cleanup too, how can I tell they got disconnected
udsDestroyNetwork(); udsDestroyNetwork();
@ -471,16 +471,16 @@ void networkDisconnect() {
void networkStart() { void networkStart() {
//TODO: This sends the node_bitmask from server to everyone else, because it is uncorrect on some clients? //TODO: This sends the node_bitmask from server to everyone else, because it is uncorrect on some clients?
if(udsRunning && isConnected && isServer) { if(udsRunning && isConnected && isServer) {
void *buffer = networkWriteBuffer; void *buffer = networkWriteBuffer;
*((u16*) buffer) = networkStatus.node_bitmask; *((u16*) buffer) = networkStatus.node_bitmask;
networkConnectedMask = networkStatus.node_bitmask; networkConnectedMask = networkStatus.node_bitmask;
networkSend(networkWriteBuffer, sizeof(u16)); networkSend(networkWriteBuffer, sizeof(u16));
networkSendWaitFlush(); networkSendWaitFlush();
} }
} }
@ -489,33 +489,33 @@ bool networkConnected() {
} }
int networkGetNodeCount() { int networkGetNodeCount() {
if(udsRunning && isConnected) { if(udsRunning && isConnected) {
return networkStatus.total_nodes; return networkStatus.total_nodes;
} else { } else {
return 0; return 0;
} }
} }
u16 networkGetLocalNodeID() { u16 networkGetLocalNodeID() {
if(udsRunning && isConnected) { if(udsRunning && isConnected) {
return networkStatus.cur_NetworkNodeID; return networkStatus.cur_NetworkNodeID;
} else { } else {
return 0; return 0;
} }
} }
bool networkIsNodeConnected(u16 id) { bool networkIsNodeConnected(u16 id) {
if(udsRunning && isConnected) { if(udsRunning && isConnected) {
return networkStatus.node_bitmask & (1 << (id-1)); return networkStatus.node_bitmask & (1 << (id-1));
} else { } else {
return false; return false;
} }
} }
bool networkGetNodeName(u16 id, char *name) { bool networkGetNodeName(u16 id, char *name) {
if(udsRunning && isConnected && networkIsNodeConnected(id)) { if(udsRunning && isConnected && networkIsNodeConnected(id)) {
udsNodeInfo nodeInfo; udsNodeInfo nodeInfo;
udsGetNodeInformation(id, &nodeInfo); udsGetNodeInformation(id, &nodeInfo);
Result ret = udsGetNodeInfoUsername(&nodeInfo, name); Result ret = udsGetNodeInfoUsername(&nodeInfo, name);
if(R_FAILED(ret)) { if(R_FAILED(ret)) {
@ -547,74 +547,74 @@ bool networkSeqIsLowerThan(u16 firstID, u16 secondID) {
} }
int fitInSendBuffer(size_t size) { int fitInSendBuffer(size_t size) {
//add "header" length //add "header" length
size += sizeof(u16)*2; size += sizeof(u16)*2;
//we have no wrap currently //we have no wrap currently
if(networkSendBufferStartPos<=networkSendBufferEndPos) { if(networkSendBufferStartPos<=networkSendBufferEndPos) {
//and can fit without wrap //and can fit without wrap
if(networkSendBufferEndPos+size<NETWORK_SENDBUFFERSIZE) { if(networkSendBufferEndPos+size<NETWORK_SENDBUFFERSIZE) {
networkSendBufferEndPos += size; networkSendBufferEndPos += size;
networkSendBufferWrapPos = networkSendBufferEndPos; networkSendBufferWrapPos = networkSendBufferEndPos;
return networkSendBufferEndPos-size; return networkSendBufferEndPos-size;
//we need to wrap //we need to wrap
} else { } else {
if(size<networkSendBufferStartPos) { if(size<networkSendBufferStartPos) {
networkSendBufferEndPos = size; networkSendBufferEndPos = size;
return 0; return 0;
} }
} }
//we have wrap currently //we have wrap currently
} else { } else {
int available = networkSendBufferStartPos - networkSendBufferEndPos - 1; int available = networkSendBufferStartPos - networkSendBufferEndPos - 1;
if(available>size) { if(available>size) {
networkSendBufferEndPos += size; networkSendBufferEndPos += size;
return networkSendBufferEndPos-size; return networkSendBufferEndPos-size;
} }
} }
return -1; return -1;
} }
void networkSend(void *packet, size_t size) { void networkSend(void *packet, size_t size) {
//search for fit in buffer (and BLOCK until free space is found) //search for fit in buffer (and BLOCK until free space is found)
LightLock_Lock(&sendBufferLock); LightLock_Lock(&sendBufferLock);
int pos = fitInSendBuffer(size); int pos = fitInSendBuffer(size);
while(pos==-1) { while(pos==-1) {
LightLock_Unlock(&sendBufferLock); LightLock_Unlock(&sendBufferLock);
svcSleepThread(4500 * 1000); //TODO: Set meaningfull value svcSleepThread(4500 * 1000); //TODO: Set meaningfull value
LightLock_Lock(&sendBufferLock); LightLock_Lock(&sendBufferLock);
pos = fitInSendBuffer(size); pos = fitInSendBuffer(size);
} }
//fit found -> space is allready "reserved" -> write packet to buffer //fit found -> space is allready "reserved" -> write packet to buffer
void *writePointer = networkSendBuffer + pos; void *writePointer = networkSendBuffer + pos;
//write seq number //write seq number
*((u16*) writePointer) = networkSeqSendNext; *((u16*) writePointer) = networkSeqSendNext;
networkSeqSendNext++; networkSeqSendNext++;
if(networkSeqSendNext==0) { if(networkSeqSendNext==0) {
networkSeqSendNext = 1; networkSeqSendNext = 1;
} }
writePointer += sizeof(u16); writePointer += sizeof(u16);
//write size //write size
*((u16*) writePointer) = (u16) size; *((u16*) writePointer) = (u16) size;
writePointer += sizeof(u16); writePointer += sizeof(u16);
//write data //write data
memcpy(writePointer, packet, size); memcpy(writePointer, packet, size);
writePointer += size; writePointer += size;
LightLock_Unlock(&sendBufferLock); LightLock_Unlock(&sendBufferLock);
} }
void networkSendWaitFlush() { void networkSendWaitFlush() {
while(networkSendBufferStartPos!=networkSendBufferEndPos) { while(networkSendBufferStartPos!=networkSendBufferEndPos) {
svcSleepThread(4500 * 1000); svcSleepThread(4500 * 1000);
} }
} }

View file

@ -5,359 +5,347 @@
FILE *recvFile; FILE *recvFile;
size_t recvFileSize; size_t recvFileSize;
void * writeBool(void *buffer, size_t *size, bool value) { void * writeBool(void *buffer, size_t *size, bool value) {
*((bool*) buffer) = value; *((bool*) buffer) = value;
*(size) += sizeof(bool); *(size) += sizeof(bool);
return buffer + sizeof(bool); return buffer + sizeof(bool);
} }
void * writeU8(void *buffer, size_t *size, u8 value) { void * writeU8(void *buffer, size_t *size, u8 value) {
*((u8*) buffer) = value; *((u8*) buffer) = value;
*(size) += sizeof(u8); *(size) += sizeof(u8);
return buffer + sizeof(u8); return buffer + sizeof(u8);
} }
void * writeU16(void *buffer, size_t *size, u16 value) { void * writeU16(void *buffer, size_t *size, u16 value) {
*((u16*) buffer) = value; *((u16*) buffer) = value;
*(size) += sizeof(u16); *(size) += sizeof(u16);
return buffer + sizeof(u16); return buffer + sizeof(u16);
} }
void * writeU32(void *buffer, size_t *size, u32 value) { void * writeU32(void *buffer, size_t *size, u32 value) {
*((u32*) buffer) = value; *((u32*) buffer) = value;
*(size) += sizeof(u32); *(size) += sizeof(u32);
return buffer + sizeof(u32); return buffer + sizeof(u32);
} }
void * writeSizeT(void *buffer, size_t *size, size_t value) { void * writeSizeT(void *buffer, size_t *size, size_t value) {
*((size_t*) buffer) = value; *((size_t*) buffer) = value;
*(size) += sizeof(size_t); *(size) += sizeof(size_t);
return buffer + sizeof(size_t); return buffer + sizeof(size_t);
} }
void * readBool(void *buffer, size_t *size, bool *value) { void * readBool(void *buffer, size_t *size, bool *value) {
*value = *((bool*) buffer); *value = *((bool*) buffer);
*(size) -= sizeof(bool); *(size) -= sizeof(bool);
return buffer + sizeof(bool); return buffer + sizeof(bool);
} }
void * readU8(void *buffer, size_t *size, u8 *value) { void * readU8(void *buffer, size_t *size, u8 *value) {
*value = *((u8*) buffer); *value = *((u8*) buffer);
*(size) -= sizeof(u8); *(size) -= sizeof(u8);
return buffer + sizeof(u8); return buffer + sizeof(u8);
} }
void * readU16(void *buffer, size_t *size, u16 *value) { void * readU16(void *buffer, size_t *size, u16 *value) {
*value = *((u16*) buffer); *value = *((u16*) buffer);
*(size) -= sizeof(u16); *(size) -= sizeof(u16);
return buffer + sizeof(u16); return buffer + sizeof(u16);
} }
void * readU32(void *buffer, size_t *size, u32 *value) { void * readU32(void *buffer, size_t *size, u32 *value) {
*value = *((u32*) buffer); *value = *((u32*) buffer);
*(size) -= sizeof(u32); *(size) -= sizeof(u32);
return buffer + sizeof(u32); return buffer + sizeof(u32);
} }
void * readSizeT(void *buffer, size_t *size, size_t *value) { void * readSizeT(void *buffer, size_t *size, size_t *value) {
*value = *((size_t*) buffer); *value = *((size_t*) buffer);
*(size) -= sizeof(size_t); *(size) -= sizeof(size_t);
return buffer + sizeof(size_t); return buffer + sizeof(size_t);
} }
void processPacket(void *packet, size_t size) { void processPacket(void *packet, size_t size) {
//Differenciate the packets and process them //Differenciate the packets and process them
switch(packetGetID(packet)) { switch(packetGetID(packet)) {
case PACKET_START: { case PACKET_START: {
void *buffer = packetGetDataStart(packet); void *buffer = packetGetDataStart(packet);
size = packetGetDataSize(size); size = packetGetDataSize(size);
//find player index based on network node id //find player index based on network node id
//and set player uuid in synchronizer //and set player uuid in synchronizer
u32 seed; u32 seed;
u32 playerCount = 1; u32 playerCount = 1;
int playerIndex = 0; int playerIndex = 0;
buffer = readU32(buffer, &size, &seed); buffer = readU32(buffer, &size, &seed);
buffer = readU32(buffer, &size, &playerCount); buffer = readU32(buffer, &size, &playerCount);
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
u16 nodeID; u16 nodeID;
buffer = readU16(buffer, &size, &nodeID); buffer = readU16(buffer, &size, &nodeID);
if(nodeID==networkGetLocalNodeID()) { if(nodeID==networkGetLocalNodeID()) {
playerIndex = i; playerIndex = i;
} }
} }
//cleanup transfer tmp file //cleanup transfer tmp file
FILE *file = fopen("tmpTransfer.bin", "wb"); FILE *file = fopen("tmpTransfer.bin", "wb");
if(file!=NULL) { if(file!=NULL) {
fclose(file); fclose(file);
remove("tmpTransfer.bin"); remove("tmpTransfer.bin");
} }
//init synchronizer //init synchronizer
synchronizerInit(seed, playerCount, playerIndex); synchronizerInit(seed, playerCount, playerIndex);
break; break;
} }
case PACKET_START_FILEHEADER: { case PACKET_START_FILEHEADER: {
void *data = packetGetDataStart(packet); void *data = packetGetDataStart(packet);
u8 type; u8 type;
u8 id; u8 id;
size_t fsize; size_t fsize;
data = readU8(data, &size, &type); data = readU8(data, &size, &type);
data = readU8(data, &size, &id); data = readU8(data, &size, &id);
data = readSizeT(data, &size, &fsize); data = readSizeT(data, &size, &fsize);
recvFile = fopen("tmpTransfer.bin", "wb"); recvFile = fopen("tmpTransfer.bin", "wb");
recvFileSize = fsize; recvFileSize = fsize;
break; break;
} }
case PACKET_START_FILEDATA: { case PACKET_START_FILEDATA: {
void *data = packetGetDataStart(packet); void *data = packetGetDataStart(packet);
size_t dsize = packetGetDataSize(size); size_t dsize = packetGetDataSize(size);
size_t toread = dsize; size_t toread = dsize;
fwrite(data, 1, toread, recvFile); fwrite(data, 1, toread, recvFile);
recvFileSize -= toread; recvFileSize -= toread;
if(recvFileSize<=0) { if(recvFileSize<=0) {
fclose(recvFile); fclose(recvFile);
recvFile = NULL; recvFile = NULL;
} }
break; break;
} }
case PACKET_START_REQUEST_IDS: { case PACKET_START_REQUEST_IDS: {
synchronizerSendUID(); synchronizerSendUID();
break; break;
} }
case PACKET_START_ID: { case PACKET_START_ID: {
u8 playerID = packetGetSender(packet); u8 playerID = packetGetSender(packet);
u32 uid; u32 uid;
void *data = packetGetDataStart(packet); void *data = packetGetDataStart(packet);
size_t dsize = packetGetDataSize(size); size_t dsize = packetGetDataSize(size);
data = readU32(data, &dsize, &uid); data = readU32(data, &dsize, &uid);
synchronizerSetPlayerUID(playerID, uid); synchronizerSetPlayerUID(playerID, uid);
synchronizerSendIfReady(); synchronizerSendIfReady();
break; break;
} }
case PACKET_START_READY: { case PACKET_START_READY: {
synchronizerSetPlayerReady(packetGetSender(packet)); synchronizerSetPlayerReady(packetGetSender(packet));
if(playerLocalID==0) { if(playerLocalID==0) {
if(synchronizerAllReady()) { if(synchronizerAllReady()) {
sendStartSyncPacket(); sendStartSyncPacket();
synchronizerStart(); //server needs to call this here, all others do when they recieve the packet synchronizerStart(); //server needs to call this here, all others do when they recieve the packet
} }
} }
break; break;
} }
case PACKET_TURN_START: { case PACKET_TURN_START: {
synchronizerStart(); synchronizerStart();
break; break;
} }
case PACKET_TURN_INPUT: { case PACKET_TURN_INPUT: {
synchronizerOnInputPacket(packetGetSender(packet), packetGetTurn(packet), packetGetDataStart(packet), packetGetDataSize(size)); synchronizerOnInputPacket(packetGetSender(packet), packetGetTurn(packet), packetGetDataStart(packet), packetGetDataSize(size));
break; break;
} }
} }
} }
u8 packetGetID(void *packet) { u8 packetGetID(void *packet) {
return *((u8*) packet); return *((u8*) packet);
} }
u8 packetGetSender(void *packet) { u8 packetGetSender(void *packet) {
return *((u8*) packet+sizeof(u8)); return *((u8*) packet+sizeof(u8));
} }
u32 packetGetTurn(void *packet) { u32 packetGetTurn(void *packet) {
return *((u32*) (packet+sizeof(u8)+sizeof(u8))); return *((u32*) (packet+sizeof(u8)+sizeof(u8)));
} }
void * packetGetDataStart(void *packet) { void * packetGetDataStart(void *packet) {
return packet+sizeof(u8)+sizeof(u8)+sizeof(u32); return packet+sizeof(u8)+sizeof(u8)+sizeof(u32);
} }
size_t packetGetDataSize(size_t size) { size_t packetGetDataSize(size_t size) {
return size-sizeof(u8)-sizeof(u8)-sizeof(u32); return size-sizeof(u8)-sizeof(u8)-sizeof(u32);
} }
size_t writeStartPacket(void *buffer, u32 seed) { size_t writeStartPacket(void *buffer, u32 seed) {
size_t size = 0; size_t size = 0;
buffer = writeU8(buffer, &size, PACKET_START); buffer = writeU8(buffer, &size, PACKET_START);
buffer = writeU8(buffer, &size, 0); buffer = writeU8(buffer, &size, 0);
buffer = writeU32(buffer, &size, 0); buffer = writeU32(buffer, &size, 0);
buffer = writeU32(buffer, &size, seed); buffer = writeU32(buffer, &size, seed);
buffer = writeU32(buffer, &size, (u32)networkGetNodeCount()); buffer = writeU32(buffer, &size, (u32)networkGetNodeCount());
for(int i=1; i<=UDS_MAXNODES; i++) { for(int i=1; i<=UDS_MAXNODES; i++) {
if(networkIsNodeConnected(i)) { if(networkIsNodeConnected(i)) {
buffer = writeU16(buffer, &size, (u16)i); buffer = writeU16(buffer, &size, (u16)i);
} }
} }
return size; return size;
} }
size_t writeStartRequestPacket(void *buffer) { size_t writeStartRequestPacket(void *buffer) {
size_t size = 0; size_t size = 0;
buffer = writeU8(buffer, &size, PACKET_START_REQUEST_IDS); buffer = writeU8(buffer, &size, PACKET_START_REQUEST_IDS);
buffer = writeU8(buffer, &size, 0); buffer = writeU8(buffer, &size, 0);
buffer = writeU32(buffer, &size, 0); buffer = writeU32(buffer, &size, 0);
return size; return size;
} }
size_t writeInputPacket(void *buffer, Inputs *inputs, u8 playerID, u32 turnNumber) { size_t writeInputPacket(void *buffer, Inputs *inputs, u8 playerID, u32 turnNumber) {
size_t size = 0; size_t size = 0;
buffer = writeU8(buffer, &size, PACKET_TURN_INPUT); buffer = writeU8(buffer, &size, PACKET_TURN_INPUT);
buffer = writeU8(buffer, &size, playerID); buffer = writeU8(buffer, &size, playerID);
buffer = writeU32(buffer, &size, turnNumber); buffer = writeU32(buffer, &size, turnNumber);
buffer = writeU16(buffer, &size, inputs->k_touch.px); buffer = writeU16(buffer, &size, inputs->k_touch.px);
buffer = writeU16(buffer, &size, inputs->k_touch.py); buffer = writeU16(buffer, &size, inputs->k_touch.py);
buffer = writeBool(buffer, &size, inputs->k_up.down); buffer = writeBool(buffer, &size, inputs->k_up.clicked); buffer = writeBool(buffer, &size, inputs->k_up.down); buffer = writeBool(buffer, &size, inputs->k_up.clicked);
buffer = writeBool(buffer, &size, inputs->k_down.down); buffer = writeBool(buffer, &size, inputs->k_down.clicked); buffer = writeBool(buffer, &size, inputs->k_down.down); buffer = writeBool(buffer, &size, inputs->k_down.clicked);
buffer = writeBool(buffer, &size, inputs->k_left.down); buffer = writeBool(buffer, &size, inputs->k_left.clicked); buffer = writeBool(buffer, &size, inputs->k_left.down); buffer = writeBool(buffer, &size, inputs->k_left.clicked);
buffer = writeBool(buffer, &size, inputs->k_right.down); buffer = writeBool(buffer, &size, inputs->k_right.clicked); buffer = writeBool(buffer, &size, inputs->k_right.down); buffer = writeBool(buffer, &size, inputs->k_right.clicked);
buffer = writeBool(buffer, &size, inputs->k_attack.down); buffer = writeBool(buffer, &size, inputs->k_attack.clicked); buffer = writeBool(buffer, &size, inputs->k_attack.down); buffer = writeBool(buffer, &size, inputs->k_attack.clicked);
buffer = writeBool(buffer, &size, inputs->k_menu.down); buffer = writeBool(buffer, &size, inputs->k_menu.clicked); buffer = writeBool(buffer, &size, inputs->k_menu.down); buffer = writeBool(buffer, &size, inputs->k_menu.clicked);
buffer = writeBool(buffer, &size, inputs->k_pause.down); buffer = writeBool(buffer, &size, inputs->k_pause.clicked); buffer = writeBool(buffer, &size, inputs->k_pause.down); buffer = writeBool(buffer, &size, inputs->k_pause.clicked);
buffer = writeBool(buffer, &size, inputs->k_accept.down); buffer = writeBool(buffer, &size, inputs->k_accept.clicked); buffer = writeBool(buffer, &size, inputs->k_accept.down); buffer = writeBool(buffer, &size, inputs->k_accept.clicked);
buffer = writeBool(buffer, &size, inputs->k_decline.down); buffer = writeBool(buffer, &size, inputs->k_decline.clicked); buffer = writeBool(buffer, &size, inputs->k_decline.down); buffer = writeBool(buffer, &size, inputs->k_decline.clicked);
buffer = writeBool(buffer, &size, inputs->k_delete.down); buffer = writeBool(buffer, &size, inputs->k_delete.clicked); buffer = writeBool(buffer, &size, inputs->k_delete.down); buffer = writeBool(buffer, &size, inputs->k_delete.clicked);
buffer = writeBool(buffer, &size, inputs->k_menuNext.down); buffer = writeBool(buffer, &size, inputs->k_menuNext.clicked); buffer = writeBool(buffer, &size, inputs->k_menuNext.down); buffer = writeBool(buffer, &size, inputs->k_menuNext.clicked);
buffer = writeBool(buffer, &size, inputs->k_menuPrev.down); buffer = writeBool(buffer, &size, inputs->k_menuPrev.clicked); buffer = writeBool(buffer, &size, inputs->k_menuPrev.down); buffer = writeBool(buffer, &size, inputs->k_menuPrev.clicked);
return size; return size;
} }
bool readInputPacketData(void *buffer, size_t size, Inputs *inputs) { bool readInputPacketData(void *buffer, size_t size, Inputs *inputs) {
buffer = readU16(buffer, &size, &(inputs->k_touch.px)); buffer = readU16(buffer, &size, &(inputs->k_touch.px));
if(size<=0) return false; if(size<=0) return false;
buffer = readU16(buffer, &size, &(inputs->k_touch.py)); buffer = readU16(buffer, &size, &(inputs->k_touch.py));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_up.down)); buffer = readBool(buffer, &size, &(inputs->k_up.clicked)); buffer = readBool(buffer, &size, &(inputs->k_up.down)); buffer = readBool(buffer, &size, &(inputs->k_up.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_down.down)); buffer = readBool(buffer, &size, &(inputs->k_down.clicked)); buffer = readBool(buffer, &size, &(inputs->k_down.down)); buffer = readBool(buffer, &size, &(inputs->k_down.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_left.down)); buffer = readBool(buffer, &size, &(inputs->k_left.clicked)); buffer = readBool(buffer, &size, &(inputs->k_left.down)); buffer = readBool(buffer, &size, &(inputs->k_left.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_right.down)); buffer = readBool(buffer, &size, &(inputs->k_right.clicked)); buffer = readBool(buffer, &size, &(inputs->k_right.down)); buffer = readBool(buffer, &size, &(inputs->k_right.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_attack.down)); buffer = readBool(buffer, &size, &(inputs->k_attack.clicked)); buffer = readBool(buffer, &size, &(inputs->k_attack.down)); buffer = readBool(buffer, &size, &(inputs->k_attack.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_menu.down)); buffer = readBool(buffer, &size, &(inputs->k_menu.clicked)); buffer = readBool(buffer, &size, &(inputs->k_menu.down)); buffer = readBool(buffer, &size, &(inputs->k_menu.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_pause.down)); buffer = readBool(buffer, &size, &(inputs->k_pause.clicked)); buffer = readBool(buffer, &size, &(inputs->k_pause.down)); buffer = readBool(buffer, &size, &(inputs->k_pause.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_accept.down)); buffer = readBool(buffer, &size, &(inputs->k_accept.clicked)); buffer = readBool(buffer, &size, &(inputs->k_accept.down)); buffer = readBool(buffer, &size, &(inputs->k_accept.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_decline.down)); buffer = readBool(buffer, &size, &(inputs->k_decline.clicked)); buffer = readBool(buffer, &size, &(inputs->k_decline.down)); buffer = readBool(buffer, &size, &(inputs->k_decline.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_delete.down)); buffer = readBool(buffer, &size, &(inputs->k_delete.clicked)); buffer = readBool(buffer, &size, &(inputs->k_delete.down)); buffer = readBool(buffer, &size, &(inputs->k_delete.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_menuNext.down)); buffer = readBool(buffer, &size, &(inputs->k_menuNext.clicked)); buffer = readBool(buffer, &size, &(inputs->k_menuNext.down)); buffer = readBool(buffer, &size, &(inputs->k_menuNext.clicked));
if(size<=0) return false; if(size<=0) return false;
buffer = readBool(buffer, &size, &(inputs->k_menuPrev.down)); buffer = readBool(buffer, &size, &(inputs->k_menuPrev.clicked)); buffer = readBool(buffer, &size, &(inputs->k_menuPrev.down)); buffer = readBool(buffer, &size, &(inputs->k_menuPrev.clicked));
return size==0; return size==0;
} }
void sendFile(FILE *file, u8 fileType, u8 id) { void sendFile(FILE *file, u8 fileType, u8 id) {
fseek(file, 0, SEEK_END); // seek to end of file fseek(file, 0, SEEK_END); // seek to end of file
size_t fsize = ftell(file); // get current file pointer size_t fsize = ftell(file); // get current file pointer
fseek(file, 0, SEEK_SET); // seek back to beginning of file fseek(file, 0, SEEK_SET); // seek back to beginning of file
//send file header //send file header
void *buffer = networkWriteBuffer; void *buffer = networkWriteBuffer;
size_t size = 0; size_t size = 0;
buffer = writeU8(buffer, &size, PACKET_START_FILEHEADER); buffer = writeU8(buffer, &size, PACKET_START_FILEHEADER);
buffer = writeU8(buffer, &size, 0); buffer = writeU8(buffer, &size, 0);
buffer = writeU32(buffer, &size, 0); buffer = writeU32(buffer, &size, 0);
buffer = writeU8(buffer, &size, fileType); buffer = writeU8(buffer, &size, fileType);
buffer = writeU8(buffer, &size, id); buffer = writeU8(buffer, &size, id);
buffer = writeSizeT(buffer, &size, fsize); buffer = writeSizeT(buffer, &size, fsize);
networkSend(networkWriteBuffer, size); networkSend(networkWriteBuffer, size);
//send file data //send file data
while(fsize>0) { while(fsize>0) {
buffer = networkWriteBuffer; buffer = networkWriteBuffer;
size = 0; size = 0;
buffer = writeU8(buffer, &size, PACKET_START_FILEDATA); buffer = writeU8(buffer, &size, PACKET_START_FILEDATA);
buffer = writeU8(buffer, &size, 0); buffer = writeU8(buffer, &size, 0);
buffer = writeU32(buffer, &size, 0); buffer = writeU32(buffer, &size, 0);
//read file data //read file data
size_t towrite = NETWORK_MAXDATASIZE - size; size_t towrite = NETWORK_MAXDATASIZE - size;
if(towrite>fsize) towrite = fsize; if(towrite>fsize) towrite = fsize;
fread(buffer, 1, towrite, file); fread(buffer, 1, towrite, file);
size += towrite; size += towrite;
fsize -= towrite; fsize -= towrite;
//send file data //send file data
networkSend(networkWriteBuffer, size); networkSend(networkWriteBuffer, size);
} }
} }
void sendIDPacket(u8 playerID, u32 uid) { void sendIDPacket(u8 playerID, u32 uid) {
void *buffer = networkWriteBuffer; void *buffer = networkWriteBuffer;
size_t size = 0; size_t size = 0;
buffer = writeU8(buffer, &size, PACKET_START_ID); buffer = writeU8(buffer, &size, PACKET_START_ID);
buffer = writeU8(buffer, &size, playerID); buffer = writeU8(buffer, &size, playerID);
buffer = writeU32(buffer, &size, 0); buffer = writeU32(buffer, &size, 0);
buffer = writeU32(buffer, &size, uid); buffer = writeU32(buffer, &size, uid);
networkSend(networkWriteBuffer, size); networkSend(networkWriteBuffer, size);
} }
void sendStartReadyPacket(u8 playerID) { void sendStartReadyPacket(u8 playerID) {
void *buffer = networkWriteBuffer; void *buffer = networkWriteBuffer;
size_t size = 0; size_t size = 0;
buffer = writeU8(buffer, &size, PACKET_START_READY); buffer = writeU8(buffer, &size, PACKET_START_READY);
buffer = writeU8(buffer, &size, playerID); buffer = writeU8(buffer, &size, playerID);
buffer = writeU32(buffer, &size, 0); buffer = writeU32(buffer, &size, 0);
networkSend(networkWriteBuffer, size); networkSend(networkWriteBuffer, size);
} }
void sendStartSyncPacket() { void sendStartSyncPacket() {
void *buffer = networkWriteBuffer; void *buffer = networkWriteBuffer;
size_t size = 0; size_t size = 0;
buffer = writeU8(buffer, &size, PACKET_TURN_START); buffer = writeU8(buffer, &size, PACKET_TURN_START);
buffer = writeU8(buffer, &size, 0); buffer = writeU8(buffer, &size, 0);
buffer = writeU32(buffer, &size, 0); buffer = writeU32(buffer, &size, 0);
networkSend(networkWriteBuffer, size); networkSend(networkWriteBuffer, size);
} }

View file

@ -19,15 +19,15 @@ void potionEffect(int type) {
} }
void initPlayers() { void initPlayers() {
for(int i=0; i<MAX_PLAYERS; i++) { for(int i=0; i<MAX_PLAYERS; i++) {
initPlayer(players+i); initPlayer(players+i);
} }
} }
void freePlayers() { void freePlayers() {
for(int i=0; i<MAX_PLAYERS; i++) { for(int i=0; i<MAX_PLAYERS; i++) {
freePlayer(players+i); freePlayer(players+i);
} }
} }
void playerInitMiniMapData(u8 *minimapData) { void playerInitMiniMapData(u8 *minimapData) {
@ -38,286 +38,286 @@ void playerInitMiniMapData(u8 *minimapData) {
} }
void playerInitEntity(PlayerData *pd) { void playerInitEntity(PlayerData *pd) {
pd->entity.type = ENTITY_PLAYER; pd->entity.type = ENTITY_PLAYER;
pd->entity.level = 1; pd->entity.level = 1;
pd->entity.xr = 4; pd->entity.xr = 4;
pd->entity.yr = 3; pd->entity.yr = 3;
pd->entity.canSwim = true; pd->entity.canSwim = true;
pd->entity.p.ax = 0; pd->entity.p.ax = 0;
pd->entity.p.ay = 0; pd->entity.p.ay = 0;
pd->entity.p.health = 10; pd->entity.p.health = 10;
pd->entity.p.stamina = 10; pd->entity.p.stamina = 10;
pd->entity.p.walkDist = 0; pd->entity.p.walkDist = 0;
pd->entity.p.attackTimer = 0; pd->entity.p.attackTimer = 0;
pd->entity.p.dir = 0; pd->entity.p.dir = 0;
pd->entity.p.isDead = false; pd->entity.p.isDead = false;
pd->entity.p.hasWon = false; pd->entity.p.hasWon = false;
pd->entity.p.data = pd; pd->entity.p.data = pd;
} }
void playerInitInventory(PlayerData *pd) { void playerInitInventory(PlayerData *pd) {
//reset inventory //reset inventory
pd->inventory.lastSlot = 0; pd->inventory.lastSlot = 0;
pd->activeItem = &noItem; pd->activeItem = &noItem;
addItemToInventory(newItem(ITEM_WORKBENCH,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_WORKBENCH,0), &(pd->inventory));
addItemToInventory(newItem(ITEM_POWGLOVE,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_POWGLOVE,0), &(pd->inventory));
if(shouldRenderDebug && playerCount < 2) { if(shouldRenderDebug && playerCount < 2) {
addItemToInventory(newItem(ITEM_GOLD_APPLE,1), &(pd->inventory)); addItemToInventory(newItem(ITEM_GOLD_APPLE,1), &(pd->inventory));
addItemToInventory(newItem(ITEM_STRENGTH_POTION,1), &(pd->inventory)); addItemToInventory(newItem(ITEM_STRENGTH_POTION,1), &(pd->inventory));
addItemToInventory(newItem(ITEM_REGEN_POTION,1), &(pd->inventory)); addItemToInventory(newItem(ITEM_REGEN_POTION,1), &(pd->inventory));
addItemToInventory(newItem(ITEM_SWIM_BREATH_POTION,1), &(pd->inventory)); addItemToInventory(newItem(ITEM_SWIM_BREATH_POTION,1), &(pd->inventory));
addItemToInventory(newItem(ITEM_SPEED_POTION,1), &(pd->inventory)); addItemToInventory(newItem(ITEM_SPEED_POTION,1), &(pd->inventory));
addItemToInventory(newItem(ITEM_POTION_MAKER,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_POTION_MAKER,0), &(pd->inventory));
addItemToInventory(newItem(TOOL_SHOVEL,1), &(pd->inventory)); addItemToInventory(newItem(TOOL_SHOVEL,1), &(pd->inventory));
addItemToInventory(newItem(TOOL_HOE,4), &(pd->inventory)); addItemToInventory(newItem(TOOL_HOE,4), &(pd->inventory));
addItemToInventory(newItem(TOOL_SWORD,4), &(pd->inventory)); addItemToInventory(newItem(TOOL_SWORD,4), &(pd->inventory));
addItemToInventory(newItem(TOOL_PICKAXE,4), &(pd->inventory)); addItemToInventory(newItem(TOOL_PICKAXE,4), &(pd->inventory));
addItemToInventory(newItem(TOOL_AXE,4), &(pd->inventory)); addItemToInventory(newItem(TOOL_AXE,4), &(pd->inventory));
addItemToInventory(newItem(ITEM_ANVIL,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_ANVIL,0), &(pd->inventory));
addItemToInventory(newItem(ITEM_CHEST,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_CHEST,0), &(pd->inventory));
addItemToInventory(newItem(ITEM_OVEN,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_OVEN,0), &(pd->inventory));
addItemToInventory(newItem(ITEM_FURNACE,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_FURNACE,0), &(pd->inventory));
addItemToInventory(newItem(ITEM_LANTERN,0), &(pd->inventory)); addItemToInventory(newItem(ITEM_LANTERN,0), &(pd->inventory));
addItemToInventory(newItem(TOOL_MAGIC_COMPASS,1), &(pd->inventory)); addItemToInventory(newItem(TOOL_MAGIC_COMPASS,1), &(pd->inventory));
int i; int i;
for (i = 7;i < 28;++i) addItemToInventory(newItem(i,50), &(pd->inventory)); for (i = 7;i < 28;++i) addItemToInventory(newItem(i,50), &(pd->inventory));
} }
} }
void playerInitSprite(PlayerData *pd) { void playerInitSprite(PlayerData *pd) {
pd->sprite.choosen = false; pd->sprite.choosen = false;
pd->sprite.legs = 0; pd->sprite.legs = 0;
pd->sprite.body = 0; pd->sprite.body = 0;
pd->sprite.arms = 0; pd->sprite.arms = 0;
pd->sprite.head = 0; pd->sprite.head = 0;
pd->sprite.eyes = 0; pd->sprite.eyes = 0;
} }
void playerInitMenus(PlayerData *pd) { void playerInitMenus(PlayerData *pd) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
pd->ingameMenuSelection = 0; pd->ingameMenuSelection = 0;
pd->ingameMenuInvSel = 0; pd->ingameMenuInvSel = 0;
pd->ingameMenuInvSelOther = 0; pd->ingameMenuInvSelOther = 0;
pd->ingameMenuAreYouSure = false; pd->ingameMenuAreYouSure = false;
pd->ingameMenuAreYouSureSave = false; pd->ingameMenuAreYouSureSave = false;
pd->ingameMenuTimer = 0; pd->ingameMenuTimer = 0;
resetNPCMenuData(&(pd->npcMenuData)); resetNPCMenuData(&(pd->npcMenuData));
pd->mapShouldRender = false; pd->mapShouldRender = false;
pd->mapScrollX = 0; pd->mapScrollX = 0;
pd->mapScrollY = 0; pd->mapScrollY = 0;
pd->mapZoomLevel = 2; pd->mapZoomLevel = 2;
sprintf(pd->mapText,"x%d", pd->mapZoomLevel); sprintf(pd->mapText,"x%d", pd->mapZoomLevel);
pd->touchLastX = -1; pd->touchLastX = -1;
pd->touchLastY = -1; pd->touchLastY = -1;
pd->touchIsDraggingMap = false; pd->touchIsDraggingMap = false;
pd->touchIsChangingSize = false; pd->touchIsChangingSize = false;
} }
void initPlayer(PlayerData *pd) { void initPlayer(PlayerData *pd) {
pd->isSpawned = false; pd->isSpawned = false;
playerInitMiniMapData(pd->minimapData); playerInitMiniMapData(pd->minimapData);
playerInitEntity(pd); playerInitEntity(pd);
playerInitInventory(pd); playerInitInventory(pd);
playerInitSprite(pd); playerInitSprite(pd);
initQuests(&(pd->questManager)); initQuests(&(pd->questManager));
resetQuests(&(pd->questManager)); resetQuests(&(pd->questManager));
playerInitMenus(pd); playerInitMenus(pd);
pd->score = 0; pd->score = 0;
} }
void freePlayer(PlayerData *pd) { void freePlayer(PlayerData *pd) {
freeQuests(&(pd->questManager)); freeQuests(&(pd->questManager));
} }
PlayerData* getNearestPlayer(s8 level, s16 x, s16 y) { PlayerData* getNearestPlayer(s8 level, s16 x, s16 y) {
int nearest = -1; int nearest = -1;
unsigned int nearestDist = UINT_MAX; unsigned int nearestDist = UINT_MAX;
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
if(players[i].entity.level!=level) continue; if(players[i].entity.level!=level) continue;
int xdif = players[i].entity.x - x; int xdif = players[i].entity.x - x;
int ydif = players[i].entity.y - y; int ydif = players[i].entity.y - y;
unsigned int dist = xdif*xdif + ydif*ydif; unsigned int dist = xdif*xdif + ydif*ydif;
if(dist<nearestDist) { if(dist<nearestDist) {
nearest = i; nearest = i;
nearestDist = dist; nearestDist = dist;
} }
} }
if(nearest==-1) return NULL; if(nearest==-1) return NULL;
return players+nearest; return players+nearest;
} }
PlayerData* getLocalPlayer() { PlayerData* getLocalPlayer() {
return players+playerLocalID; return players+playerLocalID;
} }
//player update functions //player update functions
bool playerUseItem(PlayerData *pd) { bool playerUseItem(PlayerData *pd) {
int aitemID = 0; int aitemID = 0;
Item * aitem; Item * aitem;
Item * item ; Item * item ;
switch(pd->activeItem->id){ switch(pd->activeItem->id){
//shooting arrows //shooting arrows
case TOOL_BOW: case TOOL_BOW:
item = getItemFromInventory(ITEM_ARROW_WOOD, &(pd->inventory)); item = getItemFromInventory(ITEM_ARROW_WOOD, &(pd->inventory));
if(item!=NULL) { if(item!=NULL) {
aitemID = ITEM_ARROW_WOOD; aitemID = ITEM_ARROW_WOOD;
aitem = item; aitem = item;
} }
item = getItemFromInventory(ITEM_ARROW_STONE, &(pd->inventory)); item = getItemFromInventory(ITEM_ARROW_STONE, &(pd->inventory));
if(item!=NULL) { if(item!=NULL) {
aitemID = ITEM_ARROW_STONE; aitemID = ITEM_ARROW_STONE;
aitem = item; aitem = item;
} }
item = getItemFromInventory(ITEM_ARROW_IRON, &(pd->inventory)); item = getItemFromInventory(ITEM_ARROW_IRON, &(pd->inventory));
if(item!=NULL) { if(item!=NULL) {
aitemID = ITEM_ARROW_IRON; aitemID = ITEM_ARROW_IRON;
aitem = item; aitem = item;
} }
item = getItemFromInventory(ITEM_ARROW_GOLD, &(pd->inventory)); item = getItemFromInventory(ITEM_ARROW_GOLD, &(pd->inventory));
if(item!=NULL) { if(item!=NULL) {
aitemID = ITEM_ARROW_GOLD; aitemID = ITEM_ARROW_GOLD;
aitem = item; aitem = item;
} }
item = getItemFromInventory(ITEM_ARROW_GEM, &(pd->inventory)); item = getItemFromInventory(ITEM_ARROW_GEM, &(pd->inventory));
if(item!=NULL) { if(item!=NULL) {
aitemID = ITEM_ARROW_GEM; aitemID = ITEM_ARROW_GEM;
aitem = item; aitem = item;
} }
if(aitemID!=0) { if(aitemID!=0) {
--aitem->countLevel; --aitem->countLevel;
if (isItemEmpty(aitem)) { if (isItemEmpty(aitem)) {
removeItemFromInventory(aitem->slotNum, &(pd->inventory)); removeItemFromInventory(aitem->slotNum, &(pd->inventory));
} }
switch(pd->entity.p.dir) { switch(pd->entity.p.dir) {
case 0: case 0:
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, 2, pd->entity.level), &eManager); addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, 2, pd->entity.level), &eManager);
break; break;
case 1: case 1:
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, -2, pd->entity.level), &eManager); addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, -2, pd->entity.level), &eManager);
break; break;
case 2: case 2:
addEntityToList(newArrowEntity(&(pd->entity), aitemID, -2, 0, pd->entity.level), &eManager); addEntityToList(newArrowEntity(&(pd->entity), aitemID, -2, 0, pd->entity.level), &eManager);
break; break;
case 3: case 3:
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 2, 0, pd->entity.level), &eManager); addEntityToList(newArrowEntity(&(pd->entity), aitemID, 2, 0, pd->entity.level), &eManager);
break; break;
} }
return true; return true;
} }
break; break;
// Health items // Health items
case ITEM_APPLE: case ITEM_APPLE:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 2)){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 2)){
playerHeal(pd, 1); playerHeal(pd, 1);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
break; break;
case ITEM_STRENGTH_POTION: case ITEM_STRENGTH_POTION:
if(pd->entity.p.health < 20 && pd->entity.p.strengthTimer == 0){ if(pd->entity.p.health < 20 && pd->entity.p.strengthTimer == 0){
potionEffect(1); potionEffect(1);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
return 0; return 0;
case ITEM_SPEED_POTION: case ITEM_SPEED_POTION:
if(pd->entity.p.health < 20 && pd->entity.p.speedTimer == 0){ if(pd->entity.p.health < 20 && pd->entity.p.speedTimer == 0){
potionEffect(2); potionEffect(2);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
return 0; return 0;
case ITEM_REGEN_POTION: case ITEM_REGEN_POTION:
if(pd->entity.p.health < 20 && pd->entity.p.regenTimer == 0){ if(pd->entity.p.health < 20 && pd->entity.p.regenTimer == 0){
potionEffect(3); potionEffect(3);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
return 0; return 0;
case ITEM_SWIM_BREATH_POTION: case ITEM_SWIM_BREATH_POTION:
if(pd->entity.p.health < 20 && pd->entity.p.swimBreathTimer == 0){ if(pd->entity.p.health < 20 && pd->entity.p.swimBreathTimer == 0){
potionEffect(4); potionEffect(4);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
return 0; return 0;
case ITEM_GOLD_APPLE: case ITEM_GOLD_APPLE:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 1)){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 1)){
playerHeal(pd, 8); playerHeal(pd, 8);
playerUseEnergy(pd, -10); playerUseEnergy(pd, -10);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
return 0; return 0;
case ITEM_FLESH: case ITEM_FLESH:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
playerHeal(pd, 1); playerHeal(pd, 1);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
break; break;
case ITEM_BREAD: case ITEM_BREAD:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
playerHeal(pd, 2); playerHeal(pd, 2);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
break; break;
case ITEM_PORK_RAW: case ITEM_PORK_RAW:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
playerHeal(pd, 1); playerHeal(pd, 1);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
break; break;
case ITEM_PORK_COOKED: case ITEM_PORK_COOKED:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
playerHeal(pd, 3); playerHeal(pd, 3);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
break; break;
case ITEM_BEEF_RAW: case ITEM_BEEF_RAW:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
playerHeal(pd, 1); playerHeal(pd, 1);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
break; break;
case ITEM_BEEF_COOKED: case ITEM_BEEF_COOKED:
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){ if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
playerHeal(pd, 4); playerHeal(pd, 4);
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
} }
break; break;
//special item //special item
case ITEM_WIZARD_SUMMON: case ITEM_WIZARD_SUMMON:
if(pd->entity.level==0) { if(pd->entity.level==0) {
--(pd->activeItem->countLevel); --(pd->activeItem->countLevel);
airWizardHealthDisplay = 2000; airWizardHealthDisplay = 2000;
addEntityToList(newAirWizardEntity(630, 820, 0), &eManager); addEntityToList(newAirWizardEntity(630, 820, 0), &eManager);
} }
break; break;
} }
if (isItemEmpty(pd->activeItem)) { if (isItemEmpty(pd->activeItem)) {
removeItemFromInventory(pd->activeItem->slotNum, &(pd->inventory)); removeItemFromInventory(pd->activeItem->slotNum, &(pd->inventory));
pd->activeItem = &noItem; pd->activeItem = &noItem;
} }
return false; return false;
} }
@ -329,28 +329,28 @@ bool playerInteract(PlayerData *pd, int x0, int y0, int x1, int y1) {
for (i = 0; i < eSize; ++i) { for (i = 0; i < eSize; ++i) {
Entity * ent = es[i]; Entity * ent = es[i];
if (ent != &(pd->entity)){ if (ent != &(pd->entity)){
if (ItemVsEntity(pd, pd->activeItem, ent, pd->entity.p.dir)) return true; if (ItemVsEntity(pd, pd->activeItem, ent, pd->entity.p.dir)) return true;
} }
} }
return false; return false;
} }
void playerAttack(PlayerData *pd) { void playerAttack(PlayerData *pd) {
bool done = false; bool done = false;
pd->entity.p.attackTimer = 5; pd->entity.p.attackTimer = 5;
int yo = -2; int yo = -2;
int range = 12; int range = 12;
//directly using an item //directly using an item
if(playerUseItem(pd)) return; if(playerUseItem(pd)) return;
//interacting with entities //interacting with entities
switch(pd->entity.p.dir){ switch(pd->entity.p.dir){
case 0: if(playerInteract(pd, pd->entity.x - 8, pd->entity.y + 4 + yo, pd->entity.x + 8, pd->entity.y + range + yo)) return; break; case 0: if(playerInteract(pd, pd->entity.x - 8, pd->entity.y + 4 + yo, pd->entity.x + 8, pd->entity.y + range + yo)) return; break;
case 1: if(playerInteract(pd, pd->entity.x - 8, pd->entity.y - range + yo, pd->entity.x + 8, pd->entity.y - 4 + yo)) return; break; case 1: if(playerInteract(pd, pd->entity.x - 8, pd->entity.y - range + yo, pd->entity.x + 8, pd->entity.y - 4 + yo)) return; break;
case 2: if(playerInteract(pd, pd->entity.x - range, pd->entity.y - 8 + yo, pd->entity.x - 4, pd->entity.y + 8 + yo)) return; break; case 2: if(playerInteract(pd, pd->entity.x - range, pd->entity.y - 8 + yo, pd->entity.x - 4, pd->entity.y + 8 + yo)) return; break;
case 3: if(playerInteract(pd, pd->entity.x + 4, pd->entity.y - 8 + yo, pd->entity.x + range, pd->entity.y + 8 + yo)) return; break; case 3: if(playerInteract(pd, pd->entity.x + 4, pd->entity.y - 8 + yo, pd->entity.x + range, pd->entity.y + 8 + yo)) return; break;
} }
int xt = pd->entity.x >> 4; int xt = pd->entity.x >> 4;
int yt = (pd->entity.y + yo) >> 4; int yt = (pd->entity.y + yo) >> 4;
@ -360,13 +360,13 @@ void playerAttack(PlayerData *pd) {
if (pd->entity.p.dir == 2) xt = (pd->entity.x - r) >> 4; if (pd->entity.p.dir == 2) xt = (pd->entity.x - r) >> 4;
if (pd->entity.p.dir == 3) xt = (pd->entity.x + r) >> 4; if (pd->entity.p.dir == 3) xt = (pd->entity.x + r) >> 4;
//interacting with tiles //interacting with tiles
if (xt >= 0 && yt >= 0 && xt < 128 && yt < 128) { if (xt >= 0 && yt >= 0 && xt < 128 && yt < 128) {
s8 itract = itemTileInteract(getTile(pd->entity.level, xt, yt), pd, pd->activeItem, pd->entity.level, xt, yt, pd->entity.x, pd->entity.y, pd->entity.p.dir); s8 itract = itemTileInteract(getTile(pd->entity.level, xt, yt), pd, pd->activeItem, pd->entity.level, xt, yt, pd->entity.x, pd->entity.y, pd->entity.p.dir);
if(itract > 0){ if(itract > 0){
if(itract==2) pd->entity.p.isCarrying = false; if(itract==2) pd->entity.p.isCarrying = false;
done = true; done = true;
} }
if (pd->activeItem != &noItem && isItemEmpty(pd->activeItem)) { if (pd->activeItem != &noItem && isItemEmpty(pd->activeItem)) {
removeItemFromInventory(pd->activeItem->slotNum, &(pd->inventory)); removeItemFromInventory(pd->activeItem->slotNum, &(pd->inventory));
@ -376,21 +376,21 @@ void playerAttack(PlayerData *pd) {
if(done) return; if(done) return;
//breaking tiles //breaking tiles
if (pd->activeItem == &noItem || pd->activeItem->id == TOOL_SWORD || pd->activeItem->id == TOOL_AXE) { if (pd->activeItem == &noItem || pd->activeItem->id == TOOL_SWORD || pd->activeItem->id == TOOL_AXE) {
if (xt >= 0 && yt >= 0 && xt < 128 && 128) { if (xt >= 0 && yt >= 0 && xt < 128 && 128) {
playerHurtTile(pd, getTile(pd->entity.level, xt, yt), pd->entity.level, xt, yt, (rand()%3) + 1, pd->entity.p.dir); playerHurtTile(pd, getTile(pd->entity.level, xt, yt), pd->entity.level, xt, yt, (rand()%3) + 1, pd->entity.p.dir);
} }
} }
} }
bool playerUseArea(PlayerData *pd, int x0, int y0, int x1, int y1) { bool playerUseArea(PlayerData *pd, int x0, int y0, int x1, int y1) {
Entity * entities[eManager.lastSlot[pd->entity.level]]; Entity * entities[eManager.lastSlot[pd->entity.level]];
int i; int i;
int ae = getEntities(entities, pd->entity.level, x0, y0, x1, y1); int ae = getEntities(entities, pd->entity.level, x0, y0, x1, y1);
for(i = 0; i < ae; ++i){ for(i = 0; i < ae; ++i){
if(useEntity(pd, entities[i])) return true; if(useEntity(pd, entities[i])) return true;
} }
return false; return false;
} }
@ -404,14 +404,14 @@ bool playerUse(PlayerData *pd) {
} }
void tickPlayer(PlayerData *pd, bool inmenu) { void tickPlayer(PlayerData *pd, bool inmenu) {
if (pd->entity.p.isDead) return; if (pd->entity.p.isDead) return;
//invincibility time //invincibility time
if (pd->entity.hurtTime > 0) pd->entity.hurtTime--; if (pd->entity.hurtTime > 0) pd->entity.hurtTime--;
//stamina recharging //stamina recharging
bool swimming = isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4); bool swimming = isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4);
if (pd->entity.p.stamina <= 0 && pd->entity.p.staminaRechargeDelay == 0 && pd->entity.p.staminaRecharge == 0) { if (pd->entity.p.stamina <= 0 && pd->entity.p.staminaRechargeDelay == 0 && pd->entity.p.staminaRecharge == 0) {
pd->entity.p.staminaRechargeDelay = 40; pd->entity.p.staminaRechargeDelay = 40;
} }
@ -429,18 +429,18 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
} }
} }
if(!inmenu) { if(!inmenu) {
if(!pd->sprite.choosen) { if(!pd->sprite.choosen) {
pd->ingameMenu = MENU_CHARACTER_CUSTOMIZE; pd->ingameMenu = MENU_CHARACTER_CUSTOMIZE;
pd->ingameMenuSelection = 0; pd->ingameMenuSelection = 0;
return; return;
} }
//movement //movement
pd->entity.p.ax = 0; pd->entity.p.ax = 0;
pd->entity.p.ay = 0; pd->entity.p.ay = 0;
if (pd->inputs.k_left.down){ if (pd->inputs.k_left.down){
if(UnderSpeedEffect) { if(UnderSpeedEffect) {
pd->entity.p.ax -= 2; pd->entity.p.ax -= 2;
pd->entity.p.dir = 2; pd->entity.p.dir = 2;
@ -451,9 +451,9 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
pd->entity.p.dir = 2; pd->entity.p.dir = 2;
++pd->entity.p.walkDist; ++pd->entity.p.walkDist;
} }
} }
if (pd->inputs.k_right.down){ if (pd->inputs.k_right.down){
if(UnderSpeedEffect) { if(UnderSpeedEffect) {
pd->entity.p.ax += 2; pd->entity.p.ax += 2;
pd->entity.p.dir = 3; pd->entity.p.dir = 3;
++pd->entity.p.walkDist; ++pd->entity.p.walkDist;
@ -463,9 +463,9 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
pd->entity.p.dir = 3; pd->entity.p.dir = 3;
++pd->entity.p.walkDist; ++pd->entity.p.walkDist;
} }
} }
if (pd->inputs.k_up.down){ if (pd->inputs.k_up.down){
if(UnderSpeedEffect) { if(UnderSpeedEffect) {
pd->entity.p.ay -= 2; pd->entity.p.ay -= 2;
pd->entity.p.dir = 1; pd->entity.p.dir = 1;
++pd->entity.p.walkDist; ++pd->entity.p.walkDist;
@ -475,9 +475,9 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
pd->entity.p.dir = 1; pd->entity.p.dir = 1;
++pd->entity.p.walkDist; ++pd->entity.p.walkDist;
} }
} }
if (pd->inputs.k_down.down){ if (pd->inputs.k_down.down){
if(UnderSpeedEffect) { if(UnderSpeedEffect) {
pd->entity.p.ay += 2; pd->entity.p.ay += 2;
pd->entity.p.dir = 0; pd->entity.p.dir = 0;
++pd->entity.p.walkDist; ++pd->entity.p.walkDist;
@ -487,37 +487,37 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
pd->entity.p.dir = 0; pd->entity.p.dir = 0;
++pd->entity.p.walkDist; ++pd->entity.p.walkDist;
} }
} }
if (pd->entity.p.staminaRechargeDelay % 2 == 0) moveMob(&(pd->entity), pd->entity.p.ax, pd->entity.p.ay); if (pd->entity.p.staminaRechargeDelay % 2 == 0) moveMob(&(pd->entity), pd->entity.p.ax, pd->entity.p.ay);
//"pausing", TODO: since multiplayer this will no longer pause //"pausing", TODO: since multiplayer this will no longer pause
if (pd->inputs.k_pause.clicked){ if (pd->inputs.k_pause.clicked){
pd->ingameMenuSelection = 0; pd->ingameMenuSelection = 0;
pd->ingameMenu = MENU_PAUSED; pd->ingameMenu = MENU_PAUSED;
} }
//attacking //attacking
if(pd->inputs.k_attack.clicked){ if(pd->inputs.k_attack.clicked){
if (pd->entity.p.stamina != 0) { if (pd->entity.p.stamina != 0) {
if(!shouldRenderDebug) pd->entity.p.stamina--; if(!shouldRenderDebug) pd->entity.p.stamina--;
pd->entity.p.staminaRecharge = 0; pd->entity.p.staminaRecharge = 0;
playerAttack(pd); playerAttack(pd);
} }
} }
if (pd->inputs.k_menu.clicked){ if (pd->inputs.k_menu.clicked){
pd->ingameMenuInvSel = 0; pd->ingameMenuInvSel = 0;
if(!playerUse(pd)) pd->ingameMenu = MENU_INVENTORY; if(!playerUse(pd)) pd->ingameMenu = MENU_INVENTORY;
} }
} }
//swimming stamina and drowning //swimming stamina and drowning
if (swimming && pd->entity.p.swimTimer % 60 == 0 && UnderSwimBreathEffect != true) { if (swimming && pd->entity.p.swimTimer % 60 == 0 && UnderSwimBreathEffect != true) {
if (pd->entity.p.stamina > 0) { if (pd->entity.p.stamina > 0) {
if(!shouldRenderDebug) --pd->entity.p.stamina; if(!shouldRenderDebug) --pd->entity.p.stamina;
} else { } else {
hurtEntity(&(pd->entity), 1, -1, 0xFFAF00FF, NULL); hurtEntity(&(pd->entity), 1, -1, 0xFFAF00FF, NULL);
} }
} }
@ -526,12 +526,12 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
playerHeal(pd, 1); playerHeal(pd, 1);
} }
if(isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4)) ++pd->entity.p.swimTimer; if(isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4)) ++pd->entity.p.swimTimer;
if(regening) ++pd->entity.p.regenTimer; if(regening) ++pd->entity.p.regenTimer;
if(UnderSpeedEffect) ++pd->entity.p.speedTimer; if(UnderSpeedEffect) ++pd->entity.p.speedTimer;
if(UnderStrengthEffect) ++pd->entity.p.strengthTimer; if(UnderStrengthEffect) ++pd->entity.p.strengthTimer;
if(UnderSwimBreathEffect) ++pd->entity.p.swimBreathTimer; if(UnderSwimBreathEffect) ++pd->entity.p.swimBreathTimer;
if(pd->entity.p.attackTimer > 0) --pd->entity.p.attackTimer; if(pd->entity.p.attackTimer > 0) --pd->entity.p.attackTimer;
//TODO - maybe move to own function //TODO - maybe move to own function
//Update Minimap //Update Minimap
@ -550,34 +550,34 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
void playerSetActiveItem(PlayerData *pd, Item *item) { void playerSetActiveItem(PlayerData *pd, Item *item) {
pd->activeItem = item; pd->activeItem = item;
if(pd->activeItem->id > 27 && pd->activeItem->id < 51) pd->entity.p.isCarrying = true; if(pd->activeItem->id > 27 && pd->activeItem->id < 51) pd->entity.p.isCarrying = true;
else pd->entity.p.isCarrying = false; else pd->entity.p.isCarrying = false;
} }
bool playerUseEnergy(PlayerData *pd, int amount) { bool playerUseEnergy(PlayerData *pd, int amount) {
if(shouldRenderDebug) return true; if(shouldRenderDebug) return true;
if(amount > pd->entity.p.stamina) return false; if(amount > pd->entity.p.stamina) return false;
pd->entity.p.stamina -= amount; pd->entity.p.stamina -= amount;
return true; return true;
} }
void playerHeal(PlayerData *pd, int amount) { void playerHeal(PlayerData *pd, int amount) {
pd->entity.p.health += amount; pd->entity.p.health += amount;
if(pd->entity.p.health > 10) pd->entity.p.health = 10; if(pd->entity.p.health > 10) pd->entity.p.health = 10;
char healText[11]; char healText[11];
sprintf(healText, "%d", amount); sprintf(healText, "%d", amount);
addEntityToList(newTextParticleEntity(healText,0xFF00FF00, pd->entity.x, pd->entity.y, pd->entity.level), &eManager); addEntityToList(newTextParticleEntity(healText,0xFF00FF00, pd->entity.x, pd->entity.y, pd->entity.level), &eManager);
} }
void playerSpawn(PlayerData *pd) { void playerSpawn(PlayerData *pd) {
while(true){ while(true){
int rx = rand()%128; int rx = rand()%128;
int ry = rand()%128; int ry = rand()%128;
if(getTile(pd->entity.level, rx, ry) == TILE_GRASS){ if(getTile(pd->entity.level, rx, ry) == TILE_GRASS){
pd->entity.x = (rx << 4) + 8; pd->entity.x = (rx << 4) + 8;
pd->entity.y = (ry << 4) + 8; pd->entity.y = (ry << 4) + 8;
pd->isSpawned = true; pd->isSpawned = true;
break; break;
} }
} }
} }

View file

@ -16,64 +16,64 @@
typedef struct _plrsp { typedef struct _plrsp {
bool choosen; bool choosen;
u8 legs; u8 legs;
u8 body; u8 body;
u8 arms; u8 arms;
u8 head; u8 head;
u8 eyes; u8 eyes;
} PlayerSprite; } PlayerSprite;
typedef struct _plrd { typedef struct _plrd {
//for identification in save data and sync game start //for identification in save data and sync game start
u32 id; u32 id;
bool idSet; bool idSet;
bool ready; bool ready;
//input/multiplayer/synchronization //input/multiplayer/synchronization
Inputs inputs; Inputs inputs;
Inputs nextInputs[MAX_INPUT_BUFFER]; Inputs nextInputs[MAX_INPUT_BUFFER];
bool nextTurnReady[MAX_INPUT_BUFFER]; bool nextTurnReady[MAX_INPUT_BUFFER];
// //
bool isSpawned; bool isSpawned;
u8 minimapData[128*128]; u8 minimapData[128*128];
int score; int score;
QuestlineManager questManager; QuestlineManager questManager;
Entity entity; Entity entity;
Inventory inventory; Inventory inventory;
Item *activeItem; Item *activeItem;
PlayerSprite sprite; PlayerSprite sprite;
//menu data //menu data
u8 ingameMenu; u8 ingameMenu;
s8 ingameMenuSelection; s8 ingameMenuSelection;
s16 ingameMenuInvSel; s16 ingameMenuInvSel;
s16 ingameMenuInvSelOther; s16 ingameMenuInvSelOther;
bool ingameMenuAreYouSure; bool ingameMenuAreYouSure;
bool ingameMenuAreYouSureSave; bool ingameMenuAreYouSureSave;
s16 ingameMenuTimer; s16 ingameMenuTimer;
NPC_MenuData npcMenuData; NPC_MenuData npcMenuData;
RecipeManager currentRecipes; RecipeManager currentRecipes;
char *currentCraftTitle; char *currentCraftTitle;
Entity *curChestEntity; Entity *curChestEntity;
s8 curChestEntityR; s8 curChestEntityR;
bool mapShouldRender; bool mapShouldRender;
u8 mapZoomLevel; u8 mapZoomLevel;
s16 mapScrollX; s16 mapScrollX;
s16 mapScrollY; s16 mapScrollY;
char mapText[32]; char mapText[32];
s16 touchLastX; s16 touchLastX;
s16 touchLastY; s16 touchLastY;
bool touchIsDraggingMap; bool touchIsDraggingMap;
bool touchIsChangingSize; bool touchIsChangingSize;
} PlayerData; } PlayerData;
PlayerData players[MAX_PLAYERS]; PlayerData players[MAX_PLAYERS];

View file

@ -4,434 +4,434 @@
#include "Render.h" #include "Render.h"
void initTrades() { void initTrades() {
priestTrades.size = 5; priestTrades.size = 5;
priestTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (priestTrades.size)); priestTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (priestTrades.size));
priestTrades.recipes[0] = defineRecipe(ITEM_DUNGEON_KEY,1,1,ITEM_MAGIC_DUST,2); priestTrades.recipes[0] = defineRecipe(ITEM_DUNGEON_KEY,1,1,ITEM_MAGIC_DUST,2);
priestTrades.recipes[1] = defineRecipe(ITEM_WIZARD_SUMMON,1,4,ITEM_CLOUD,100,ITEM_IRONINGOT,10,ITEM_BONE,10,ITEM_LEATHER,10); priestTrades.recipes[1] = defineRecipe(ITEM_WIZARD_SUMMON,1,4,ITEM_CLOUD,100,ITEM_IRONINGOT,10,ITEM_BONE,10,ITEM_LEATHER,10);
priestTrades.recipes[2] = defineRecipe(TOOL_MAGIC_COMPASS,1,2,ITEM_IRONINGOT,10,ITEM_GLASS,5); priestTrades.recipes[2] = defineRecipe(TOOL_MAGIC_COMPASS,1,2,ITEM_IRONINGOT,10,ITEM_GLASS,5);
priestTrades.recipes[3] = defineRecipe(ITEM_COIN,1,1,ITEM_SLIME,5); priestTrades.recipes[3] = defineRecipe(ITEM_COIN,1,1,ITEM_SLIME,5);
priestTrades.recipes[4] = defineRecipe(ITEM_COIN,1,1,ITEM_FLESH,5); priestTrades.recipes[4] = defineRecipe(ITEM_COIN,1,1,ITEM_FLESH,5);
farmerTrades.size = 7; farmerTrades.size = 7;
farmerTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (farmerTrades.size)); farmerTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (farmerTrades.size));
farmerTrades.recipes[0] = defineRecipe(ITEM_WHEAT,5,1,ITEM_COIN,3); farmerTrades.recipes[0] = defineRecipe(ITEM_WHEAT,5,1,ITEM_COIN,3);
farmerTrades.recipes[1] = defineRecipe(ITEM_BREAD,1,1,ITEM_COIN,3); farmerTrades.recipes[1] = defineRecipe(ITEM_BREAD,1,1,ITEM_COIN,3);
farmerTrades.recipes[2] = defineRecipe(ITEM_APPLE,2,1,ITEM_COIN,4); farmerTrades.recipes[2] = defineRecipe(ITEM_APPLE,2,1,ITEM_COIN,4);
farmerTrades.recipes[3] = defineRecipe(ITEM_ACORN,3,1,ITEM_COIN,1); farmerTrades.recipes[3] = defineRecipe(ITEM_ACORN,3,1,ITEM_COIN,1);
farmerTrades.recipes[4] = defineRecipe(ITEM_SEEDS,4,1,ITEM_COIN,2); farmerTrades.recipes[4] = defineRecipe(ITEM_SEEDS,4,1,ITEM_COIN,2);
farmerTrades.recipes[5] = defineRecipe(ITEM_COIN,2,1,ITEM_SEEDS,5); farmerTrades.recipes[5] = defineRecipe(ITEM_COIN,2,1,ITEM_SEEDS,5);
farmerTrades.recipes[6] = defineRecipe(ITEM_COIN,1,1,ITEM_ACORN,5); farmerTrades.recipes[6] = defineRecipe(ITEM_COIN,1,1,ITEM_ACORN,5);
dwarfTrades.size = 2; dwarfTrades.size = 2;
dwarfTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (dwarfTrades.size)); dwarfTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (dwarfTrades.size));
dwarfTrades.recipes[0] = defineRecipe(ITEM_IRONINGOT,4,1,ITEM_GOLDINGOT,1); dwarfTrades.recipes[0] = defineRecipe(ITEM_IRONINGOT,4,1,ITEM_GOLDINGOT,1);
dwarfTrades.recipes[1] = defineRecipe(ITEM_GOLDINGOT,2,1,ITEM_GEM,1); dwarfTrades.recipes[1] = defineRecipe(ITEM_GOLDINGOT,2,1,ITEM_GEM,1);
//TODO: Trade Dragon Scales for something really nice //TODO: Trade Dragon Scales for something really nice
} }
void freeTrades() { void freeTrades() {
free(priestTrades.recipes); free(priestTrades.recipes);
free(farmerTrades.recipes); free(farmerTrades.recipes);
free(dwarfTrades.recipes); free(dwarfTrades.recipes);
} }
void initQuests(QuestlineManager *questManager) { void initQuests(QuestlineManager *questManager) {
if(questManager->questlines!=NULL) { if(questManager->questlines!=NULL) {
freeQuests(questManager); freeQuests(questManager);
} }
questManager->size = 2; questManager->size = 2;
questManager->questlines = (Questline*)malloc(sizeof(Questline) * (questManager->size)); questManager->questlines = (Questline*)malloc(sizeof(Questline) * (questManager->size));
} }
void resetQuests(QuestlineManager *questManager) { void resetQuests(QuestlineManager *questManager) {
int i; int i;
for(i=0; i<questManager->size; ++i) { for(i=0; i<questManager->size; ++i) {
questManager->questlines[i].currentQuest = 0; questManager->questlines[i].currentQuest = 0;
questManager->questlines[i].currentQuestDone = false; questManager->questlines[i].currentQuestDone = false;
} }
} }
void freeQuests(QuestlineManager *questManager) { void freeQuests(QuestlineManager *questManager) {
free(questManager->questlines); free(questManager->questlines);
questManager->questlines = NULL; questManager->questlines = NULL;
} }
void resetNPCMenuData(NPC_MenuData *data) { void resetNPCMenuData(NPC_MenuData *data) {
data->currentNPC = 0; data->currentNPC = 0;
data->currentNPCMenu = 0; data->currentNPCMenu = 0;
data->currentNPCVal = 0; data->currentNPCVal = 0;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 0; data->currentTalkOptions = 0;
data->currentTalkOption0 = ""; data->currentTalkOption0 = "";
data->currentTalkOption1 = ""; data->currentTalkOption1 = "";
data->currentTalkOption2 = ""; data->currentTalkOption2 = "";
data->currentTalk0 = ""; data->currentTalk0 = "";
data->currentTalk1 = ""; data->currentTalk1 = "";
data->currentTalk2 = ""; data->currentTalk2 = "";
data->currentTalk3 = ""; data->currentTalk3 = "";
data->currentTalk4 = ""; data->currentTalk4 = "";
data->currentTalk5 = ""; data->currentTalk5 = "";
} }
void openNPCMenu(PlayerData *pd, int npc) { void openNPCMenu(PlayerData *pd, int npc) {
pd->ingameMenu = MENU_NPC; pd->ingameMenu = MENU_NPC;
NPC_MenuData *data = &(pd->npcMenuData); NPC_MenuData *data = &(pd->npcMenuData);
QuestlineManager *questManager = &(pd->questManager); QuestlineManager *questManager = &(pd->questManager);
data->currentNPC = npc; data->currentNPC = npc;
data->currentNPCVal = 0; data->currentNPCVal = 0;
data->currentNPCMenu = NPC_MENU_TALK; data->currentNPCMenu = NPC_MENU_TALK;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = "Bye"; data->currentTalkOption0 = "Bye";
data->currentTalkOption1 = ""; data->currentTalkOption1 = "";
data->currentTalkOption2 = ""; data->currentTalkOption2 = "";
data->currentTalk0 = ""; data->currentTalk0 = "";
data->currentTalk1 = ""; data->currentTalk1 = "";
data->currentTalk2 = ""; data->currentTalk2 = "";
data->currentTalk3 = ""; data->currentTalk3 = "";
data->currentTalk4 = ""; data->currentTalk4 = "";
data->currentTalk5 = ""; data->currentTalk5 = "";
//TODO: Handle upon currentNPC as well as the fitting quest progress //TODO: Handle upon currentNPC as well as the fitting quest progress
switch(data->currentNPC) { switch(data->currentNPC) {
case NPC_GIRL: case NPC_GIRL:
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = "..."; data->currentTalkOption0 = "...";
data->currentTalk0 = "Hello?"; data->currentTalk0 = "Hello?";
data->currentTalk1 = "I have a feeling of having"; data->currentTalk1 = "I have a feeling of having";
data->currentTalk2 = "forgotten something very"; data->currentTalk2 = "forgotten something very";
data->currentTalk3 = "important."; data->currentTalk3 = "important.";
data->currentTalk4 = "Hopefully I will remember"; data->currentTalk4 = "Hopefully I will remember";
data->currentTalk5 = "it soon..."; data->currentTalk5 = "it soon...";
break; break;
case NPC_PRIEST: case NPC_PRIEST:
data->currentTalkOptions = 3; data->currentTalkOptions = 3;
data->currentTalkOption1 = "Trade"; data->currentTalkOption1 = "Trade";
data->currentTalkOption2 = "Why are you so few?"; data->currentTalkOption2 = "Why are you so few?";
data->currentTalk0 = "Welcome to our small village"; data->currentTalk0 = "Welcome to our small village";
data->currentTalk1 = "I am the leader of our group."; data->currentTalk1 = "I am the leader of our group.";
data->currentTalk2 = "If you have anything usefull"; data->currentTalk2 = "If you have anything usefull";
data->currentTalk3 = "for us I might be able to"; data->currentTalk3 = "for us I might be able to";
data->currentTalk4 = "provide something nice in"; data->currentTalk4 = "provide something nice in";
data->currentTalk5 = "exchange."; data->currentTalk5 = "exchange.";
break; break;
case NPC_FARMER: case NPC_FARMER:
data->currentTalkOptions = 2; data->currentTalkOptions = 2;
data->currentTalkOption0 = "Maybe some other time"; data->currentTalkOption0 = "Maybe some other time";
data->currentTalkOption1 = "Trade"; data->currentTalkOption1 = "Trade";
data->currentTalk0 = "Hello friend!"; data->currentTalk0 = "Hello friend!";
data->currentTalk1 = "Nice seeing somebody else"; data->currentTalk1 = "Nice seeing somebody else";
data->currentTalk2 = "visit my little farm."; data->currentTalk2 = "visit my little farm.";
data->currentTalk3 = "Interested in buying some"; data->currentTalk3 = "Interested in buying some";
data->currentTalk4 = "fresh farm goods?"; data->currentTalk4 = "fresh farm goods?";
data->currentTalk5 = ""; data->currentTalk5 = "";
break; break;
case NPC_LIBRARIAN: case NPC_LIBRARIAN:
data->currentTalkOptions = 2; data->currentTalkOptions = 2;
data->currentTalkOption0 = "Nothing"; data->currentTalkOption0 = "Nothing";
data->currentTalkOption1 = "What are you doing here?"; data->currentTalkOption1 = "What are you doing here?";
if(questManager->questlines[1].currentQuest==1) { if(questManager->questlines[1].currentQuest==1) {
data->currentTalkOptions = 3; data->currentTalkOptions = 3;
data->currentTalkOption2 = "Dwarvish language"; data->currentTalkOption2 = "Dwarvish language";
} }
data->currentTalk0 = "Oh hello?"; data->currentTalk0 = "Oh hello?";
data->currentTalk1 = "You must be quite brave"; data->currentTalk1 = "You must be quite brave";
data->currentTalk2 = "or stupid to be walking"; data->currentTalk2 = "or stupid to be walking";
data->currentTalk3 = "around in this dungeon."; data->currentTalk3 = "around in this dungeon.";
data->currentTalk4 = ""; data->currentTalk4 = "";
data->currentTalk5 = "How can I help you?"; data->currentTalk5 = "How can I help you?";
break; break;
case NPC_DWARF: case NPC_DWARF:
if(questManager->questlines[1].currentQuest<=1) { if(questManager->questlines[1].currentQuest<=1) {
questManager->questlines[1].currentQuest = 1; questManager->questlines[1].currentQuest = 1;
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = "?"; data->currentTalkOption0 = "?";
data->currentTalk0 = "Dwo neal bet reck da lo"; data->currentTalk0 = "Dwo neal bet reck da lo";
data->currentTalk1 = "dhum don lir lugn at el"; data->currentTalk1 = "dhum don lir lugn at el";
data->currentTalk2 = "nur tor erno ur yo trad"; data->currentTalk2 = "nur tor erno ur yo trad";
data->currentTalk3 = "thra so tir kho ukk tin"; data->currentTalk3 = "thra so tir kho ukk tin";
data->currentTalk4 = "hel dro ic"; data->currentTalk4 = "hel dro ic";
data->currentTalk5 = ""; data->currentTalk5 = "";
//TODO: set to 2 once translation book has been bought from librarian(can only be done once it is 1, so the dwarf has been found once) //TODO: set to 2 once translation book has been bought from librarian(can only be done once it is 1, so the dwarf has been found once)
} else if(questManager->questlines[1].currentQuest==2) { } else if(questManager->questlines[1].currentQuest==2) {
data->currentTalkOptions = 2; data->currentTalkOptions = 2;
data->currentTalkOption0 = "Not really"; data->currentTalkOption0 = "Not really";
data->currentTalkOption1 = "Trade"; data->currentTalkOption1 = "Trade";
data->currentTalk0 = "How are ya?"; data->currentTalk0 = "How are ya?";
data->currentTalk1 = "Pretty unusal meeting a"; data->currentTalk1 = "Pretty unusal meeting a";
data->currentTalk2 = "human down here."; data->currentTalk2 = "human down here.";
data->currentTalk3 = ""; data->currentTalk3 = "";
data->currentTalk4 = "have something valuable"; data->currentTalk4 = "have something valuable";
data->currentTalk5 = "to trade?"; data->currentTalk5 = "to trade?";
} }
break; break;
} }
} }
void tickTalkMenu(PlayerData *pd, NPC_MenuData *data) { void tickTalkMenu(PlayerData *pd, NPC_MenuData *data) {
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE; if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
if (pd->inputs.k_up.clicked){ ++data->currentTalkSel; if(data->currentTalkSel >= data->currentTalkOptions) data->currentTalkSel=0;} if (pd->inputs.k_up.clicked){ ++data->currentTalkSel; if(data->currentTalkSel >= data->currentTalkOptions) data->currentTalkSel=0;}
if (pd->inputs.k_down.clicked){ --data->currentTalkSel; if(data->currentTalkSel < 0) data->currentTalkSel=data->currentTalkOptions-1;} if (pd->inputs.k_down.clicked){ --data->currentTalkSel; if(data->currentTalkSel < 0) data->currentTalkSel=data->currentTalkOptions-1;}
if(pd->inputs.k_accept.clicked){ if(pd->inputs.k_accept.clicked){
data->currentTalkDone = true; data->currentTalkDone = true;
} }
} }
void tickNPCMenu(PlayerData *pd) { void tickNPCMenu(PlayerData *pd) {
NPC_MenuData *data = &(pd->npcMenuData); NPC_MenuData *data = &(pd->npcMenuData);
QuestlineManager *questManager = &(pd->questManager); QuestlineManager *questManager = &(pd->questManager);
//TODO: Handle upon currentNPC as well as the fitting quest progress //TODO: Handle upon currentNPC as well as the fitting quest progress
if(data->currentNPCMenu==NPC_MENU_TALK) tickTalkMenu(pd, data); if(data->currentNPCMenu==NPC_MENU_TALK) tickTalkMenu(pd, data);
switch(data->currentNPC) { switch(data->currentNPC) {
case NPC_GIRL: case NPC_GIRL:
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) { if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE; if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE;
} }
break; break;
case NPC_PRIEST: case NPC_PRIEST:
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) { if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
if(data->currentNPCVal==0) { if(data->currentNPCVal==0) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} else if(data->currentTalkSel==1) { } else if(data->currentTalkSel==1) {
openCraftingMenu(pd, &priestTrades, "Trading"); openCraftingMenu(pd, &priestTrades, "Trading");
} else if(data->currentTalkSel==2) { } else if(data->currentTalkSel==2) {
data->currentNPCVal = 1; data->currentNPCVal = 1;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = "..."; data->currentTalkOption0 = "...";
data->currentTalk0 = "For quite some time now this"; data->currentTalk0 = "For quite some time now this";
data->currentTalk1 = "village has been tyrannized"; data->currentTalk1 = "village has been tyrannized";
data->currentTalk2 = "by a powerfull Air Wizard."; data->currentTalk2 = "by a powerfull Air Wizard.";
data->currentTalk3 = "We are the only ones who"; data->currentTalk3 = "We are the only ones who";
data->currentTalk4 = "still have not given up"; data->currentTalk4 = "still have not given up";
data->currentTalk5 = "our old homes."; data->currentTalk5 = "our old homes.";
} }
} else if(data->currentNPCVal==1) { } else if(data->currentNPCVal==1) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
data->currentNPCVal = 2; data->currentNPCVal = 2;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = "..."; data->currentTalkOption0 = "...";
data->currentTalk0 = "Most of the time the wizard"; data->currentTalk0 = "Most of the time the wizard";
data->currentTalk1 = "hides somewhere in the"; data->currentTalk1 = "hides somewhere in the";
data->currentTalk2 = "cloudes. They can only be"; data->currentTalk2 = "cloudes. They can only be";
data->currentTalk3 = "reached by a stairwell"; data->currentTalk3 = "reached by a stairwell";
data->currentTalk4 = "protected by an almost"; data->currentTalk4 = "protected by an almost";
data->currentTalk5 = "undestroyable stone barrier."; data->currentTalk5 = "undestroyable stone barrier.";
} }
} else if(data->currentNPCVal==2) { } else if(data->currentNPCVal==2) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
data->currentNPCVal = 3; data->currentNPCVal = 3;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = "..."; data->currentTalkOption0 = "...";
data->currentTalk0 = "I am guessing you would "; data->currentTalk0 = "I am guessing you would ";
data->currentTalk1 = "need tools atleast as"; data->currentTalk1 = "need tools atleast as";
data->currentTalk2 = "strong as diamonds to be"; data->currentTalk2 = "strong as diamonds to be";
data->currentTalk3 = "able to destroy it."; data->currentTalk3 = "able to destroy it.";
data->currentTalk4 = ""; data->currentTalk4 = "";
data->currentTalk5 = ""; data->currentTalk5 = "";
} }
} else if(data->currentNPCVal==3) { } else if(data->currentNPCVal==3) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
data->currentNPCVal = 4; data->currentNPCVal = 4;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 2; data->currentTalkOptions = 2;
data->currentTalkOption0 = "Let me do it!"; data->currentTalkOption0 = "Let me do it!";
data->currentTalkOption1 = "I am not sure"; data->currentTalkOption1 = "I am not sure";
data->currentTalk0 = "I am willing to give an"; data->currentTalk0 = "I am willing to give an";
data->currentTalk1 = "ancient artifact passed"; data->currentTalk1 = "ancient artifact passed";
data->currentTalk2 = "down over generations to"; data->currentTalk2 = "down over generations to";
data->currentTalk3 = "anybody who manages to"; data->currentTalk3 = "anybody who manages to";
data->currentTalk4 = "chase the wizard away and"; data->currentTalk4 = "chase the wizard away and";
data->currentTalk5 = "come back with proof."; data->currentTalk5 = "come back with proof.";
} }
} else if(data->currentNPCVal==4) { } else if(data->currentNPCVal==4) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} }
} }
break; break;
case NPC_FARMER: case NPC_FARMER:
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) { if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
if(data->currentNPCVal==0) { if(data->currentNPCVal==0) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} else if(data->currentTalkSel==1) { } else if(data->currentTalkSel==1) {
openCraftingMenu(pd, &farmerTrades, "Trading"); openCraftingMenu(pd, &farmerTrades, "Trading");
} }
} }
} }
break; break;
case NPC_LIBRARIAN: case NPC_LIBRARIAN:
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) { if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
if(data->currentNPCVal==0) { if(data->currentNPCVal==0) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} else if(data->currentTalkSel==1) { } else if(data->currentTalkSel==1) {
data->currentNPCVal = 2; data->currentNPCVal = 2;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = "Ok"; data->currentTalkOption0 = "Ok";
data->currentTalk0 = "The books in this dungeon"; data->currentTalk0 = "The books in this dungeon";
data->currentTalk1 = "house secrets that cannot be"; data->currentTalk1 = "house secrets that cannot be";
data->currentTalk2 = "found anywhere else in the"; data->currentTalk2 = "found anywhere else in the";
data->currentTalk3 = "world. So I came to study"; data->currentTalk3 = "world. So I came to study";
data->currentTalk4 = "them. Most are written in"; data->currentTalk4 = "them. Most are written in";
data->currentTalk5 = "an ancient language."; data->currentTalk5 = "an ancient language.";
} else if(data->currentTalkSel==2) { } else if(data->currentTalkSel==2) {
data->currentNPCVal = 1; data->currentNPCVal = 1;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 2; data->currentTalkOptions = 2;
data->currentTalkOption0 = "I need to think about it"; data->currentTalkOption0 = "I need to think about it";
data->currentTalkOption1 = "Here they are"; data->currentTalkOption1 = "Here they are";
data->currentTalk0 = "So you have met a dwarf but"; data->currentTalk0 = "So you have met a dwarf but";
data->currentTalk1 = "had a little communication"; data->currentTalk1 = "had a little communication";
data->currentTalk2 = "problem? I do have a dwarvish"; data->currentTalk2 = "problem? I do have a dwarvish";
data->currentTalk3 = "translation book but I havent"; data->currentTalk3 = "translation book but I havent";
data->currentTalk4 = "read it yet. For 10 Gold bars"; data->currentTalk4 = "read it yet. For 10 Gold bars";
data->currentTalk5 = "I will give it to you anyway."; data->currentTalk5 = "I will give it to you anyway.";
} }
} else if(data->currentNPCVal==1) { } else if(data->currentNPCVal==1) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} else if(data->currentTalkSel==1) { } else if(data->currentTalkSel==1) {
data->currentNPCVal = 2; data->currentNPCVal = 2;
data->currentTalkSel = 0; data->currentTalkSel = 0;
data->currentTalkDone = false; data->currentTalkDone = false;
data->currentTalkOptions = 1; data->currentTalkOptions = 1;
data->currentTalkOption0 = ""; data->currentTalkOption0 = "";
if(countItemInv(ITEM_GOLDINGOT, 0, &(pd->inventory))>=10) { if(countItemInv(ITEM_GOLDINGOT, 0, &(pd->inventory))>=10) {
//remove gold from player inventory //remove gold from player inventory
//TODO: Maybe I should make a generic substract items method sometime //TODO: Maybe I should make a generic substract items method sometime
Item* item = getItemFromInventory(ITEM_GOLDINGOT, &(pd->inventory)); Item* item = getItemFromInventory(ITEM_GOLDINGOT, &(pd->inventory));
item->countLevel -= 10; item->countLevel -= 10;
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, &(pd->inventory)); if(item->countLevel < 1) removeItemFromInventory(item->slotNum, &(pd->inventory));
questManager->questlines[1].currentQuest = 2; questManager->questlines[1].currentQuest = 2;
data->currentTalk0 = "Thank you these will be"; data->currentTalk0 = "Thank you these will be";
data->currentTalk1 = "really helpfull."; data->currentTalk1 = "really helpfull.";
data->currentTalk2 = "Here take this book with"; data->currentTalk2 = "Here take this book with";
data->currentTalk3 = "it you should be able to"; data->currentTalk3 = "it you should be able to";
data->currentTalk4 = "easily understand anything"; data->currentTalk4 = "easily understand anything";
data->currentTalk5 = "a dwarf can say."; data->currentTalk5 = "a dwarf can say.";
data->currentTalkOption0 = "Thanks"; data->currentTalkOption0 = "Thanks";
} else { } else {
data->currentTalk0 = "You do not seem to have"; data->currentTalk0 = "You do not seem to have";
data->currentTalk1 = "enough Gold Bars with you."; data->currentTalk1 = "enough Gold Bars with you.";
data->currentTalk2 = ""; data->currentTalk2 = "";
data->currentTalk3 = "Ask again when you have"; data->currentTalk3 = "Ask again when you have";
data->currentTalk4 = "collected the 10 Bars."; data->currentTalk4 = "collected the 10 Bars.";
data->currentTalk5 = ""; data->currentTalk5 = "";
data->currentTalkOption0 = "Ok"; data->currentTalkOption0 = "Ok";
} }
} }
} else if(data->currentNPCVal==2) { } else if(data->currentNPCVal==2) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} }
} }
} }
break; break;
case NPC_DWARF: case NPC_DWARF:
if(questManager->questlines[1].currentQuest<=1) { if(questManager->questlines[1].currentQuest<=1) {
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) { if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE; if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE;
} }
} else if(questManager->questlines[1].currentQuest==2) { } else if(questManager->questlines[1].currentQuest==2) {
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) { if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
if(data->currentTalkSel==0) { if(data->currentTalkSel==0) {
pd->ingameMenu = MENU_NONE; pd->ingameMenu = MENU_NONE;
} else if(data->currentTalkSel==1) { } else if(data->currentTalkSel==1) {
openCraftingMenu(pd, &dwarfTrades, "Trading"); openCraftingMenu(pd, &dwarfTrades, "Trading");
} }
} }
} }
break; break;
} }
} }
void renderTalkMenu(NPC_MenuData *data, char * name) { void renderTalkMenu(NPC_MenuData *data, char * name) {
renderFrame(1,1,24,14,0xFFFF1010); renderFrame(1,1,24,14,0xFFFF1010);
drawTextColor(name,24+1,14+1,0xFF000000); drawTextColor(name,24+1,14+1,0xFF000000);
drawTextColor(name,24,14,0xFF6FE2E2); drawTextColor(name,24,14,0xFF6FE2E2);
drawText(data->currentTalk0, 32, 32); drawText(data->currentTalk0, 32, 32);
drawText(data->currentTalk1, 32, 48); drawText(data->currentTalk1, 32, 48);
drawText(data->currentTalk2, 32, 64); drawText(data->currentTalk2, 32, 64);
drawText(data->currentTalk3, 32, 80); drawText(data->currentTalk3, 32, 80);
drawText(data->currentTalk4, 32, 96); drawText(data->currentTalk4, 32, 96);
drawText(data->currentTalk5, 32, 112); drawText(data->currentTalk5, 32, 112);
if(data->currentTalkOptions>=3) drawText(data->currentTalkOption2, 64, 147); if(data->currentTalkOptions>=3) drawText(data->currentTalkOption2, 64, 147);
if(data->currentTalkOptions>=2) drawText(data->currentTalkOption1, 64, 171); if(data->currentTalkOptions>=2) drawText(data->currentTalkOption1, 64, 171);
if(data->currentTalkOptions>=1) drawText(data->currentTalkOption0, 64, 195); if(data->currentTalkOptions>=1) drawText(data->currentTalkOption0, 64, 195);
if(data->currentTalkOptions>=3 && data->currentTalkSel==2) drawText(">", 48, 147); if(data->currentTalkOptions>=3 && data->currentTalkSel==2) drawText(">", 48, 147);
if(data->currentTalkOptions>=2 && data->currentTalkSel==1) drawText(">", 48, 171); if(data->currentTalkOptions>=2 && data->currentTalkSel==1) drawText(">", 48, 171);
if(data->currentTalkOptions>=1 && data->currentTalkSel==0) drawText(">", 48, 195); if(data->currentTalkOptions>=1 && data->currentTalkSel==0) drawText(">", 48, 195);
} }
void renderNPCMenu(NPC_MenuData *data) { void renderNPCMenu(NPC_MenuData *data) {
//TODO: Handle upon currentNPC as well as the fitting quest progress //TODO: Handle upon currentNPC as well as the fitting quest progress
switch(data->currentNPC) { switch(data->currentNPC) {
case NPC_GIRL: case NPC_GIRL:
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Maria"); if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Maria");
break; break;
case NPC_PRIEST: case NPC_PRIEST:
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Priest Brom"); if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Priest Brom");
break; break;
case NPC_FARMER: case NPC_FARMER:
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Farmer Garrow"); if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Farmer Garrow");
break; break;
case NPC_LIBRARIAN: case NPC_LIBRARIAN:
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Librarian Ajihad"); if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Librarian Ajihad");
break; break;
case NPC_DWARF: case NPC_DWARF:
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Dwarf Orik"); if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Dwarf Orik");
break; break;
} }
} }

View file

@ -3,33 +3,33 @@
#include <3ds.h> #include <3ds.h>
typedef struct _questline { typedef struct _questline {
int currentQuest; int currentQuest;
bool currentQuestDone; bool currentQuestDone;
} Questline; } Questline;
typedef struct _questlineManager { typedef struct _questlineManager {
int size; int size;
Questline * questlines; Questline * questlines;
} QuestlineManager; } QuestlineManager;
typedef struct _npcMenuData { typedef struct _npcMenuData {
u8 currentNPC; u8 currentNPC;
int currentNPCMenu; int currentNPCMenu;
int currentNPCVal; int currentNPCVal;
int currentTalkSel; int currentTalkSel;
bool currentTalkDone; bool currentTalkDone;
int currentTalkOptions; int currentTalkOptions;
char * currentTalkOption0; char * currentTalkOption0;
char * currentTalkOption1; char * currentTalkOption1;
char * currentTalkOption2; char * currentTalkOption2;
char * currentTalk0; char * currentTalk0;
char * currentTalk1; char * currentTalk1;
char * currentTalk2; char * currentTalk2;
char * currentTalk3; char * currentTalk3;
char * currentTalk4; char * currentTalk4;
char * currentTalk5; char * currentTalk5;
} NPC_MenuData; } NPC_MenuData;
//TODO: Actually move the data here //TODO: Actually move the data here

View file

@ -166,7 +166,7 @@ void renderp(s32 xp, s32 yp, u32 xTile, u32 yTile) {
yp -= offsetY; yp -= offsetY;
int scaleX = playerScale, scaleY = playerScale; int scaleX = playerScale, scaleY = playerScale;
sf2d_draw_texture_part_scale(playerSprites, xp << 1, yp << 1, xTile, yTile, 16, 16, sf2d_draw_texture_part_scale(playerSprites, xp << 1, yp << 1, xTile, yTile, 16, 16,
scaleX, scaleY); scaleX, scaleY);
} }
void renderTitle(int x, int y) { void renderTitle(int x, int y) {
@ -311,8 +311,8 @@ void renderLightsToStencil(PlayerData *pd, bool force, bool invert, bool rplayer
C3D_StencilOp(GPU_STENCIL_REPLACE, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP); C3D_StencilOp(GPU_STENCIL_REPLACE, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP);
C3D_AlphaTest(true, GPU_GREATER, 0); C3D_AlphaTest(true, GPU_GREATER, 0);
if(pd->activeItem->id == ITEM_LANTERN) renderLight(pd->entity.x, pd->entity.y, lanternLightBake); if(pd->activeItem->id == ITEM_LANTERN) renderLight(pd->entity.x, pd->entity.y, lanternLightBake);
else if(rplayer) renderLight(pd->entity.x, pd->entity.y, playerLightBake); else if(rplayer) renderLight(pd->entity.x, pd->entity.y, playerLightBake);
int i; int i;
for (i = 0; i < eManager.lastSlot[pd->entity.level]; ++i) { for (i = 0; i < eManager.lastSlot[pd->entity.level]; ++i) {
@ -334,7 +334,7 @@ void renderLightsToStencil(PlayerData *pd, bool force, bool invert, bool rplayer
//TODO: Even this is not performant enough for old 3DS, when there is a lot of lava on screen //TODO: Even this is not performant enough for old 3DS, when there is a lot of lava on screen
for (x = xo-2; x <= 13 + xo+2; ++x) { for (x = xo-2; x <= 13 + xo+2; ++x) {
for (y = yo-2; y <= 8 + yo+2; ++y) { for (y = yo-2; y <= 8 + yo+2; ++y) {
if(getTile(pd->entity.level, x, y) == TILE_LAVA) { if(getTile(pd->entity.level, x, y) == TILE_LAVA) {
//experimental "speedhack" //experimental "speedhack"
if(getTile(pd->entity.level, x+1,y)==TILE_LAVA && getTile(pd->entity.level, x-1,y)==TILE_LAVA && getTile(pd->entity.level, x,y+1)==TILE_LAVA && getTile(pd->entity.level, x,y-1)==TILE_LAVA) { if(getTile(pd->entity.level, x+1,y)==TILE_LAVA && getTile(pd->entity.level, x-1,y)==TILE_LAVA && getTile(pd->entity.level, x,y+1)==TILE_LAVA && getTile(pd->entity.level, x,y-1)==TILE_LAVA) {
if((x+y)%2 == 0) continue; if((x+y)%2 == 0) continue;
@ -479,8 +479,8 @@ void renderTile(int i, int d, u8 level, int x, int y) {
checkSurrTiles4(level, x >> 4, y >> 4, TILE_FLOWER); checkSurrTiles4(level, x >> 4, y >> 4, TILE_FLOWER);
checkSurrTiles4(level, x >> 4, y >> 4, TILE_SAPLING_TREE); checkSurrTiles4(level, x >> 4, y >> 4, TILE_SAPLING_TREE);
if(level==1 && worldData.season==3) renderConnectedTile4(x, y, 256, 112); if(level==1 && worldData.season==3) renderConnectedTile4(x, y, 256, 112);
else if(level==1 && worldData.season==2) renderConnectedTile4(x, y, 256, 128); else if(level==1 && worldData.season==2) renderConnectedTile4(x, y, 256, 128);
else renderConnectedTile4(x, y, 256, 0); else renderConnectedTile4(x, y, 256, 0);
break; break;
case TILE_TREE: case TILE_TREE:
@ -488,30 +488,30 @@ void renderTile(int i, int d, u8 level, int x, int y) {
checkSurrTiles8(level, x >> 4, y >> 4, TILE_TREE); checkSurrTiles8(level, x >> 4, y >> 4, TILE_TREE);
if(worldData.season==2) { if(worldData.season==2) {
render(x, y, 352+((tu && tl && tul) ? 16 : 0), 96, 0); render(x, y, 352+((tu && tl && tul) ? 16 : 0), 96, 0);
render(x+8, y, 360+((tu && tr && tur) ? 16 : 0), 96, 0); render(x+8, y, 360+((tu && tr && tur) ? 16 : 0), 96, 0);
render(x, y+8, 352+((td && tl && tdl) ? 16 : 0), 104, 0); render(x, y+8, 352+((td && tl && tdl) ? 16 : 0), 104, 0);
render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 104, 0); render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 104, 0);
} else if(worldData.season==3) { } else if(worldData.season==3) {
render(x, y, 352+((tu && tl && tul) ? 16 : 0), 112, 0); render(x, y, 352+((tu && tl && tul) ? 16 : 0), 112, 0);
render(x+8, y, 360+((tu && tr && tur) ? 16 : 0), 112, 0); render(x+8, y, 360+((tu && tr && tur) ? 16 : 0), 112, 0);
render(x, y+8, 352+((td && tl && tdl) ? 16 : 0), 120, 0); render(x, y+8, 352+((td && tl && tdl) ? 16 : 0), 120, 0);
render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 120, 0); render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 120, 0);
} else { } else {
render(x, y, 256+((tu && tl && tul) ? 16 : 0), 48, 0); render(x, y, 256+((tu && tl && tul) ? 16 : 0), 48, 0);
render(x+8, y, 264+((tu && tr && tur) ? 16 : 0), 48, 0); render(x+8, y, 264+((tu && tr && tur) ? 16 : 0), 48, 0);
render(x, y+8, 256+((td && tl && tdl) ? 16 : 0), 56, 0); render(x, y+8, 256+((td && tl && tdl) ? 16 : 0), 56, 0);
render(x+8, y+8, 264+((td && tr && tdr) ? 16 : 0), 56, 0); render(x+8, y+8, 264+((td && tr && tdr) ? 16 : 0), 56, 0);
} }
break; break;
case TILE_ROCK: case TILE_ROCK:
checkSurrTiles8(level, x >> 4, y >> 4, TILE_ROCK); checkSurrTiles8(level, x >> 4, y >> 4, TILE_ROCK);
if(level>1) if(level>1)
renderConnectedTile8(x, y, 256, 96); renderConnectedTile8(x, y, 256, 96);
else else
renderConnectedTile8(x, y, 336, 64); renderConnectedTile8(x, y, 336, 64);
break; break;
case TILE_HARDROCK: case TILE_HARDROCK:
checkSurrTiles8(level, x >> 4, y >> 4, TILE_HARDROCK); checkSurrTiles8(level, x >> 4, y >> 4, TILE_HARDROCK);
@ -529,14 +529,14 @@ void renderTile(int i, int d, u8 level, int x, int y) {
checkSurrTiles4(level, x >> 4, y >> 4, TILE_SAPLING_CACTUS); checkSurrTiles4(level, x >> 4, y >> 4, TILE_SAPLING_CACTUS);
if(level==1 && worldData.season==3) { if(level==1 && worldData.season==3) {
renderConnectedTile4(x, y, 256, 112); renderConnectedTile4(x, y, 256, 112);
} else { } else {
renderConnectedTile4(x, y, 320, 0); renderConnectedTile4(x, y, 320, 0);
if (d > 0) { if (d > 0) {
render16(x, y, 336, 48, 0); render16(x, y, 336, 48, 0);
} }
} }
break; break;
case TILE_WATER: case TILE_WATER:
checkSurrTiles4(level, x >> 4, y >> 4, TILE_WATER); checkSurrTiles4(level, x >> 4, y >> 4, TILE_WATER);
@ -571,7 +571,7 @@ void renderTile(int i, int d, u8 level, int x, int y) {
case TILE_FLOWER: case TILE_FLOWER:
renderTile(TILE_GRASS, 0, level, x, y); renderTile(TILE_GRASS, 0, level, x, y);
if(level==1 && worldData.season==3) render16(x, y, 320, 112, d); if(level==1 && worldData.season==3) render16(x, y, 320, 112, d);
else render16(x, y, 320, 48, d); else render16(x, y, 320, 48, d);
break; break;
case TILE_STAIRS_DOWN: case TILE_STAIRS_DOWN:
if (level == 0) if (level == 0)
@ -659,7 +659,7 @@ void renderTile(int i, int d, u8 level, int x, int y) {
render16(x, y, 320, 64, d); render16(x, y, 320, 64, d);
//draw remaining pillar count //draw remaining pillar count
PlayerData *lp = getLocalPlayer(); PlayerData *lp = getLocalPlayer();
if((lp->entity.x - (x+8))*(lp->entity.x - (x+8)) + (lp->entity.y - (y+8))*(lp->entity.y - (y+8)) <= 24*24) { if((lp->entity.x - (x+8))*(lp->entity.x - (x+8)) + (lp->entity.y - (y+8))*(lp->entity.y - (y+8)) <= 24*24) {
x -= offsetX; x -= offsetX;
y -= offsetY; y -= offsetY;
@ -682,15 +682,15 @@ void renderTile(int i, int d, u8 level, int x, int y) {
} }
break; break;
case TILE_BOOKSHELVES: case TILE_BOOKSHELVES:
checkSurrTiles4(level, x >> 4, y >> 4, TILE_BOOKSHELVES); checkSurrTiles4(level, x >> 4, y >> 4, TILE_BOOKSHELVES);
renderConnectedTile4(x, y, 384, 80 + d*16); renderConnectedTile4(x, y, 384, 80 + d*16);
break; break;
case TILE_WOOD_FLOOR: case TILE_WOOD_FLOOR:
render16(x, y, 336, 96, 0); render16(x, y, 336, 96, 0);
break; break;
case TILE_MYCELIUM: case TILE_MYCELIUM:
checkSurrTiles4(level, x >> 4, y >> 4, TILE_MYCELIUM); checkSurrTiles4(level, x >> 4, y >> 4, TILE_MYCELIUM);
checkSurrTiles4(level, x >> 4, y >> 4, TILE_MUSHROOM_BROWN); checkSurrTiles4(level, x >> 4, y >> 4, TILE_MUSHROOM_BROWN);
checkSurrTiles4(level, x >> 4, y >> 4, TILE_MUSHROOM_RED); checkSurrTiles4(level, x >> 4, y >> 4, TILE_MUSHROOM_RED);
@ -698,15 +698,15 @@ void renderTile(int i, int d, u8 level, int x, int y) {
if(level==1 && worldData.season==3) renderConnectedTile4(x, y, 256, 112); if(level==1 && worldData.season==3) renderConnectedTile4(x, y, 256, 112);
else renderConnectedTile4(x, y, 448, 80); else renderConnectedTile4(x, y, 448, 80);
break; break;
case TILE_MUSHROOM_BROWN: case TILE_MUSHROOM_BROWN:
renderTile(TILE_MYCELIUM, 0, level, x, y); renderTile(TILE_MYCELIUM, 0, level, x, y);
render16(x, y, 448 + (d&0x1)*16, 96, 0); render16(x, y, 448 + (d&0x1)*16, 96, 0);
break; break;
case TILE_MUSHROOM_RED: case TILE_MUSHROOM_RED:
renderTile(TILE_MYCELIUM, 0, level, x, y); renderTile(TILE_MYCELIUM, 0, level, x, y);
render16(x, y, 480 + (d&0x1)*16, 96, 0); render16(x, y, 480 + (d&0x1)*16, 96, 0);
break; break;
case TILE_ICE: case TILE_ICE:
renderTile(TILE_WATER, 0, level, x, y); renderTile(TILE_WATER, 0, level, x, y);
//checkSurrTiles4(x >> 4, y >> 4, TILE_WATER); //checkSurrTiles4(x >> 4, y >> 4, TILE_WATER);
//checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE); //checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE);
@ -758,9 +758,9 @@ void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile) {
void renderZoomedMap(PlayerData *pd) { void renderZoomedMap(PlayerData *pd) {
sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way
int mx = pd->mapScrollX; int mx = pd->mapScrollX;
int my = pd->mapScrollY; int my = pd->mapScrollY;
if(pd->mapZoomLevel == 2) mx = 32; if(pd->mapZoomLevel == 2) mx = 32;
sf2d_draw_texture_scale(minimap[pd->entity.level], mx, my, pd->mapZoomLevel, pd->mapZoomLevel); // zoomed map sf2d_draw_texture_scale(minimap[pd->entity.level], mx, my, pd->mapZoomLevel, pd->mapZoomLevel); // zoomed map
// Airwizard on zoomed map // Airwizard on zoomed map
@ -774,28 +774,28 @@ void renderZoomedMap(PlayerData *pd) {
2, 2 2, 2
); );
} }
} }
// Player on zoomed map // Player on zoomed map
//TODO: Maybe also render other players? //TODO: Maybe also render other players?
render16c( render16c(
(mx+((pd->entity.x/16)*pd->mapZoomLevel)-16)/2, (mx+((pd->entity.x/16)*pd->mapZoomLevel)-16)/2,
(my+((pd->entity.y/16)*pd->mapZoomLevel)-16)/2, (my+((pd->entity.y/16)*pd->mapZoomLevel)-16)/2,
0, 112, 0, 112,
((pd->entity.p.walkDist >> 6) & 1) == 0 ? 0 : 1, ((pd->entity.p.walkDist >> 6) & 1) == 0 ? 0 : 1,
2, 2 2, 2
); );
drawText(pd->mapText,224, 214); // "x2"/"x4"/"x6" drawText(pd->mapText,224, 214); // "x2"/"x4"/"x6"
render16(142, 2, 72, 208, 0); // Exit button render16(142, 2, 72, 208, 0); // Exit button
renderc(126, 102, 40, 208, 32, 16, 0); // Plus/Minus zoom buttons renderc(126, 102, 40, 208, 32, 16, 0); // Plus/Minus zoom buttons
if(pd->mapZoomLevel < 3) sf2d_draw_rectangle(258, 210, 26, 20, 0x7F4F4F4F); // gray out minus button if(pd->mapZoomLevel < 3) sf2d_draw_rectangle(258, 210, 26, 20, 0x7F4F4F4F); // gray out minus button
else if(pd->mapZoomLevel > 5) sf2d_draw_rectangle(284, 210, 26, 20, 0x7F4F4F4F); // gray out minus button else if(pd->mapZoomLevel > 5) sf2d_draw_rectangle(284, 210, 26, 20, 0x7F4F4F4F); // gray out minus button
} }
char scoreT[32]; char scoreT[32];
void renderGui(PlayerData *pd) { void renderGui(PlayerData *pd) {
int i; int i;
//health and stamina //health and stamina
for (i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i) {
if (i < pd->entity.p.health) if (i < pd->entity.p.health)
render(i * 8 + 6, 5, 168, 152, 0); render(i * 8 + 6, 5, 168, 152, 0);
@ -807,10 +807,10 @@ void renderGui(PlayerData *pd) {
render(i * 8 + 6, 14, 191, 152, 0); render(i * 8 + 6, 14, 191, 152, 0);
} }
//minimap //minimap
sf2d_draw_texture(minimap[pd->entity.level], 10, 102); sf2d_draw_texture(minimap[pd->entity.level], 10, 102);
//active item //active item
renderItemWithTextCentered(pd->activeItem, 320, 66); renderItemWithTextCentered(pd->activeItem, 320, 66);
itoa(pd->score, scoreT, 10); // integer to base10 string itoa(pd->score, scoreT, 10); // integer to base10 string
drawText("Score:",214,12); drawText("Score:",214,12);
@ -819,8 +819,8 @@ void renderGui(PlayerData *pd) {
if(awX != 0 && awY != 0){ if(awX != 0 && awY != 0){
renderc(1 + (awX/32), 47 + (awY/32), 88, 216, 8, 8, 0); // Mini-AWizard head. renderc(1 + (awX/32), 47 + (awY/32), 88, 216, 8, 8, 0); // Mini-AWizard head.
} }
} }
//TODO: Maybe also render other players? //TODO: Maybe also render other players?
renderc(1 + (pd->entity.x/32), 47 + (pd->entity.y/32), 88, 208, 8, 8, 0); // Mini-Player head. renderc(1 + (pd->entity.x/32), 47 + (pd->entity.y/32), 88, 208, 8, 8, 0); // Mini-Player head.
//quick select //quick select
@ -840,86 +840,86 @@ void renderGui(PlayerData *pd) {
} }
void renderPlayer(PlayerData *pd) { void renderPlayer(PlayerData *pd) {
if (pd->entity.level!=getLocalPlayer()->entity.level) { if (pd->entity.level!=getLocalPlayer()->entity.level) {
return; return;
} }
if (pd->entity.p.isDead) { if (pd->entity.p.isDead) {
return; return;
} }
int xo = pd->entity.x - 8; int xo = pd->entity.x - 8;
int yo = pd->entity.y - 8; int yo = pd->entity.y - 8;
//attack animation upwards //attack animation upwards
if (pd->entity.p.attackTimer > 0 && pd->entity.p.dir == 1) { if (pd->entity.p.attackTimer > 0 && pd->entity.p.dir == 1) {
renderc(xo, yo - 4, 16, 160, 16, 8, 0); renderc(xo, yo - 4, 16, 160, 16, 8, 0);
renderItemIcon(pd->activeItem->id, pd->activeItem->countLevel, xo + 4, yo - 4); renderItemIcon(pd->activeItem->id, pd->activeItem->countLevel, xo + 4, yo - 4);
} }
//find basic indices //find basic indices
int aIndexBig = 0; int aIndexBig = 0;
int aIndexSmall = 0; int aIndexSmall = 0;
switch(pd->entity.p.dir) { switch(pd->entity.p.dir) {
case 0: //down case 0: //down
aIndexBig = 0; aIndexBig = 0;
aIndexSmall = 0; aIndexSmall = 0;
break; break;
case 1: //up case 1: //up
aIndexBig = 2; aIndexBig = 2;
aIndexSmall = 1; aIndexSmall = 1;
break; break;
case 2: //left case 2: //left
aIndexBig = 7; aIndexBig = 7;
aIndexSmall = 3; aIndexSmall = 3;
break; break;
case 3: //right case 3: //right
aIndexBig = 4; aIndexBig = 4;
aIndexSmall = 2; aIndexSmall = 2;
break; break;
} }
//find index offset based on walk state //find index offset based on walk state
u8 walkingOffset = (pd->entity.p.walkDist >> 4) % 2; u8 walkingOffset = (pd->entity.p.walkDist >> 4) % 2;
if(pd->entity.p.dir==2 || pd->entity.p.dir==3) { if(pd->entity.p.dir==2 || pd->entity.p.dir==3) {
walkingOffset = (pd->entity.p.walkDist >> 4) % 4; walkingOffset = (pd->entity.p.walkDist >> 4) % 4;
if(walkingOffset==2) walkingOffset = 0; if(walkingOffset==2) walkingOffset = 0;
if(walkingOffset==3) walkingOffset = 2; if(walkingOffset==3) walkingOffset = 2;
} }
bool swimming = isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4); bool swimming = isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4);
//render water anim when swimming //render water anim when swimming
if (swimming) { if (swimming) {
renderc(xo, yo + 5, 48, 160 + (((pd->entity.p.swimTimer >> 4) & 1) << 3), 16, 8, 0); renderc(xo, yo + 5, 48, 160 + (((pd->entity.p.swimTimer >> 4) & 1) << 3), 16, 8, 0);
} }
//render the different parts //render the different parts
//legs //legs
if(!swimming) { if(!swimming) {
renderp(xo, yo, (0+aIndexBig+walkingOffset)*16, pd->sprite.legs*16); renderp(xo, yo, (0+aIndexBig+walkingOffset)*16, pd->sprite.legs*16);
} }
//body //body
renderp(xo, yo, (10+aIndexBig+walkingOffset)*16, pd->sprite.body*16); renderp(xo, yo, (10+aIndexBig+walkingOffset)*16, pd->sprite.body*16);
//arms (normal) //arms (normal)
if(!(pd->entity.p.isCarrying)) { if(!(pd->entity.p.isCarrying)) {
renderp(xo, yo, (20+aIndexBig+walkingOffset)*16, pd->sprite.arms*16); renderp(xo, yo, (20+aIndexBig+walkingOffset)*16, pd->sprite.arms*16);
} }
//head //head
renderp(xo, yo, (30+aIndexSmall)*16, pd->sprite.head*16); renderp(xo, yo, (30+aIndexSmall)*16, pd->sprite.head*16);
//eyes //eyes
renderp(xo, yo, (34+aIndexSmall)*16, pd->sprite.eyes*16); renderp(xo, yo, (34+aIndexSmall)*16, pd->sprite.eyes*16);
//arms (carrying) //arms (carrying)
if(pd->entity.p.isCarrying) { if(pd->entity.p.isCarrying) {
renderp(xo, yo, (38+aIndexSmall)*16, pd->sprite.arms*16); renderp(xo, yo, (38+aIndexSmall)*16, pd->sprite.arms*16);
} }
//furniture //furniture
if (pd->entity.p.isCarrying) { if (pd->entity.p.isCarrying) {
renderFurniture(pd->activeItem->id, xo, yo - 12); renderFurniture(pd->activeItem->id, xo, yo - 12);
} }
//attack animation (other directios) //attack animation (other directios)
if (pd->entity.p.attackTimer > 0) { if (pd->entity.p.attackTimer > 0) {
switch (pd->entity.p.dir) { switch (pd->entity.p.dir) {
case 0: case 0:
@ -939,37 +939,37 @@ void renderPlayer(PlayerData *pd) {
} }
void renderWeather(u8 level, int xScroll, int yScroll) { void renderWeather(u8 level, int xScroll, int yScroll) {
if(level==1) { if(level==1) {
if(worldData.season==3) { if(worldData.season==3) {
int xp = -128 + ((syncTickCount>>2) - xScroll*2)%128; int xp = -128 + ((syncTickCount>>2) - xScroll*2)%128;
int yp = -128 + ((syncTickCount>>1) - yScroll*2)%128; int yp = -128 + ((syncTickCount>>1) - yScroll*2)%128;
int xp2 = 0 - ((syncTickCount>>2) + xScroll*2)%128; int xp2 = 0 - ((syncTickCount>>2) + xScroll*2)%128;
int yp2 = -128 + ((syncTickCount>>1)+64 - yScroll*2)%128; int yp2 = -128 + ((syncTickCount>>1)+64 - yScroll*2)%128;
int xt; int xt;
int yt; int yt;
for(xt=0; xt<4; ++xt) { for(xt=0; xt<4; ++xt) {
for(yt=0; yt<3; ++yt) { for(yt=0; yt<3; ++yt) {
sf2d_draw_texture_part_scale(icons, xp + xt*128, yp + yt*128, 192, 0, 64, 64, 2, 2); sf2d_draw_texture_part_scale(icons, xp + xt*128, yp + yt*128, 192, 0, 64, 64, 2, 2);
sf2d_draw_texture_part_scale(icons, xp2 + xt*128, yp2 + yt*128, 192, 0, 64, 64, 2, 2); sf2d_draw_texture_part_scale(icons, xp2 + xt*128, yp2 + yt*128, 192, 0, 64, 64, 2, 2);
} }
} }
} }
if(worldData.rain) { if(worldData.rain) {
int xp = -((xScroll*2)%128); int xp = -((xScroll*2)%128);
int yp = -128 + ((syncTickCount<<2) - yScroll*2)%128; int yp = -128 + ((syncTickCount<<2) - yScroll*2)%128;
int xp2 = -((xScroll*2+8)%128); int xp2 = -((xScroll*2+8)%128);
int yp2 = -128 + ((syncTickCount<<1)+64 - yScroll*2)%128; int yp2 = -128 + ((syncTickCount<<1)+64 - yScroll*2)%128;
int xt; int xt;
int yt; int yt;
for(xt=0; xt<4; ++xt) { for(xt=0; xt<4; ++xt) {
for(yt=0; yt<3; ++yt) { for(yt=0; yt<3; ++yt) {
sf2d_draw_texture_part_scale(icons, xp + xt*128, yp + yt*128, 128, 0, 64, 64, 2, 2); sf2d_draw_texture_part_scale(icons, xp + xt*128, yp + yt*128, 128, 0, 64, 64, 2, 2);
sf2d_draw_texture_part_scale(icons, xp2 + xt*128, yp2 + yt*128, 128, 0, 64, 64, 2, 2); sf2d_draw_texture_part_scale(icons, xp2 + xt*128, yp2 + yt*128, 128, 0, 64, 64, 2, 2);
} }
} }
} }
} }
} }
void renderDayNight(PlayerData *pd) { void renderDayNight(PlayerData *pd) {
@ -998,7 +998,7 @@ void renderDayNight(PlayerData *pd) {
} }
void renderBackground(s8 level, int xScroll, int yScroll) { void renderBackground(s8 level, int xScroll, int yScroll) {
if(level == 0) { if(level == 0) {
sf2d_draw_texture_part_scale(minimap[1], (-xScroll / 3) - 256, (-yScroll / 3) - 32, 0, 0, 128, 128, 12.5, 7.5); sf2d_draw_texture_part_scale(minimap[1], (-xScroll / 3) - 256, (-yScroll / 3) - 32, 0, 0, 128, 128, 12.5, 7.5);
sf2d_draw_rectangle(0, 0, 400, 240, 0xAFDFDFDF); sf2d_draw_rectangle(0, 0, 400, 240, 0xAFDFDFDF);
} else if(level == 5) { } else if(level == 5) {
@ -1118,7 +1118,7 @@ void renderFurniture(int itemID, int x, int y) {
render16(x, y, 240, 128, 0); render16(x, y, 240, 128, 0);
break; break;
case ITEM_POTION_MAKER: case ITEM_POTION_MAKER:
render16(x, y, 240, 96, 0); render16(x, y, 192, 168, 0);
break; break;
} }
} }
@ -1314,7 +1314,7 @@ void renderEntity(Entity* e, int x, int y) {
case ENTITY_GLOWWORM: case ENTITY_GLOWWORM:
render(x-4, y-4, 224, 112, 0); render(x-4, y-4, 224, 112, 0);
break; break;
case ENTITY_NPC: case ENTITY_NPC:
render16(x - 8, y - 8, (e->npc.type*16) + 0, 64, 0); render16(x - 8, y - 8, (e->npc.type*16) + 0, 64, 0);
} }
} }
@ -1432,10 +1432,10 @@ void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, int select
else else
col = 0xFF7F7F7F; col = 0xFF7F7F7F;
if(r->recipes[i + io].itemAmountLevel==1) { if(r->recipes[i + io].itemAmountLevel==1) {
drawTextColor(getBasicItemName(r->recipes[i + io].itemResult, r->recipes[i + io].itemAmountLevel), x + 18, y + 2, col); drawTextColor(getBasicItemName(r->recipes[i + io].itemResult, r->recipes[i + io].itemAmountLevel), x + 18, y + 2, col);
} else { } else {
drawTextColor(getItemName(r->recipes[i + io].itemResult, r->recipes[i + io].itemAmountLevel), x + 18, y + 2, col); drawTextColor(getItemName(r->recipes[i + io].itemResult, r->recipes[i + io].itemAmountLevel), x + 18, y + 2, col);
} }
} }
int yy = selected + 1 - io + yo; int yy = selected + 1 - io + yo;
@ -1466,7 +1466,7 @@ void renderItemStuffWithText(int itemID, int itemCL, bool onlyOne, int x, int y)
/* For bottom screen */ /* For bottom screen */
void renderItemWithTextCentered(Item* item, int width, int y) { void renderItemWithTextCentered(Item* item, int width, int y) {
char * tn = getItemName(item->id, item->countLevel); char * tn = getItemName(item->id, item->countLevel);
int x = (width - ((strlen(tn) + 2) * 12))/2; int x = (width - ((strlen(tn) + 2) * 12))/2;
renderItemIcon(item->id, item->countLevel, x >> 1, y >> 1); renderItemIcon(item->id, item->countLevel, x >> 1, y >> 1);
@ -1478,8 +1478,8 @@ void renderItemWithTextCentered(Item* item, int width, int y) {
} }
void renderItemIcon(int itemID, int countLevel, int x, int y) { void renderItemIcon(int itemID, int countLevel, int x, int y) {
int xd; int xd;
int yd; int yd;
switch (itemID) { switch (itemID) {
case ITEM_NULL: case ITEM_NULL:
return; return;
@ -1523,7 +1523,7 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
render(x, y, 0, 152, 0); render(x, y, 0, 152, 0);
break; break;
case ITEM_WOOD: case ITEM_WOOD:
render(x, y, 8, 152, 0); render(x, y, 160, 168, 0);
break; break;
case ITEM_STONE: case ITEM_STONE:
renderb(x, y, 16, 152, 0, rockColor[1]); renderb(x, y, 16, 152, 0, rockColor[1]);
@ -1559,19 +1559,19 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
render(x, y, 80, 152, 0); render(x, y, 80, 152, 0);
break; break;
case ITEM_GOLD_APPLE: case ITEM_GOLD_APPLE:
render(x, y, 177, 160, 0); render(x, y, 144, 168, 0);
break; break;
case ITEM_STRENGTH_POTION: case ITEM_STRENGTH_POTION:
render(x, y, 184, 160, 0); render(x, y, 176, 160, 0);
break; break;
case ITEM_SPEED_POTION: case ITEM_SPEED_POTION:
render(x, y, 191, 160, 0); render(x, y, 184, 160, 0);
break; break;
case ITEM_REGEN_POTION: case ITEM_REGEN_POTION:
render(x, y, 198, 160, 0); render(x, y, 192, 160, 0);
break; break;
case ITEM_SWIM_BREATH_POTION: case ITEM_SWIM_BREATH_POTION:
render(x, y, 219, 160, 0); render(x, y, 200, 160, 0);
break; break;
case ITEM_SLIME: case ITEM_SLIME:
renderb(x, y, 88, 152, 0, 0xFF4DC04D); renderb(x, y, 88, 152, 0, 0xFF4DC04D);
@ -1604,7 +1604,7 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
render(x, y, 144, 160, 0); render(x, y, 144, 160, 0);
break; break;
case ITEM_POTION_MAKER: case ITEM_POTION_MAKER:
render(x, y, 216, 152, 0); render(x, y, 192, 168, 0);
break; break;
case ITEM_WALL_WOOD: case ITEM_WALL_WOOD:
renderb(x, y, 224, 144, 0, woodColor); renderb(x, y, 224, 144, 0, woodColor);
@ -1672,14 +1672,14 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
case ITEM_DRAGON_SCALE: case ITEM_DRAGON_SCALE:
render(x, y, 168, 160, 0); render(x, y, 168, 160, 0);
break; break;
case ITEM_BOOKSHELVES: case ITEM_BOOKSHELVES:
render(x, y, 232, 144, 0); render(x, y, 232, 144, 0);
break; break;
case ITEM_MAGIC_DUST: case ITEM_MAGIC_DUST:
render(x, y, 200, 152, 0); render(x, y, 200, 152, 0);
break; break;
case ITEM_COIN: case ITEM_COIN:
render(x, y, 208, 152, 0); render(x, y, 208, 152, 0);
break; break;
case TOOL_BUCKET: case TOOL_BUCKET:
render(x, y, 200 + countLevel * 8, 144, 0); render(x, y, 200 + countLevel * 8, 144, 0);
@ -1687,16 +1687,16 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
case TOOL_BOW: case TOOL_BOW:
render(x, y, 64, 168, 0); render(x, y, 64, 168, 0);
break; break;
case TOOL_MAGIC_COMPASS: case TOOL_MAGIC_COMPASS:
xd = worldData.compassData[getLocalPlayer()->entity.level][0] - (getLocalPlayer()->entity.x>>4); xd = worldData.compassData[getLocalPlayer()->entity.level][0] - (getLocalPlayer()->entity.x>>4);
yd = worldData.compassData[getLocalPlayer()->entity.level][1] - (getLocalPlayer()->entity.y>>4); yd = worldData.compassData[getLocalPlayer()->entity.level][1] - (getLocalPlayer()->entity.y>>4);
if(abs(yd)>abs(xd)) { if(abs(yd)>abs(xd)) {
if(yd<0) render(x, y, 112, 168, 0); if(yd<0) render(x, y, 112, 168, 0);
else render(x, y, 120, 168, 0); else render(x, y, 120, 168, 0);
} else { } else {
if(xd<0) render(x, y, 128, 168, 0); if(xd<0) render(x, y, 128, 168, 0);
else render(x, y, 136, 168, 0); else render(x, y, 136, 168, 0);
} }
break; break;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -5,48 +5,48 @@ int soundListenerX;
int soundListenerY; int soundListenerY;
void loadSound(Sound * snd, char * filename){ void loadSound(Sound * snd, char * filename){
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
if(file != NULL){ if(file != NULL){
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
snd->size = ftell(file)/2; snd->size = ftell(file)/2;
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
snd->buffer = linearAlloc(snd->size*sizeof(u16)); snd->buffer = linearAlloc(snd->size*sizeof(u16));
fread(snd->buffer, 1, snd->size, file); fread(snd->buffer, 1, snd->size, file);
} }
fclose(file); fclose(file);
} }
void playSound(Sound snd){ void playSound(Sound snd){
csndPlaySound(8, SOUND_FORMAT_16BIT | SOUND_ONE_SHOT, 44100, 1, 0, snd.buffer, snd.buffer, snd.size); csndPlaySound(8, SOUND_FORMAT_16BIT | SOUND_ONE_SHOT, 44100, 1, 0, snd.buffer, snd.buffer, snd.size);
} }
void playSoundPositioned(Sound snd, s8 level, int x, int y) { void playSoundPositioned(Sound snd, s8 level, int x, int y) {
if(level != soundListenerLevel) return; if(level != soundListenerLevel) return;
int xd = soundListenerX - x; int xd = soundListenerX - x;
int yd = soundListenerY - y; int yd = soundListenerY - y;
if (xd * xd + yd * yd > 80 * 80) return; if (xd * xd + yd * yd > 80 * 80) return;
csndPlaySound(8, SOUND_FORMAT_16BIT | SOUND_ONE_SHOT, 44100, 1, 0, snd.buffer, snd.buffer, snd.size); csndPlaySound(8, SOUND_FORMAT_16BIT | SOUND_ONE_SHOT, 44100, 1, 0, snd.buffer, snd.buffer, snd.size);
} }
void setListenerPosition(s8 level, int x, int y) { void setListenerPosition(s8 level, int x, int y) {
soundListenerLevel = level; soundListenerLevel = level;
soundListenerX = x; soundListenerX = x;
soundListenerY = y; soundListenerY = y;
} }
void playMusic(Sound *snd){ void playMusic(Sound *snd){
static Sound *lastSnd; static Sound *lastSnd;
if(lastSnd==snd) return; if(lastSnd==snd) return;
lastSnd = snd; lastSnd = snd;
csndPlaySound(10, SOUND_FORMAT_16BIT | SOUND_REPEAT, 44100, 1, 0, snd->buffer, snd->buffer, snd->size); csndPlaySound(10, SOUND_FORMAT_16BIT | SOUND_REPEAT, 44100, 1, 0, snd->buffer, snd->buffer, snd->size);
} }
void stopMusic() { void stopMusic() {
CSND_SetPlayState(8, 0); CSND_SetPlayState(8, 0);
CSND_SetPlayState(10, 0); CSND_SetPlayState(10, 0);
csndExecCmds(true); csndExecCmds(true);
} }
void updateMusic(int lvl, int time) { void updateMusic(int lvl, int time) {
@ -87,13 +87,13 @@ void loadSounds() {
} }
void freeSounds(){ void freeSounds(){
linearFree(snd_playerHurt.buffer); linearFree(snd_playerHurt.buffer);
linearFree(snd_playerDeath.buffer); linearFree(snd_playerDeath.buffer);
linearFree(snd_monsterHurt.buffer); linearFree(snd_monsterHurt.buffer);
linearFree(snd_test.buffer); linearFree(snd_test.buffer);
linearFree(snd_pickup.buffer); linearFree(snd_pickup.buffer);
linearFree(snd_bossdeath.buffer); linearFree(snd_bossdeath.buffer);
linearFree(snd_craft.buffer); linearFree(snd_craft.buffer);
linearFree(music_menu.buffer); linearFree(music_menu.buffer);
linearFree(music_floor0.buffer); linearFree(music_floor0.buffer);

View file

@ -6,8 +6,8 @@
typedef struct { typedef struct {
u32 size; u32 size;
u8 * buffer; u8 * buffer;
} Sound; } Sound;
void loadSound(Sound * snd, char * filename); void loadSound(Sound * snd, char * filename);

View file

@ -21,204 +21,204 @@ void synchronizerSendLocalInputs();
int synchronizerGetTurnIndex(u32 turn); int synchronizerGetTurnIndex(u32 turn);
void synchronizerInit(int seed, int initPlayerCount, int initPlayerLocalID) { void synchronizerInit(int seed, int initPlayerCount, int initPlayerLocalID) {
synchronizerLocalTurn = 0; synchronizerLocalTurn = 0;
synchronizerNextSeed = seed; synchronizerNextSeed = seed;
playerCount = initPlayerCount; playerCount = initPlayerCount;
playerLocalID = initPlayerLocalID; playerLocalID = initPlayerLocalID;
syncTickCount = 0; syncTickCount = 0;
//reset player turn states (e.g. is turn data recieved), first turn needs to happen with no inputs //reset player turn states (e.g. is turn data recieved), first turn needs to happen with no inputs
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
resetKeys(&(players[i].inputs)); resetKeys(&(players[i].inputs));
for(int j=0; j<MAX_INPUT_BUFFER; j++) { for(int j=0; j<MAX_INPUT_BUFFER; j++) {
resetKeys(&(players[i].nextInputs[j])); resetKeys(&(players[i].nextInputs[j]));
} }
players[i].nextTurnReady[0] = true; players[i].nextTurnReady[0] = true;
players[i].idSet = false; players[i].idSet = false;
players[i].ready = false; players[i].ready = false;
} }
players[playerLocalID].id = localUID; players[playerLocalID].id = localUID;
players[playerLocalID].idSet = true; players[playerLocalID].idSet = true;
players[playerLocalID].ready = true; players[playerLocalID].ready = true;
//switch menu //switch menu
currentMenu = MENU_LOADING; currentMenu = MENU_LOADING;
synchronizerRunning = false; synchronizerRunning = false;
} }
void synchronizerSendUID() { void synchronizerSendUID() {
sendIDPacket(playerLocalID, localUID); sendIDPacket(playerLocalID, localUID);
} }
void synchronizerSetPlayerUID(int playerID, u32 uid) { void synchronizerSetPlayerUID(int playerID, u32 uid) {
players[playerID].id = uid; players[playerID].id = uid;
players[playerID].idSet = true; players[playerID].idSet = true;
} }
void synchronizerSendIfReady() { void synchronizerSendIfReady() {
//we are ready when we recieved all uids //we are ready when we recieved all uids
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
if(!players[i].idSet) { if(!players[i].idSet) {
return; return;
} }
} }
//ready -> send to server //ready -> send to server
sendStartReadyPacket(playerLocalID); sendStartReadyPacket(playerLocalID);
} }
void synchronizerSetPlayerReady(int playerID) { void synchronizerSetPlayerReady(int playerID) {
players[playerID].ready = true; players[playerID].ready = true;
} }
bool synchronizerAllReady() { bool synchronizerAllReady() {
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
if(!players[i].ready) { if(!players[i].ready) {
return false; return false;
} }
} }
return true; return true;
} }
void synchronizerStart() { void synchronizerStart() {
//check if save file is present //check if save file is present
bool doLoad = false; bool doLoad = false;
char *loadName = NULL; char *loadName = NULL;
//host and single player need to load the actual file //host and single player need to load the actual file
if(playerLocalID==0) { if(playerLocalID==0) {
FILE *file = fopen(currentFileName, "rb"); FILE *file = fopen(currentFileName, "rb");
if(file!=NULL) { if(file!=NULL) {
fclose(file); fclose(file);
doLoad = true; doLoad = true;
loadName = currentFileName; loadName = currentFileName;
} }
//all others the transfered one //all others the transfered one
} else { } else {
FILE *file = fopen("tmpTransfer.bin", "rb"); FILE *file = fopen("tmpTransfer.bin", "rb");
if(file!=NULL) { if(file!=NULL) {
fclose(file); fclose(file);
doLoad = true; doLoad = true;
loadName = "tmpTransfer.bin"; loadName = "tmpTransfer.bin";
} }
} }
// reset random generators // reset random generators
srand(synchronizerNextSeed); srand(synchronizerNextSeed);
gaussrand(true); gaussrand(true);
//start the game //start the game
startGame(doLoad, loadName); startGame(doLoad, loadName);
//remove transfered save file from clients //remove transfered save file from clients
if(playerLocalID!=0) { if(playerLocalID!=0) {
FILE *file = fopen("tmpTransfer.bin", "rb"); FILE *file = fopen("tmpTransfer.bin", "rb");
if(file!=NULL) { if(file!=NULL) {
fclose(file); fclose(file);
remove("tmpTransfer.bin"); remove("tmpTransfer.bin");
} }
} }
//clear menu //clear menu
currentMenu = MENU_NONE; currentMenu = MENU_NONE;
synchronizerRunning = true; synchronizerRunning = true;
synchronizerCurrentTicks = SYNCHRONIZER_TICKS_PER_TURN; synchronizerCurrentTicks = SYNCHRONIZER_TICKS_PER_TURN;
} }
void synchronizerTick(void (*gtick)(void)) { void synchronizerTick(void (*gtick)(void)) {
if(synchronizerRunning && synchronizerTurnReady()) { if(synchronizerRunning && synchronizerTurnReady()) {
synchronizerNextTurn(); synchronizerNextTurn();
// reset random generators // reset random generators
srand(synchronizerNextSeed); srand(synchronizerNextSeed);
gaussrand(true); gaussrand(true);
syncTickCount++; syncTickCount++;
//call game tick //call game tick
(*gtick)(); (*gtick)();
synchronizerNextSeed = rand(); synchronizerNextSeed = rand();
} }
} }
//Test if all players (including single player) input is recieved //Test if all players (including single player) input is recieved
bool synchronizerTurnReady() { bool synchronizerTurnReady() {
if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) return true; if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) return true;
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
if(!players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)]) { if(!players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)]) {
return false; return false;
} }
} }
return true; return true;
} }
void synchronizerNextTurn() { void synchronizerNextTurn() {
if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) { if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) {
synchronizerCurrentTicks++; synchronizerCurrentTicks++;
//clicked events are only fired for the first tick per turn //clicked events are only fired for the first tick per turn
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
resetClicked(&(players[i].inputs)); resetClicked(&(players[i].inputs));
} }
} else { } else {
//move nextInput of every player to currentInput //move nextInput of every player to currentInput
for(int i=0; i<playerCount; i++) { for(int i=0; i<playerCount; i++) {
players[i].inputs = players[i].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)]; players[i].inputs = players[i].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)];
players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = false; players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = false;
} }
//Increase turn number //Increase turn number
synchronizerLocalTurn++; synchronizerLocalTurn++;
synchronizerCurrentTicks = 1; synchronizerCurrentTicks = 1;
//send local input //send local input
synchronizerSendLocalInputs(); synchronizerSendLocalInputs();
} }
} }
void synchronizerSendLocalInputs() { void synchronizerSendLocalInputs() {
//scan local inputs //scan local inputs
hidScanInput(); hidScanInput();
tickKeys(&localInputs, hidKeysHeld(), hidKeysDown()); tickKeys(&localInputs, hidKeysHeld(), hidKeysDown());
//store local input in nextInput //store local input in nextInput
players[playerLocalID].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)] = localInputs; players[playerLocalID].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)] = localInputs;
players[playerLocalID].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = true; players[playerLocalID].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = true;
//send local input //send local input
if(playerCount>1) { if(playerCount>1) {
size_t size = writeInputPacket(networkWriteBuffer, &localInputs, playerLocalID, synchronizerLocalTurn); size_t size = writeInputPacket(networkWriteBuffer, &localInputs, playerLocalID, synchronizerLocalTurn);
networkSend(networkWriteBuffer, size); networkSend(networkWriteBuffer, size);
} }
} }
void synchronizerOnInputPacket(u8 playerID, u32 turnNumber, void *data, size_t dataSize) { void synchronizerOnInputPacket(u8 playerID, u32 turnNumber, void *data, size_t dataSize) {
if(turnNumber>=synchronizerLocalTurn && turnNumber<synchronizerLocalTurn+MAX_INPUT_BUFFER && playerID<playerCount) { if(turnNumber>=synchronizerLocalTurn && turnNumber<synchronizerLocalTurn+MAX_INPUT_BUFFER && playerID<playerCount) {
if(readInputPacketData(data, dataSize, &(players[playerID].nextInputs[synchronizerGetTurnIndex(turnNumber)]))) { if(readInputPacketData(data, dataSize, &(players[playerID].nextInputs[synchronizerGetTurnIndex(turnNumber)]))) {
players[playerID].nextTurnReady[synchronizerGetTurnIndex(turnNumber)] = true; players[playerID].nextTurnReady[synchronizerGetTurnIndex(turnNumber)] = true;
} }
} }
} }
int synchronizerGetTurnIndex(u32 turn) { int synchronizerGetTurnIndex(u32 turn) {
return turn%MAX_INPUT_BUFFER; return turn%MAX_INPUT_BUFFER;
} }
void synchronizerReset() { void synchronizerReset() {
synchronizerRunning = false; synchronizerRunning = false;
synchronizerCurrentTicks = 0; synchronizerCurrentTicks = 0;
} }
bool synchronizerIsRunning() { bool synchronizerIsRunning() {
return synchronizerRunning; return synchronizerRunning;
} }
// helpers for random numbers // helpers for random numbers
@ -229,12 +229,12 @@ double gaussrand(bool reset)
static int phase = 0; static int phase = 0;
double Z; double Z;
if(reset) { if(reset) {
U = 0; U = 0;
V = 0; V = 0;
phase = 0; phase = 0;
return 0; return 0;
} }
if(phase == 0) { if(phase == 0) {
U = (rand() + 1.) / (RAND_MAX + 2.); U = (rand() + 1.) / (RAND_MAX + 2.);
@ -242,7 +242,7 @@ double gaussrand(bool reset)
Z = sqrt(-2 * log(U)) * sin(2 * PI * V); Z = sqrt(-2 * log(U)) * sin(2 * PI * V);
} else { } else {
Z = sqrt(-2 * log(U)) * cos(2 * PI * V); Z = sqrt(-2 * log(U)) * cos(2 * PI * V);
} }
phase = 1 - phase; phase = 1 - phase;

View file

@ -11,203 +11,203 @@
#define READ_SIZE 9216 #define READ_SIZE 9216
int unzipAndLoad(char *filename, int (*fileCallback)(char *filename), char *expectedComment, int keepFiles) { int unzipAndLoad(char *filename, int (*fileCallback)(char *filename), char *expectedComment, int keepFiles) {
// Open the zip file // Open the zip file
unzFile *zipfile = unzOpen(filename); unzFile *zipfile = unzOpen(filename);
if (zipfile == NULL) { if (zipfile == NULL) {
return 1; // Error: ZipFile could not be opened. return 1; // Error: ZipFile could not be opened.
} }
// Get info about the zip file // Get info about the zip file
unz_global_info global_info; unz_global_info global_info;
if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK) { if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK) {
unzClose(zipfile); unzClose(zipfile);
return 2; // Error: Could not read global info return 2; // Error: Could not read global info
} }
if(expectedComment!=NULL) { if(expectedComment!=NULL) {
char *buffer = malloc(global_info.size_comment+1); char *buffer = malloc(global_info.size_comment+1);
if(buffer==NULL) { if(buffer==NULL) {
unzClose(zipfile); unzClose(zipfile);
return 3; // Error: Could not read global comment return 3; // Error: Could not read global comment
} }
if (unzGetGlobalComment(zipfile, buffer, global_info.size_comment+1) < 0) { if (unzGetGlobalComment(zipfile, buffer, global_info.size_comment+1) < 0) {
unzClose(zipfile); unzClose(zipfile);
return 3; // Error: Could not read global comment return 3; // Error: Could not read global comment
} }
if (strcmp(expectedComment, buffer)!=0) { if (strcmp(expectedComment, buffer)!=0) {
unzClose(zipfile); unzClose(zipfile);
return 4; // Error: Global comment did not have expected value return 4; // Error: Global comment did not have expected value
} }
free(buffer); free(buffer);
} }
// Buffer to hold data read from the zip file. // Buffer to hold data read from the zip file.
void *read_buffer = malloc(READ_SIZE); void *read_buffer = malloc(READ_SIZE);
if(read_buffer==NULL) { if(read_buffer==NULL) {
// Error: Could not allocate read buffer // Error: Could not allocate read buffer
return 5; return 5;
} }
// Loop to extract all files // Loop to extract all files
uLong i; uLong i;
for (i = 0; i < global_info.number_entry; ++i) { for (i = 0; i < global_info.number_entry; ++i) {
// Get info about current file. // Get info about current file.
unz_file_info file_info; unz_file_info file_info;
char filename[MAX_FILENAME]; char filename[MAX_FILENAME];
if (unzGetCurrentFileInfo(zipfile, &file_info, filename, MAX_FILENAME, NULL, 0, NULL, 0 ) != UNZ_OK) { if (unzGetCurrentFileInfo(zipfile, &file_info, filename, MAX_FILENAME, NULL, 0, NULL, 0 ) != UNZ_OK) {
free(read_buffer); free(read_buffer);
unzClose(zipfile); unzClose(zipfile);
return 6; // Error: Could not read file info return 6; // Error: Could not read file info
} }
// Check if this entry is NOT a directory or file. // Check if this entry is NOT a directory or file.
const size_t filename_length = strlen(filename); const size_t filename_length = strlen(filename);
if (filename[ filename_length-1 ] != dir_delimter){ if (filename[ filename_length-1 ] != dir_delimter){
if (unzOpenCurrentFile( zipfile ) != UNZ_OK) { if (unzOpenCurrentFile( zipfile ) != UNZ_OK) {
free(read_buffer); free(read_buffer);
unzClose(zipfile); unzClose(zipfile);
return 7; return 7;
} }
// Open a file to write out the data. // Open a file to write out the data.
FILE * out = fopen(filename, "wb"); FILE * out = fopen(filename, "wb");
if (out == NULL) { if (out == NULL) {
free(read_buffer); free(read_buffer);
unzCloseCurrentFile(zipfile); unzCloseCurrentFile(zipfile);
unzClose(zipfile); unzClose(zipfile);
return 8; return 8;
} }
int error = UNZ_OK; int error = UNZ_OK;
do { do {
error = unzReadCurrentFile(zipfile, read_buffer, READ_SIZE); error = unzReadCurrentFile(zipfile, read_buffer, READ_SIZE);
if ( error < 0 ) { if ( error < 0 ) {
//printf("error %d\n", error); //printf("error %d\n", error);
free(read_buffer); free(read_buffer);
unzCloseCurrentFile(zipfile); unzCloseCurrentFile(zipfile);
unzClose(zipfile); unzClose(zipfile);
fclose(out); fclose(out);
remove(filename); remove(filename);
return 9; return 9;
} }
// Write data to file. // Write data to file.
if (error > 0) { if (error > 0) {
fwrite(read_buffer, error, 1, out); // You should check return of fwrite... fwrite(read_buffer, error, 1, out); // You should check return of fwrite...
} }
} while (error > 0); } while (error > 0);
fclose(out); fclose(out);
//run callback //run callback
if((*fileCallback)(filename) != 0) { if((*fileCallback)(filename) != 0) {
free(read_buffer); free(read_buffer);
unzClose(zipfile); unzClose(zipfile);
remove(filename); remove(filename);
return 10; // Error: Callback error return 10; // Error: Callback error
} }
if(keepFiles==ZIPHELPER_CLEANUP_FILES) { if(keepFiles==ZIPHELPER_CLEANUP_FILES) {
remove(filename); remove(filename);
} }
} }
unzCloseCurrentFile(zipfile); unzCloseCurrentFile(zipfile);
// Go the the next entry listed in the zip file. // Go the the next entry listed in the zip file.
if (( i+1 ) < global_info.number_entry) { if (( i+1 ) < global_info.number_entry) {
if (unzGoToNextFile( zipfile ) != UNZ_OK) { if (unzGoToNextFile( zipfile ) != UNZ_OK) {
free(read_buffer); free(read_buffer);
unzClose(zipfile); unzClose(zipfile);
return 11; return 11;
} }
} }
} }
free(read_buffer); free(read_buffer);
unzClose(zipfile); unzClose(zipfile);
return 0; return 0;
} }
int zipFiles(char *filename, char **files, int fileCount, int mode, char *comment) { int zipFiles(char *filename, char **files, int fileCount, int mode, char *comment) {
// Set mode // Set mode
int zipMode = mode==ZIPHELPER_ADD ? APPEND_STATUS_ADDINZIP : APPEND_STATUS_CREATE; int zipMode = mode==ZIPHELPER_ADD ? APPEND_STATUS_ADDINZIP : APPEND_STATUS_CREATE;
FILE *testFile = fopen(filename, "r"); FILE *testFile = fopen(filename, "r");
if(testFile!=NULL) { if(testFile!=NULL) {
fclose(testFile); fclose(testFile);
} else { } else {
zipMode = APPEND_STATUS_CREATE; zipMode = APPEND_STATUS_CREATE;
} }
// Open the zip file // Open the zip file
zipFile *zipfile = zipOpen(filename, zipMode); zipFile *zipfile = zipOpen(filename, zipMode);
if (zipfile == NULL) return 1; // Error: ZipFile could not be opened. if (zipfile == NULL) return 1; // Error: ZipFile could not be opened.
// Buffer to hold data read from the files. // Buffer to hold data read from the files.
void *read_buffer = malloc(READ_SIZE); void *read_buffer = malloc(READ_SIZE);
if(read_buffer==NULL) { if(read_buffer==NULL) {
// Error: Could not allocate read buffer // Error: Could not allocate read buffer
return 2; return 2;
} }
// Loop all files to add // Loop all files to add
for(int i = 0; i < fileCount; i++) { for(int i = 0; i < fileCount; i++) {
// Open a zipfile to write out the data. // Open a zipfile to write out the data.
if (zipOpenNewFileInZip(zipfile, files[i], NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) { if (zipOpenNewFileInZip(zipfile, files[i], NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) {
free(read_buffer); free(read_buffer);
zipClose(zipfile, ""); zipClose(zipfile, "");
return 3; return 3;
} }
// Open a file to read the data. // Open a file to read the data.
FILE *in = fopen(files[i], "rb"); FILE *in = fopen(files[i], "rb");
if (in == NULL) { if (in == NULL) {
free(read_buffer); free(read_buffer);
zipCloseFileInZip(zipfile); zipCloseFileInZip(zipfile);
zipClose(zipfile, ""); zipClose(zipfile, "");
return 4; return 4;
} }
size_t size; size_t size;
do do
{ {
size = fread(read_buffer, 1, READ_SIZE, in); size = fread(read_buffer, 1, READ_SIZE, in);
if(size<READ_SIZE) { if(size<READ_SIZE) {
if(!feof(in)) { if(!feof(in)) {
free(read_buffer); free(read_buffer);
zipCloseFileInZip(zipfile); zipCloseFileInZip(zipfile);
zipClose(zipfile, ""); zipClose(zipfile, "");
fclose(in); fclose(in);
return 5; return 5;
} }
} }
if(size>0) { if(size>0) {
//write data to zip //write data to zip
if (zipWriteInFileInZip(zipfile, read_buffer, size) != ZIP_OK) { if (zipWriteInFileInZip(zipfile, read_buffer, size) != ZIP_OK) {
//printf("error %d\n", error); //printf("error %d\n", error);
free(read_buffer); free(read_buffer);
zipCloseFileInZip(zipfile); zipCloseFileInZip(zipfile);
zipClose(zipfile, ""); zipClose(zipfile, "");
fclose(in); fclose(in);
return 6; return 6;
} }
} }
} while (size > 0); } while (size > 0);
fclose(in); fclose(in);
zipCloseFileInZip(zipfile); zipCloseFileInZip(zipfile);
} }
free(read_buffer); free(read_buffer);
zipClose(zipfile, comment); zipClose(zipfile, comment);
return 0; return 0;
} }

View file

@ -135,7 +135,7 @@ int main() {
quitGame = false; quitGame = false;
initBGMap = 1; initBGMap = 1;
icons = sfil_load_PNG_buffer(icons2_png, SF2D_PLACE_RAM); icons = sfil_load_PNG_buffer(icons_png, SF2D_PLACE_RAM);
playerSprites = sfil_load_PNG_buffer(player_png, SF2D_PLACE_RAM); playerSprites = sfil_load_PNG_buffer(player_png, SF2D_PLACE_RAM);
font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM); font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM);
bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM); bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM);
@ -163,18 +163,18 @@ int main() {
localInputs.k_down.input = KEY_DDOWN | KEY_CPAD_DOWN | KEY_CSTICK_DOWN; localInputs.k_down.input = KEY_DDOWN | KEY_CPAD_DOWN | KEY_CSTICK_DOWN;
localInputs.k_left.input = KEY_DLEFT | KEY_CPAD_LEFT | KEY_CSTICK_LEFT; localInputs.k_left.input = KEY_DLEFT | KEY_CPAD_LEFT | KEY_CSTICK_LEFT;
localInputs.k_right.input = KEY_DRIGHT | KEY_CPAD_RIGHT | KEY_CSTICK_RIGHT; localInputs.k_right.input = KEY_DRIGHT | KEY_CPAD_RIGHT | KEY_CSTICK_RIGHT;
localInputs.k_attack.input = KEY_A | KEY_B | KEY_L | KEY_ZR; localInputs.k_attack.input = KEY_A | KEY_B;
localInputs.k_menu.input = KEY_X | KEY_Y | KEY_R | KEY_ZL; localInputs.k_menu.input = KEY_X | KEY_Y;
localInputs.k_pause.input = KEY_START; localInputs.k_pause.input = KEY_START;
localInputs.k_accept.input = KEY_A; localInputs.k_accept.input = KEY_A;
localInputs.k_decline.input = KEY_B; localInputs.k_decline.input = KEY_B;
localInputs.k_delete.input = KEY_X; localInputs.k_delete.input = KEY_X;
localInputs.k_menuNext.input = KEY_R; localInputs.k_menuNext.input = KEY_R | KEY_ZR;
localInputs.k_menuPrev.input = KEY_L; localInputs.k_menuPrev.input = KEY_L | KEY_ZL;
/* If btnSave exists, then use that. */ /* If btnSave exists, then use that. */
if ((file = fopen("btnSave.bin", "rb"))) { if ((file = fopen("btnSave.bin", "rb"))) {
fread(&(localInputs.k_up.input), sizeof(int), 1, file); fread(&(localInputs.k_up.input), sizeof(int), 1, file);
fread(&(localInputs.k_down.input), sizeof(int), 1, file); fread(&(localInputs.k_down.input), sizeof(int), 1, file);
fread(&(localInputs.k_left.input), sizeof(int), 1, file); fread(&(localInputs.k_left.input), sizeof(int), 1, file);
fread(&(localInputs.k_right.input), sizeof(int), 1, file); fread(&(localInputs.k_right.input), sizeof(int), 1, file);

View file

@ -10,91 +10,91 @@ bool texturepackUseDefaultFont = true;
bool texturepackUseDefaultBottom = true; bool texturepackUseDefaultBottom = true;
void toLowerString(char * str){ void toLowerString(char * str){
int i; int i;
for (i = 0; str[i] != '\0'; i++)str[i] = (char)tolower((unsigned char)str[i]); for (i = 0; str[i] != '\0'; i++)str[i] = (char)tolower((unsigned char)str[i]);
} }
int getTexturePackComment(char * filename, char * cmmtBuf){ int getTexturePackComment(char * filename, char * cmmtBuf){
// Open the zip file // Open the zip file
unzFile *zipfile = unzOpen(filename); unzFile *zipfile = unzOpen(filename);
if ( zipfile == NULL ) return 1; // Error: ZipFile could not be opened. if ( zipfile == NULL ) return 1; // Error: ZipFile could not be opened.
// Get info about the zip file // Get info about the zip file
unz_global_info global_info; unz_global_info global_info;
if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK ) if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK )
{ {
unzClose( zipfile ); unzClose( zipfile );
return 2; // Error: Could not read global info return 2; // Error: Could not read global info
} }
unzGetGlobalComment(zipfile, cmmtBuf, 58); unzGetGlobalComment(zipfile, cmmtBuf, 58);
unzClose( zipfile ); unzClose( zipfile );
return 0; return 0;
} }
int loadTexture(char * filename) { int loadTexture(char * filename) {
char lowerFilename[MAX_FILENAME]; char lowerFilename[MAX_FILENAME];
strcpy(lowerFilename,filename); strcpy(lowerFilename,filename);
toLowerString(lowerFilename); toLowerString(lowerFilename);
if(strcmp(lowerFilename, "icons.png") == 0){ if(strcmp(lowerFilename, "icons.png") == 0){
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
return 0; return 0;
} }
icons = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); icons = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
reloadColors(); reloadColors();
texturepackUseDefaultIcons = false; texturepackUseDefaultIcons = false;
} else if(strcmp(lowerFilename, "player.png") == 0){ } else if(strcmp(lowerFilename, "player.png") == 0){
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
return 0; return 0;
} }
playerSprites = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); playerSprites = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
texturepackUseDefaultPlayer = false; texturepackUseDefaultPlayer = false;
} else if(strcmp(lowerFilename, "font.png") == 0){ } else if(strcmp(lowerFilename, "font.png") == 0){
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
return 0; return 0;
} }
font = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); font = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
texturepackUseDefaultFont = false; texturepackUseDefaultFont = false;
} else if(strcmp(lowerFilename, "bottombg.png") == 0){ } else if(strcmp(lowerFilename, "bottombg.png") == 0){
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
return 0; return 0;
} }
bottombg = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); bottombg = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
texturepackUseDefaultBottom = false; texturepackUseDefaultBottom = false;
} }
return 0; return 0;
} }
int loadTexturePack(char * filename) { int loadTexturePack(char * filename) {
texturepackUseDefaultIcons = true; texturepackUseDefaultIcons = true;
texturepackUseDefaultPlayer = true; texturepackUseDefaultPlayer = true;
texturepackUseDefaultFont = true; texturepackUseDefaultFont = true;
texturepackUseDefaultBottom = true; texturepackUseDefaultBottom = true;
if(unzipAndLoad(filename, &loadTexture, NULL, ZIPHELPER_CLEANUP_FILES)!=0) { if(unzipAndLoad(filename, &loadTexture, NULL, ZIPHELPER_CLEANUP_FILES)!=0) {
return 1; return 1;
} }
if(texturepackUseDefaultIcons){ if(texturepackUseDefaultIcons){
icons = sfil_load_PNG_buffer(icons2_png, SF2D_PLACE_RAM); icons = sfil_load_PNG_buffer(icons_png, SF2D_PLACE_RAM);
reloadColors(); reloadColors();
} }
if(texturepackUseDefaultPlayer) playerSprites = sfil_load_PNG_buffer(player_png, SF2D_PLACE_RAM); if(texturepackUseDefaultPlayer) playerSprites = sfil_load_PNG_buffer(player_png, SF2D_PLACE_RAM);
if(texturepackUseDefaultFont) font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM); if(texturepackUseDefaultFont) font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM);
if(texturepackUseDefaultBottom) bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM); if(texturepackUseDefaultBottom) bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM);
return 0; return 0;
} }