Compare commits
12 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
43ce7184e1 | ||
![]() |
7b42d7dc1d | ||
![]() |
873c7bc06e | ||
![]() |
80c95de053 | ||
![]() |
7bc9c274de | ||
![]() |
24460ee48c | ||
![]() |
52ab48ba55 | ||
![]() |
a5ea06a928 | ||
![]() |
5423be67ca | ||
![]() |
4f0e3c4dd4 | ||
![]() |
7402ac40fb | ||
![]() |
06b18f3c64 |
50 changed files with 7563 additions and 7455 deletions
BIN
3dslink.exe
BIN
3dslink.exe
Binary file not shown.
BIN
3dstool.exe
BIN
3dstool.exe
Binary file not shown.
4
Makefile
4
Makefile
|
@ -36,8 +36,8 @@ INCLUDES := include
|
|||
ROMFS := romfs
|
||||
|
||||
APP_TITLE := Minicraft 3DS
|
||||
APP_DESCRIPTION := Minicraft was originally created by Markus "Notch" Perrson. Ported to the 3DS by Davideesk.
|
||||
APP_AUTHOR := Davideesk/andre111/ElijahZAwesome
|
||||
APP_DESCRIPTION := Originally created by Notch.
|
||||
APP_AUTHOR := Davideesk/andre111/ElijahZAwesome/tognee
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
|
|
|
@ -7,7 +7,7 @@ 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
|
||||
//TODO
|
||||
For building the game yourself look below.
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ zlib: http://www.zlib.net/
|
|||
**2. Install zlib, libjpeg-turbo and libpng**
|
||||
- Download 3DS-Portlibs: https://github.com/devkitPro/3ds_portlibs
|
||||
- Run these commands:
|
||||
|
||||
|
||||
```
|
||||
make zlib
|
||||
make install-zlib
|
||||
|
@ -68,11 +68,11 @@ zlib: http://www.zlib.net/
|
|||
----------
|
||||
|
||||
|
||||
You can do anything with the source code (besides sell it) as long as you give proper credit to the right people.
|
||||
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/
|
||||
Forum thread: //TODO
|
||||
|
|
BIN
bannertool.exe
BIN
bannertool.exe
Binary file not shown.
|
@ -1,11 +1,10 @@
|
|||
@echo off
|
||||
echo Building 3DSX/ELF/SMDH...
|
||||
set mypath=%cd%
|
||||
make
|
||||
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...
|
||||
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...
|
||||
3dstool -cvtf romfs icons-banners/romfs.bin --romfs-dir romfs/
|
||||
echo Creating CIA...
|
||||
|
@ -15,4 +14,4 @@ makerom -f cci -o result/Minicraft3DS.3ds -DAPP_ENCRYPTED=true -rsf icons-banner
|
|||
echo Cleaning Up...
|
||||
del /s result\Minicraft3DS.elf
|
||||
del /s result\Minicraft3DS.smdh
|
||||
pause
|
||||
pause
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
cd "`dirname $0`"
|
||||
echo Building 3DSX/ELF/SMDH...
|
||||
make
|
||||
echo Creating banner...
|
||||
`dirname $0`/bannertool makebanner -i icons-banners/banner.png -a icons-banners/audio.wav -o icons-banners/banner.bnr
|
||||
echo Creating icon...
|
||||
`dirname $0`/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 CIA...
|
||||
`dirname $0`/makerom -f cia -o result/Minicraft3DS.cia -DAPP_ENCRYPTED=false -rsf icons-banners/Minicraft3DS.rsf -target t -exefslogo -elf result/Minicraft3DS.elf -icon icons-banners/icon.icn -banner icons-banners/banner.bnr
|
||||
echo Creating 3DS/CCI...
|
||||
`dirname $0`/makerom -f cci -o result/Minicraft3DS.3ds -DAPP_ENCRYPTED=true -rsf icons-banners/Minicraft3DS.rsf -target t -exefslogo -elf result/Minicraft3DS.elf -icon icons-banners/icon.icn -banner icons-banners/banner.bnr
|
12
build.sh
Executable file
12
build.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
cd "`dirname $0`"
|
||||
echo Building 3DSX/ELF/SMDH...
|
||||
make
|
||||
echo Creating banner...
|
||||
bannertool makebanner -i icons-banners/banner.png -a icons-banners/audio.wav -o icons-banners/banner.bnr
|
||||
echo Creating icon...
|
||||
bannertool makesmdh -s "Minicraft3DS" -l "Original game by Notch" -p "Davideesk/Andre111/ElijahZAwesome/tognee" -i icons-banners/icon.png -o icons-banners/icon.icn
|
||||
echo Creating CIA...
|
||||
makerom -f cia -o result/Minicraft3DS.cia -DAPP_ENCRYPTED=false -rsf icons-banners/Minicraft3DS.rsf -target t -exefslogo -elf result/Minicraft3DS.elf -icon icons-banners/icon.icn -banner icons-banners/banner.bnr
|
||||
echo Creating 3DS/CCI...
|
||||
makerom -f cci -o result/Minicraft3DS.3ds -DAPP_ENCRYPTED=true -rsf icons-banners/Minicraft3DS.rsf -target t -exefslogo -elf result/Minicraft3DS.elf -icon icons-banners/icon.icn -banner icons-banners/banner.bnr
|
BIN
ctrtool.exe
BIN
ctrtool.exe
Binary file not shown.
BIN
data/icons.png
Executable file
BIN
data/icons.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
BIN
data/icons2.png
BIN
data/icons2.png
Binary file not shown.
Before Width: | Height: | Size: 37 KiB |
BIN
data/player.png
BIN
data/player.png
Binary file not shown.
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
@ -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/
|
|
@ -1,4 +0,0 @@
|
|||
theme: jekyll-theme-cayman
|
||||
title: Minicraft3DS
|
||||
description: A 2D Homebrew for 3DS
|
||||
show_downloads: true
|
BIN
makerom.exe
BIN
makerom.exe
Binary file not shown.
|
@ -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
|
|
@ -1,132 +1,139 @@
|
|||
#include "Crafting.h"
|
||||
|
||||
void cloneRecipeManager(RecipeManager *from, RecipeManager *to) {
|
||||
//free old manager recipes
|
||||
free(to->recipes);
|
||||
|
||||
//copy over recipes
|
||||
to->size = from->size;
|
||||
to->recipes = (Recipe*)malloc(sizeof(Recipe) * to->size);
|
||||
memcpy(to->recipes, from->recipes, sizeof(Recipe) * to->size);
|
||||
//free old manager recipes
|
||||
free(to->recipes);
|
||||
|
||||
//copy over recipes
|
||||
to->size = from->size;
|
||||
to->recipes = (Recipe*)malloc(sizeof(Recipe) * to->size);
|
||||
memcpy(to->recipes, from->recipes, sizeof(Recipe) * to->size);
|
||||
}
|
||||
|
||||
void checkCanCraftRecipes(RecipeManager * rm, Inventory * inv){
|
||||
int i, j;
|
||||
for(i = 0; i < rm->size; i++){
|
||||
rm->recipes[i].canCraft = true;
|
||||
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){
|
||||
rm->recipes[i].canCraft = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
int i, j;
|
||||
for(i = 0; i < rm->size; i++){
|
||||
rm->recipes[i].canCraft = true;
|
||||
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){
|
||||
rm->recipes[i].canCraft = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int compareCanCraft(const void * ra, const void * rb) {
|
||||
Recipe* r1 = (Recipe*)ra;
|
||||
Recipe* r2 = (Recipe*)rb;
|
||||
Recipe* r1 = (Recipe*)ra;
|
||||
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;
|
||||
return r1->order - r2->order; // Needed for stable sorting.
|
||||
}
|
||||
|
||||
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){
|
||||
Item* item = getItemFromInventory(c.costItem, inv);
|
||||
if(!item->onlyOne){
|
||||
item->countLevel -= c.costAmount;
|
||||
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, inv);
|
||||
} else {
|
||||
removeItemFromInventory(item->slotNum, inv);
|
||||
}
|
||||
Item* item = getItemFromInventory(c.costItem, inv);
|
||||
if(!item->onlyOne){
|
||||
item->countLevel -= c.costAmount;
|
||||
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, inv);
|
||||
} else {
|
||||
removeItemFromInventory(item->slotNum, inv);
|
||||
}
|
||||
}
|
||||
|
||||
bool craftItem(RecipeManager * rm, Recipe* r, Inventory* inv){
|
||||
if(r->canCraft){
|
||||
int i;
|
||||
for(i=0;i<r->numOfCosts;++i) deductCost(r->costs[i], inv);
|
||||
Item item = newItem(r->itemResult,r->itemAmountLevel);
|
||||
|
||||
if(!item.onlyOne && countItemInv(item.id,item.countLevel,inv) > 0){
|
||||
getItemFromInventory(item.id, inv)->countLevel += r->itemAmountLevel;
|
||||
} else{
|
||||
pushItemToInventoryFront(item, inv);
|
||||
}
|
||||
checkCanCraftRecipes(rm, inv);
|
||||
sortRecipes(rm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if(r->canCraft){
|
||||
int i;
|
||||
for(i=0;i<r->numOfCosts;++i) deductCost(r->costs[i], inv);
|
||||
Item item = newItem(r->itemResult,r->itemAmountLevel);
|
||||
|
||||
if(!item.onlyOne && countItemInv(item.id,item.countLevel,inv) > 0){
|
||||
getItemFromInventory(item.id, inv)->countLevel += r->itemAmountLevel;
|
||||
} else{
|
||||
pushItemToInventoryFront(item, inv);
|
||||
}
|
||||
checkCanCraftRecipes(rm, inv);
|
||||
sortRecipes(rm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Cost newCost(int i, int c){
|
||||
Cost nc;
|
||||
nc.costItem = i;
|
||||
nc.costAmount = c;
|
||||
return nc;
|
||||
Cost nc;
|
||||
nc.costItem = i;
|
||||
nc.costAmount = c;
|
||||
return nc;
|
||||
}
|
||||
|
||||
u8 curPlace = 0;
|
||||
Recipe defineRecipe(int item, int amountOrLevel, int numArgs, ...){
|
||||
Recipe r;
|
||||
r.itemResult = item;
|
||||
r.itemAmountLevel = amountOrLevel;
|
||||
r.numOfCosts = numArgs;
|
||||
int i;
|
||||
va_list al;
|
||||
numArgs <<= 1; // Did this to get rid of a warning.
|
||||
va_start(al,numArgs);
|
||||
for(i=0;i<r.numOfCosts;++i) r.costs[i] = newCost(va_arg(al,int), va_arg(al,int));
|
||||
va_end(al);
|
||||
r.order = curPlace;
|
||||
curPlace++;
|
||||
return r;
|
||||
Recipe r;
|
||||
r.itemResult = item;
|
||||
r.itemAmountLevel = amountOrLevel;
|
||||
r.numOfCosts = numArgs;
|
||||
int i;
|
||||
va_list al;
|
||||
numArgs <<= 1; // Did this to get rid of a warning.
|
||||
va_start(al,numArgs);
|
||||
for(i=0;i<r.numOfCosts;++i) r.costs[i] = newCost(va_arg(al,int), va_arg(al,int));
|
||||
va_end(al);
|
||||
r.order = curPlace;
|
||||
curPlace++;
|
||||
return r;
|
||||
}
|
||||
|
||||
void initRecipes(){
|
||||
|
||||
curPlace = 0;
|
||||
workbenchRecipes.size = 22;
|
||||
workbenchRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (workbenchRecipes.size));
|
||||
workbenchRecipes.recipes[0] = defineRecipe(ITEM_WORKBENCH,1,1,ITEM_WOOD,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[3] = defineRecipe(ITEM_CHEST,1,1,ITEM_WOOD,20);
|
||||
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);
|
||||
curPlace = 0;
|
||||
|
||||
inHeadRecipes.size = 2;
|
||||
inHeadRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (inHeadRecipes.size));
|
||||
inHeadRecipes.recipes[0] = defineRecipe(ITEM_WORKBENCH,1,1,ITEM_WOOD,10);
|
||||
inHeadRecipes.recipes[1] = defineRecipe(ITEM_TORCH,1,2,ITEM_WOOD,1,ITEM_COAL,1);
|
||||
|
||||
workbenchRecipes.size = 24;
|
||||
workbenchRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (workbenchRecipes.size));
|
||||
workbenchRecipes.recipes[0] = defineRecipe(ITEM_WORKBENCH,1,1,ITEM_WOOD,10);
|
||||
workbenchRecipes.recipes[1] = defineRecipe(ITEM_FURNACE,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[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[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[8] = defineRecipe(TOOL_AXE,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[11] = defineRecipe(TOOL_SHOVEL,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[9] = defineRecipe(TOOL_HOE,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[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[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[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[18] = defineRecipe(TOOL_SHOVEL,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[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[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[20] = defineRecipe(ITEM_WALL_WOOD,1,1,ITEM_WOOD,4);
|
||||
workbenchRecipes.recipes[21] = defineRecipe(ITEM_WALL_STONE,1,1,ITEM_STONE,4);
|
||||
workbenchRecipes.recipes[22] = defineRecipe(ITEM_FISHING_ROD,1,2,ITEM_WOOD,10,ITEM_STRING,3);
|
||||
workbenchRecipes.recipes[23] = defineRecipe(ITEM_TORCH,1,2,ITEM_WOOD,1,ITEM_COAL,1);
|
||||
|
||||
anvilRecipes.size = 18;
|
||||
anvilRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (anvilRecipes.size));
|
||||
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[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[4] = defineRecipe(TOOL_SHOVEL,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
|
||||
anvilRecipes.size = 19;
|
||||
anvilRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (anvilRecipes.size));
|
||||
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[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[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[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[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[10] = defineRecipe(TOOL_SHOVEL,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[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[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[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);
|
||||
|
@ -134,36 +141,39 @@ void initRecipes(){
|
|||
anvilRecipes.recipes[15] = defineRecipe(ITEM_WALL_GOLD,1,1,ITEM_GOLDINGOT,2);
|
||||
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);
|
||||
|
||||
furnaceRecipes.size = 3;
|
||||
furnaceRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (furnaceRecipes.size));
|
||||
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[2] = defineRecipe(ITEM_GLASS,1,2,ITEM_SAND,4,ITEM_COAL,1);
|
||||
|
||||
ovenRecipes.size = 3;
|
||||
ovenRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (ovenRecipes.size));
|
||||
ovenRecipes.recipes[0] = defineRecipe(ITEM_BREAD,1,1,ITEM_WHEAT,4);
|
||||
anvilRecipes.recipes[18] = defineRecipe(ITEM_SHEARS,1,1,ITEM_IRONINGOT,2);
|
||||
|
||||
furnaceRecipes.size = 3;
|
||||
furnaceRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (furnaceRecipes.size));
|
||||
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[2] = defineRecipe(ITEM_GLASS,1,2,ITEM_SAND,4,ITEM_COAL,1);
|
||||
|
||||
ovenRecipes.size = 4;
|
||||
ovenRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (ovenRecipes.size));
|
||||
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[2] = defineRecipe(ITEM_BEEF_COOKED,1,2,ITEM_BEEF_RAW,1,ITEM_COAL,1);
|
||||
|
||||
loomRecipes.size = 1;
|
||||
loomRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (loomRecipes.size));
|
||||
loomRecipes.recipes[0] = defineRecipe(ITEM_STRING,1,1,ITEM_WOOL,1);
|
||||
|
||||
ovenRecipes.recipes[3] = defineRecipe(ITEM_FISH_COOKED,1,2,ITEM_FISH_RAW,1,ITEM_COAL,1);
|
||||
|
||||
loomRecipes.size = 2;
|
||||
loomRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (loomRecipes.size));
|
||||
loomRecipes.recipes[0] = defineRecipe(ITEM_STRING,1,1,ITEM_WOOL,1);
|
||||
loomRecipes.recipes[1] = defineRecipe(ITEM_BED,1,2,ITEM_WOOD,5,ITEM_WOOL,3);
|
||||
|
||||
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[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[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[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[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[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[7] = defineRecipe(ITEM_GOLD_APPLE,1,2,ITEM_APPLE,1,ITEM_GOLDINGOT,15);
|
||||
|
||||
|
||||
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[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);
|
||||
|
@ -172,10 +182,11 @@ void initRecipes(){
|
|||
|
||||
/* Free up allocated memory */
|
||||
void freeRecipes(){
|
||||
free(workbenchRecipes.recipes);
|
||||
free(ovenRecipes.recipes);
|
||||
free(furnaceRecipes.recipes);
|
||||
free(anvilRecipes.recipes);
|
||||
free(inHeadRecipes.recipes);
|
||||
free(workbenchRecipes.recipes);
|
||||
free(ovenRecipes.recipes);
|
||||
free(furnaceRecipes.recipes);
|
||||
free(anvilRecipes.recipes);
|
||||
free(loomRecipes.recipes);
|
||||
free(enchanterRecipes.recipes);
|
||||
free(potionMakerRecipes.recipes);
|
||||
|
|
|
@ -3,25 +3,25 @@
|
|||
#include "Item.h"
|
||||
|
||||
typedef struct _recipecost {
|
||||
int costItem;
|
||||
int costAmount;
|
||||
int costItem;
|
||||
int costAmount;
|
||||
} Cost;
|
||||
|
||||
typedef struct _recipe {
|
||||
bool canCraft;
|
||||
int itemResult;
|
||||
int itemAmountLevel;
|
||||
s8 numOfCosts;
|
||||
Cost costs[6]; // Up to 6 items for costs
|
||||
u8 order; // Used for stable sorting.
|
||||
bool canCraft;
|
||||
int itemResult;
|
||||
int itemAmountLevel;
|
||||
s8 numOfCosts;
|
||||
Cost costs[6]; // Up to 6 items for costs
|
||||
u8 order; // Used for stable sorting.
|
||||
} Recipe;
|
||||
|
||||
typedef struct _recipeManager {
|
||||
int size;
|
||||
Recipe * recipes;
|
||||
int size;
|
||||
Recipe * recipes;
|
||||
} RecipeManager;
|
||||
|
||||
|
||||
RecipeManager inHeadRecipes;
|
||||
RecipeManager workbenchRecipes;
|
||||
RecipeManager furnaceRecipes;
|
||||
RecipeManager ovenRecipes;
|
||||
|
|
496
source/Entity.c
496
source/Entity.c
|
@ -3,361 +3,361 @@
|
|||
#include "Synchronizer.h"
|
||||
|
||||
Entity newItemEntity(Item item, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_ITEM;
|
||||
e.level = level;
|
||||
e.entityItem.age = 0;
|
||||
e.entityItem.item = item;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
|
||||
Entity e;
|
||||
e.type = ENTITY_ITEM;
|
||||
e.level = level;
|
||||
e.entityItem.age = 0;
|
||||
e.entityItem.item = item;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
|
||||
e.entityItem.xx = x;
|
||||
e.entityItem.yy = y;
|
||||
e.entityItem.zz = 2;
|
||||
e.entityItem.xa = gaussrand(false) * 0.1;
|
||||
e.entityItem.ya = gaussrand(false) * 0.1;
|
||||
e.entityItem.za = ((float)rand() / RAND_MAX) * 0.45 + 1;
|
||||
|
||||
return e;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void assignInventory(Entity* e){
|
||||
if(eManager.nextInv > 300) return;
|
||||
e->entityFurniture.inv = &eManager.invs[eManager.nextInv];
|
||||
eManager.nextInv++;
|
||||
if(eManager.nextInv > 300) return;
|
||||
e->entityFurniture.inv = &eManager.invs[eManager.nextInv];
|
||||
eManager.nextInv++;
|
||||
}
|
||||
|
||||
Entity newFurnitureEntity(int itemID,Inventory * invPtr, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_FURNITURE;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.entityFurniture.itemID = itemID;
|
||||
e.canPass = false;
|
||||
if(itemID == ITEM_LANTERN) e.entityFurniture.r = 8;
|
||||
else if(itemID == ITEM_CHEST){
|
||||
if(invPtr == NULL)assignInventory(&e);
|
||||
else e.entityFurniture.inv = invPtr;
|
||||
}
|
||||
return e;
|
||||
Entity e;
|
||||
e.type = ENTITY_FURNITURE;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.entityFurniture.itemID = itemID;
|
||||
e.canPass = false;
|
||||
if(itemID == ITEM_LANTERN) e.entityFurniture.r = 8;
|
||||
else if(itemID == ITEM_CHEST){
|
||||
if(invPtr == NULL)assignInventory(&e);
|
||||
else e.entityFurniture.inv = invPtr;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newPassiveEntity(int type, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_PASSIVE;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.passive.mtype = type;
|
||||
e.passive.health = 20;
|
||||
e.passive.dir = 0;
|
||||
e.type = ENTITY_PASSIVE;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.passive.mtype = type;
|
||||
e.passive.health = 20;
|
||||
e.passive.dir = 0;
|
||||
e.passive.xa = 0;
|
||||
e.passive.ya = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
return e;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newZombieEntity(int lvl, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_ZOMBIE;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.hostile.lvl = lvl;
|
||||
Entity e;
|
||||
e.type = ENTITY_ZOMBIE;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.hostile.lvl = lvl;
|
||||
e.hostile.xa = 0;
|
||||
e.hostile.ya = 0;
|
||||
e.hostile.health = lvl * lvl * 10;
|
||||
e.hostile.dir = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.hostile.color = 0xFF8282CC; break;
|
||||
case 3: e.hostile.color = 0xFFEFEFEF; break;
|
||||
case 4: e.hostile.color = 0xFFAA6262; break;
|
||||
default: e.hostile.color = 0xFF95DB95; break;
|
||||
}
|
||||
return e;
|
||||
e.hostile.health = lvl * lvl * 10;
|
||||
e.hostile.dir = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.hostile.color = 0xFF8282CC; break;
|
||||
case 3: e.hostile.color = 0xFFEFEFEF; break;
|
||||
case 4: e.hostile.color = 0xFFAA6262; break;
|
||||
default: e.hostile.color = 0xFF95DB95; break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newSkeletonEntity(int lvl, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_SKELETON;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.hostile.lvl = lvl;
|
||||
Entity e;
|
||||
e.type = ENTITY_SKELETON;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.hostile.lvl = lvl;
|
||||
e.hostile.xa = 0;
|
||||
e.hostile.ya = 0;
|
||||
e.hostile.health = lvl * lvl * 10;
|
||||
e.hostile.dir = 0;
|
||||
e.hostile.health = lvl * lvl * 10;
|
||||
e.hostile.dir = 0;
|
||||
e.hostile.randAttackTime = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.hostile.color = 0xFFC4C4C4; break;
|
||||
case 3: e.hostile.color = 0xFFA0A0A0; break;
|
||||
case 4: e.hostile.color = 0xFF7A7A7A; break;
|
||||
default: e.hostile.color = 0xFFFFFFFF; break;
|
||||
}
|
||||
return e;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.hostile.color = 0xFFC4C4C4; break;
|
||||
case 3: e.hostile.color = 0xFFA0A0A0; break;
|
||||
case 4: e.hostile.color = 0xFF7A7A7A; break;
|
||||
default: e.hostile.color = 0xFFFFFFFF; break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newKnightEntity(int lvl, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_KNIGHT;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.hostile.lvl = lvl;
|
||||
Entity e;
|
||||
e.type = ENTITY_KNIGHT;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.hostile.lvl = lvl;
|
||||
e.hostile.xa = 0;
|
||||
e.hostile.ya = 0;
|
||||
e.hostile.health = lvl * lvl * 20;
|
||||
e.hostile.dir = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.hostile.color = 0xFF0000C6; break;
|
||||
case 3: e.hostile.color = 0xFF00A3C6; break;
|
||||
case 4: e.hostile.color = 0xFF707070; break;
|
||||
default: e.hostile.color = 0xFFFFFFFF; break;
|
||||
}
|
||||
return e;
|
||||
e.hostile.health = lvl * lvl * 20;
|
||||
e.hostile.dir = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.hostile.color = 0xFF0000C6; break;
|
||||
case 3: e.hostile.color = 0xFF00A3C6; break;
|
||||
case 4: e.hostile.color = 0xFF707070; break;
|
||||
default: e.hostile.color = 0xFFFFFFFF; break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newSlimeEntity(int lvl, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_SLIME;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.slime.lvl = lvl;
|
||||
e.slime.xa = 0;
|
||||
e.slime.ya = 0;
|
||||
e.slime.dir = 0;
|
||||
e.slime.health = lvl * lvl * 5;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.slime.color = 0xFF8282CC; break;
|
||||
case 3: e.slime.color = 0xFFEFEFEF; break;
|
||||
case 4: e.slime.color = 0xFFAA6262; break;
|
||||
default: e.slime.color = 0xFF95DB95; break;
|
||||
}
|
||||
return e;
|
||||
Entity e;
|
||||
e.type = ENTITY_SLIME;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.slime.lvl = lvl;
|
||||
e.slime.xa = 0;
|
||||
e.slime.ya = 0;
|
||||
e.slime.dir = 0;
|
||||
e.slime.health = lvl * lvl * 5;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
switch(lvl){
|
||||
case 2: e.slime.color = 0xFF8282CC; break;
|
||||
case 3: e.slime.color = 0xFFEFEFEF; break;
|
||||
case 4: e.slime.color = 0xFFAA6262; break;
|
||||
default: e.slime.color = 0xFF95DB95; break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newAirWizardEntity(int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_AIRWIZARD;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.wizard.dir = 0;
|
||||
e.wizard.health = 2000;
|
||||
Entity e;
|
||||
e.type = ENTITY_AIRWIZARD;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.wizard.dir = 0;
|
||||
e.wizard.health = 2000;
|
||||
e.wizard.attackDelay = 0;
|
||||
e.wizard.attackTime = 0;
|
||||
e.wizard.attackType = 0;
|
||||
e.wizard.xa = 0;
|
||||
e.wizard.ya = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
e.wizard.xa = 0;
|
||||
e.wizard.ya = 0;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newSparkEntity(Entity* parent, float xa, float ya){
|
||||
Entity e;
|
||||
e.type = ENTITY_SPARK;
|
||||
Entity e;
|
||||
e.type = ENTITY_SPARK;
|
||||
e.level = parent->level;
|
||||
e.spark.age = 0;
|
||||
e.spark.parent = parent;
|
||||
e.spark.xa = xa;
|
||||
e.spark.ya = ya;
|
||||
e.spark.xx = parent->x;
|
||||
e.spark.yy = parent->y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
e.spark.age = 0;
|
||||
e.spark.parent = parent;
|
||||
e.spark.xa = xa;
|
||||
e.spark.ya = ya;
|
||||
e.spark.xx = parent->x;
|
||||
e.spark.yy = parent->y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newDragonEntity(int x, int y, int level) {
|
||||
Entity e;
|
||||
e.type = ENTITY_DRAGON;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.dragon.dir = 0;
|
||||
e.dragon.health = 2000;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.dragon.dir = 0;
|
||||
e.dragon.health = 2000;
|
||||
e.dragon.attackDelay = 0;
|
||||
e.dragon.attackTime = 0;
|
||||
e.dragon.attackType = 0;
|
||||
e.dragon.animTimer = 0;
|
||||
e.dragon.xa = 0;
|
||||
e.dragon.ya = 0;
|
||||
e.xr = 8;
|
||||
e.yr = 8;
|
||||
e.canPass = false;
|
||||
e.dragon.xa = 0;
|
||||
e.dragon.ya = 0;
|
||||
e.xr = 8;
|
||||
e.yr = 8;
|
||||
e.canPass = false;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newDragonFireEntity(Entity* parent, u8 type, int x, int y, float xa, float ya) {
|
||||
Entity e;
|
||||
e.type = ENTITY_DRAGONPROJECTILE;
|
||||
e.type = ENTITY_DRAGONPROJECTILE;
|
||||
e.level = parent->level;
|
||||
e.dragonFire.age = 0;
|
||||
e.dragonFire.age = 0;
|
||||
e.dragonFire.type = type;
|
||||
e.dragonFire.parent = parent;
|
||||
e.dragonFire.xa = xa;
|
||||
e.dragonFire.ya = ya;
|
||||
e.dragonFire.xx = x;
|
||||
e.dragonFire.yy = y;
|
||||
e.dragonFire.parent = parent;
|
||||
e.dragonFire.xa = xa;
|
||||
e.dragonFire.ya = ya;
|
||||
e.dragonFire.xx = x;
|
||||
e.dragonFire.yy = y;
|
||||
e.x = (int) x;
|
||||
e.y = (int) y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newMagicPillarEntity(int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_MAGIC_PILLAR;
|
||||
e.type = ENTITY_MAGIC_PILLAR;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
return e;
|
||||
e.xr = 3;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newTextParticleEntity(char * str, u32 color, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_TEXTPARTICLE;
|
||||
e.level = level;
|
||||
e.textParticle.color = color;
|
||||
e.textParticle.age = 0;
|
||||
e.textParticle.text = (char*)calloc(strlen(str),sizeof(char));
|
||||
strncpy(e.textParticle.text,str,strlen(str));
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.canPass = true;
|
||||
Entity e;
|
||||
e.type = ENTITY_TEXTPARTICLE;
|
||||
e.level = level;
|
||||
e.textParticle.color = color;
|
||||
e.textParticle.age = 0;
|
||||
e.textParticle.text = (char*)calloc(strlen(str),sizeof(char));
|
||||
strncpy(e.textParticle.text,str,strlen(str));
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.canPass = true;
|
||||
e.textParticle.xx = x;
|
||||
e.textParticle.yy = y;
|
||||
e.textParticle.zz = 2;
|
||||
e.textParticle.xa = gaussrand(false) * 0.3;
|
||||
e.textParticle.ya = gaussrand(false) * 0.2;
|
||||
e.textParticle.za = ((float)rand() / RAND_MAX) * 0.7 + 2;
|
||||
|
||||
return e;
|
||||
|
||||
return e;
|
||||
}
|
||||
Entity newSmashParticleEntity(int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_SMASHPARTICLE;
|
||||
e.level = level;
|
||||
e.smashParticle.age = 0;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.canPass = true;
|
||||
Entity e;
|
||||
e.type = ENTITY_SMASHPARTICLE;
|
||||
e.level = level;
|
||||
e.smashParticle.age = 0;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.canPass = true;
|
||||
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 e;
|
||||
e.type = ENTITY_ARROW;
|
||||
e.type = ENTITY_ARROW;
|
||||
e.level = level;
|
||||
e.arrow.age = 0;
|
||||
e.arrow.parent = parent;
|
||||
e.arrow.age = 0;
|
||||
e.arrow.parent = parent;
|
||||
e.arrow.itemID = itemID;
|
||||
e.arrow.xa = xa;
|
||||
e.arrow.ya = ya;
|
||||
e.x = parent->x;
|
||||
e.y = parent->y;
|
||||
e.xr = 2;
|
||||
e.yr = 2;
|
||||
e.canPass = false;
|
||||
e.arrow.xa = xa;
|
||||
e.arrow.ya = ya;
|
||||
e.x = parent->x;
|
||||
e.y = parent->y;
|
||||
e.xr = 2;
|
||||
e.yr = 2;
|
||||
e.canPass = false;
|
||||
e.canSwim = true;
|
||||
return e;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newGlowwormEntity(int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_GLOWWORM;
|
||||
e.level = level;
|
||||
Entity e;
|
||||
e.type = ENTITY_GLOWWORM;
|
||||
e.level = level;
|
||||
e.glowworm.xa = 0;
|
||||
e.glowworm.ya = 0;
|
||||
e.glowworm.randWalkTime = 0;
|
||||
e.glowworm.waitTime = 0;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
e.y = y;
|
||||
e.canPass = true;
|
||||
return e;
|
||||
}
|
||||
|
||||
Entity newNPCEntity(int type, int x, int y, int level){
|
||||
Entity e;
|
||||
e.type = ENTITY_NPC;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.npc.type = type;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
return e;
|
||||
e.type = ENTITY_NPC;
|
||||
e.level = level;
|
||||
e.x = x;
|
||||
e.y = y;
|
||||
e.hurtTime = 0;
|
||||
e.xKnockback = 0;
|
||||
e.yKnockback = 0;
|
||||
e.npc.type = type;
|
||||
e.xr = 4;
|
||||
e.yr = 3;
|
||||
e.canPass = false;
|
||||
return e;
|
||||
}
|
||||
|
||||
void addEntityToList(Entity e, EntityManager* em){
|
||||
e.slotNum = em->lastSlot[e.level];
|
||||
em->entities[e.level][em->lastSlot[e.level]] = e;
|
||||
++em->lastSlot[e.level];
|
||||
e.slotNum = em->lastSlot[e.level];
|
||||
em->entities[e.level][em->lastSlot[e.level]] = e;
|
||||
++em->lastSlot[e.level];
|
||||
}
|
||||
|
||||
void removeEntityFromList(Entity * e,int level,EntityManager* em){
|
||||
int i;
|
||||
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){
|
||||
em->entities[level][i] = em->entities[level][i + 1]; // Move the items down.
|
||||
em->entities[level][i].slotNum = i;
|
||||
}
|
||||
em->lastSlot[level]--;
|
||||
em->entities[level][em->lastSlot[level]] = nullEntity; // Make the last slot null.
|
||||
int i;
|
||||
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){
|
||||
em->entities[level][i] = em->entities[level][i + 1]; // Move the items down.
|
||||
em->entities[level][i].slotNum = i;
|
||||
}
|
||||
em->lastSlot[level]--;
|
||||
em->entities[level][em->lastSlot[level]] = nullEntity; // Make the last slot null.
|
||||
}
|
||||
|
|
227
source/Entity.h
227
source/Entity.h
|
@ -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 {
|
||||
s8 ax;
|
||||
s8 ay;
|
||||
u8 dir;
|
||||
s8 health;
|
||||
s8 stamina;
|
||||
s8 staminaRecharge;
|
||||
s8 staminaRechargeDelay;
|
||||
s8 attackTimer;
|
||||
u8 spawnTrigger;
|
||||
bool isDead;
|
||||
bool hasWon;
|
||||
bool hasWonSaved;
|
||||
s8 endTimer;
|
||||
s16 walkDist;
|
||||
bool isCarrying;
|
||||
bool isSwimming;
|
||||
int swimTimer;
|
||||
s8 ax;
|
||||
s8 ay;
|
||||
u8 dir;
|
||||
s8 health;
|
||||
s8 stamina;
|
||||
s8 staminaRecharge;
|
||||
s8 staminaRechargeDelay;
|
||||
s8 attackTimer;
|
||||
u8 spawnTrigger;
|
||||
bool isDead;
|
||||
bool hasWon;
|
||||
bool hasWonSaved;
|
||||
s8 endTimer;
|
||||
s16 walkDist;
|
||||
bool isCarrying;
|
||||
bool isSwimming;
|
||||
int swimTimer;
|
||||
int regenTimer;
|
||||
int strengthTimer;
|
||||
int swimBreathTimer;
|
||||
int speedTimer;
|
||||
int score;
|
||||
PlayerData *data;
|
||||
PlayerData *data;
|
||||
} Player;
|
||||
|
||||
|
||||
typedef struct {
|
||||
float xa;
|
||||
float ya;
|
||||
float za;
|
||||
float xx;
|
||||
float yy;
|
||||
float zz;
|
||||
s16 age;
|
||||
Item item;
|
||||
float xa;
|
||||
float ya;
|
||||
float za;
|
||||
float xx;
|
||||
float yy;
|
||||
float zz;
|
||||
s16 age;
|
||||
Item item;
|
||||
} EntityItem;
|
||||
|
||||
typedef struct {
|
||||
s16 itemID;
|
||||
bool active;
|
||||
s8 r; // light radius for lantern.
|
||||
Inventory* inv; // Points to chest inventory.
|
||||
s16 itemID;
|
||||
bool active;
|
||||
s8 r; // light radius for lantern.
|
||||
Inventory* inv; // Points to chest inventory.
|
||||
} EntityFurniture;
|
||||
|
||||
typedef struct {
|
||||
u8 mtype;
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 dir;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
s8 dir;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
} PassiveMob;
|
||||
|
||||
typedef struct {
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 dir;
|
||||
s8 lvl;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 dir;
|
||||
s8 lvl;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
s8 randAttackTime;
|
||||
u32 color;
|
||||
u32 color;
|
||||
} HostileMob;
|
||||
|
||||
typedef struct {
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 lvl;
|
||||
s8 dir;
|
||||
s8 jumpTime;
|
||||
u32 color;
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 lvl;
|
||||
s8 dir;
|
||||
s8 jumpTime;
|
||||
u32 color;
|
||||
} Slime;
|
||||
|
||||
typedef struct {
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
s8 dir;
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
s8 dir;
|
||||
int attackDelay;
|
||||
int attackTime;
|
||||
int attackType;
|
||||
|
@ -120,12 +120,12 @@ typedef struct {
|
|||
} AirWizard;
|
||||
|
||||
typedef struct {
|
||||
Entity* parent;
|
||||
s16 age;
|
||||
float xa;
|
||||
float ya;
|
||||
float xx;
|
||||
float yy;
|
||||
Entity* parent;
|
||||
s16 age;
|
||||
float xa;
|
||||
float ya;
|
||||
float xx;
|
||||
float yy;
|
||||
} Spark;
|
||||
|
||||
typedef struct {
|
||||
|
@ -137,12 +137,12 @@ typedef struct {
|
|||
} Arrow;
|
||||
|
||||
typedef struct {
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
s8 dir;
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s16 health;
|
||||
s8 randWalkTime;
|
||||
s8 walkDist;
|
||||
s8 dir;
|
||||
int attackDelay;
|
||||
int attackTime;
|
||||
int attackType;
|
||||
|
@ -150,19 +150,19 @@ typedef struct {
|
|||
} Dragon;
|
||||
|
||||
typedef struct {
|
||||
Entity* parent;
|
||||
Entity* parent;
|
||||
u8 type;
|
||||
s16 age;
|
||||
float xa;
|
||||
float ya;
|
||||
float xx;
|
||||
float yy;
|
||||
s16 age;
|
||||
float xa;
|
||||
float ya;
|
||||
float xx;
|
||||
float yy;
|
||||
} DragonFire;
|
||||
|
||||
typedef struct {
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s8 randWalkTime;
|
||||
s8 xa;
|
||||
s8 ya;
|
||||
s8 randWalkTime;
|
||||
s8 waitTime;
|
||||
} Glowworm;
|
||||
|
||||
|
@ -171,56 +171,56 @@ typedef struct {
|
|||
} NPC;
|
||||
|
||||
typedef struct {
|
||||
float xa;
|
||||
float ya;
|
||||
float za;
|
||||
float xx;
|
||||
float yy;
|
||||
float zz;
|
||||
s16 age;
|
||||
char* text;
|
||||
int color;
|
||||
float xa;
|
||||
float ya;
|
||||
float za;
|
||||
float xx;
|
||||
float yy;
|
||||
float zz;
|
||||
s16 age;
|
||||
char* text;
|
||||
int color;
|
||||
} TextParticleEntity;
|
||||
|
||||
typedef struct {
|
||||
s16 age;
|
||||
s16 age;
|
||||
} SmashParticleEntity;
|
||||
|
||||
struct Entity {
|
||||
s16 x;
|
||||
s16 y;
|
||||
s8 xKnockback,yKnockback;
|
||||
u8 xr,yr;
|
||||
u8 type;
|
||||
u8 level;
|
||||
s8 hurtTime;
|
||||
s16 slotNum; // Read-only. Do not mess with this.
|
||||
bool canPass;
|
||||
bool canSwim;
|
||||
union {
|
||||
Player p;
|
||||
EntityItem entityItem;
|
||||
EntityFurniture entityFurniture;
|
||||
s16 x;
|
||||
s16 y;
|
||||
s8 xKnockback,yKnockback;
|
||||
u8 xr,yr;
|
||||
u8 type;
|
||||
u8 level;
|
||||
s8 hurtTime;
|
||||
s16 slotNum; // Read-only. Do not mess with this.
|
||||
bool canPass;
|
||||
bool canSwim;
|
||||
union {
|
||||
Player p;
|
||||
EntityItem entityItem;
|
||||
EntityFurniture entityFurniture;
|
||||
PassiveMob passive;
|
||||
HostileMob hostile;
|
||||
Slime slime;
|
||||
AirWizard wizard;
|
||||
Spark spark;
|
||||
HostileMob hostile;
|
||||
Slime slime;
|
||||
AirWizard wizard;
|
||||
Spark spark;
|
||||
Arrow arrow;
|
||||
Glowworm glowworm;
|
||||
Dragon dragon;
|
||||
DragonFire dragonFire;
|
||||
NPC npc;
|
||||
TextParticleEntity textParticle;
|
||||
SmashParticleEntity smashParticle;
|
||||
};
|
||||
NPC npc;
|
||||
TextParticleEntity textParticle;
|
||||
SmashParticleEntity smashParticle;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
Entity entities[6][1000];
|
||||
s16 lastSlot[6];
|
||||
Inventory invs[300];
|
||||
s16 nextInv;
|
||||
Entity entities[6][1000];
|
||||
s16 lastSlot[6];
|
||||
Inventory invs[300];
|
||||
s16 nextInv;
|
||||
} EntityManager;
|
||||
|
||||
EntityManager eManager;
|
||||
|
@ -246,6 +246,3 @@ Entity newGlowwormEntity(int x, int y, int level);
|
|||
Entity newNPCEntity(int type, int x, int y, int level);
|
||||
void addEntityToList(Entity e, EntityManager* em);
|
||||
void removeEntityFromList(Entity * e,int level,EntityManager* em);
|
||||
|
||||
|
||||
|
||||
|
|
2496
source/Globals.c
2496
source/Globals.c
File diff suppressed because it is too large
Load diff
|
@ -7,7 +7,7 @@
|
|||
#include "MapGen.h"
|
||||
#include "Quests.h"
|
||||
|
||||
#include "icons2_png.h"
|
||||
#include "icons_png.h"
|
||||
#include "player_png.h"
|
||||
#include "Font_png.h"
|
||||
#include "bottombg_png.h"
|
||||
|
@ -89,6 +89,8 @@
|
|||
//WARNING: Having this set to different values in different clients will break multiplayer!
|
||||
#define TESTGODMODE false
|
||||
|
||||
bool paused;
|
||||
|
||||
u32 localUID;
|
||||
|
||||
int loadedtp;
|
||||
|
@ -140,15 +142,15 @@ bool quitGame;
|
|||
s8 currentSelection;
|
||||
|
||||
typedef struct _worldData {
|
||||
u8 map[6][128*128];
|
||||
u8 data[6][128*128];
|
||||
|
||||
u16 daytime;
|
||||
int day;
|
||||
u8 season;
|
||||
bool rain;
|
||||
|
||||
u8 compassData[6][3];
|
||||
u8 map[6][128*128];
|
||||
u8 data[6][128*128];
|
||||
|
||||
u16 daytime;
|
||||
int day;
|
||||
u8 season;
|
||||
bool rain;
|
||||
|
||||
u8 compassData[6][3];
|
||||
} WorldData;
|
||||
|
||||
WorldData worldData;
|
||||
|
@ -199,4 +201,4 @@ u32 getMinimapColor(PlayerData *pd, int level, int x, int y);
|
|||
void initMinimapLevel(PlayerData *pd, int level);
|
||||
void updateLevel1Map();
|
||||
|
||||
void reloadColors();
|
||||
void reloadColors();
|
||||
|
|
627
source/Ingame.c
627
source/Ingame.c
|
@ -17,53 +17,53 @@ bool stallAreYouSure;
|
|||
|
||||
//generates stairs up and creates compass data
|
||||
void generatePass2() {
|
||||
int level, x, y;
|
||||
|
||||
for (level = 0; level < 5; ++level) {
|
||||
for (x = 0; x < 128; ++x) {
|
||||
for (y = 0; y < 128; ++y) {
|
||||
int level, x, y;
|
||||
|
||||
//generate stairs up matching stairs down
|
||||
switch (worldData.map[level][x + y * 128]) {
|
||||
case TILE_STAIRS_DOWN:
|
||||
if(level < 4) {
|
||||
worldData.map[level + 1][x + y * 128] = TILE_STAIRS_UP;
|
||||
if (level == 0) {
|
||||
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 - 1) + y * 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;
|
||||
} else {
|
||||
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 - 1) + y * 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//calculate compass data
|
||||
//choose one stair down and store for magic compass
|
||||
switch (worldData.map[level][x + y * 128]) {
|
||||
case TILE_STAIRS_DOWN:
|
||||
case TILE_DUNGEON_ENTRANCE:
|
||||
worldData.compassData[level][2] = worldData.compassData[level][2] + 1;
|
||||
if((worldData.compassData[level][2]==1) || (rand()%(worldData.compassData[level][2])==0)) {
|
||||
worldData.compassData[level][0] = x;
|
||||
worldData.compassData[level][1] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (level = 0; level < 5; ++level) {
|
||||
for (x = 0; x < 128; ++x) {
|
||||
for (y = 0; y < 128; ++y) {
|
||||
|
||||
//generate stairs up matching stairs down
|
||||
switch (worldData.map[level][x + y * 128]) {
|
||||
case TILE_STAIRS_DOWN:
|
||||
if(level < 4) {
|
||||
worldData.map[level + 1][x + y * 128] = TILE_STAIRS_UP;
|
||||
if (level == 0) {
|
||||
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 - 1) + y * 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;
|
||||
} else {
|
||||
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 - 1) + y * 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//calculate compass data
|
||||
//choose one stair down and store for magic compass
|
||||
switch (worldData.map[level][x + y * 128]) {
|
||||
case TILE_STAIRS_DOWN:
|
||||
case TILE_DUNGEON_ENTRANCE:
|
||||
worldData.compassData[level][2] = worldData.compassData[level][2] + 1;
|
||||
if((worldData.compassData[level][2]==1) || (rand()%(worldData.compassData[level][2])==0)) {
|
||||
worldData.compassData[level][0] = x;
|
||||
worldData.compassData[level][1] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initNewMap() {
|
||||
|
@ -72,7 +72,7 @@ void initNewMap() {
|
|||
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, 3, 4, worldData.map[4], worldData.data[4]);
|
||||
generatePass2();
|
||||
generatePass2();
|
||||
}
|
||||
|
||||
void initMiniMap(PlayerData *pd) {
|
||||
|
@ -83,298 +83,297 @@ void initMiniMap(PlayerData *pd) {
|
|||
}
|
||||
|
||||
void startGame(bool load, char *filename) {
|
||||
// Reset entity manager.
|
||||
// Reset entity manager.
|
||||
memset(&eManager, 0, sizeof(eManager));
|
||||
|
||||
// Reset players
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
initPlayer(players+i);
|
||||
}
|
||||
|
||||
// Reset players
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
initPlayer(players+i);
|
||||
}
|
||||
if (playerCount > 1) {
|
||||
shouldRenderDebug = false;
|
||||
}
|
||||
|
||||
if (!load) {
|
||||
initNewMap();
|
||||
airWizardHealthDisplay = 2000;
|
||||
int i;
|
||||
for (i = 0; i < 5; ++i) {
|
||||
trySpawn(500, i);
|
||||
}
|
||||
addEntityToList(newAirWizardEntity(630, 820, 0), &eManager);
|
||||
worldData.daytime = 6000;
|
||||
worldData.day = 0;
|
||||
worldData.season = 0;
|
||||
worldData.rain = false;
|
||||
} else {
|
||||
if(!loadWorld(filename, &eManager, &worldData, players, playerCount)) {
|
||||
//TODO: What do?
|
||||
networkDisconnect();
|
||||
|
||||
sf2d_set_clear_color(0xFF);
|
||||
currentSelection = 0;
|
||||
currentMenu = MENU_TITLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn players
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].isSpawned) {
|
||||
playerSpawn(players+i);
|
||||
}
|
||||
}
|
||||
|
||||
// Init player maps
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
initMiniMap(players+i);
|
||||
}
|
||||
|
||||
stallCounter = 0;
|
||||
|
||||
if (!load) {
|
||||
initNewMap();
|
||||
airWizardHealthDisplay = 2000;
|
||||
int i;
|
||||
for (i = 0; i < 5; ++i) {
|
||||
trySpawn(500, i);
|
||||
}
|
||||
addEntityToList(newAirWizardEntity(630, 820, 0), &eManager);
|
||||
worldData.daytime = 6000;
|
||||
worldData.day = 0;
|
||||
worldData.season = 0;
|
||||
worldData.rain = false;
|
||||
} else {
|
||||
if(!loadWorld(filename, &eManager, &worldData, players, playerCount)) {
|
||||
//TODO: What do?
|
||||
networkDisconnect();
|
||||
|
||||
sf2d_set_clear_color(0xFF);
|
||||
currentSelection = 0;
|
||||
currentMenu = MENU_TITLE;
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn players
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].isSpawned) {
|
||||
playerSpawn(players+i);
|
||||
}
|
||||
}
|
||||
|
||||
// Init player maps
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
initMiniMap(players+i);
|
||||
}
|
||||
|
||||
stallCounter = 0;
|
||||
}
|
||||
|
||||
void syncedTick() {
|
||||
int i;
|
||||
|
||||
setListenerPosition(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y);
|
||||
int i;
|
||||
|
||||
//win/death menus
|
||||
for(i=0; i<playerCount; i++) {
|
||||
if (players[i].entity.p.isDead) {
|
||||
if (players[i].entity.p.endTimer < 1) {
|
||||
players[i].ingameMenu = MENU_LOSE;
|
||||
}
|
||||
--players[i].entity.p.endTimer;
|
||||
} else if (players[i].entity.p.hasWon) {
|
||||
if (players[i].entity.p.endTimer < 1) {
|
||||
players[i].ingameMenu = MENU_WIN;
|
||||
}
|
||||
--players[i].entity.p.endTimer;
|
||||
}
|
||||
}
|
||||
setListenerPosition(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y);
|
||||
|
||||
//update worldData (daytime,season and weather)
|
||||
++worldData.daytime;
|
||||
if(worldData.daytime>=24000) {
|
||||
worldData.daytime -= 24000;
|
||||
++worldData.day;
|
||||
//TODO: maybe make season length not as hardcoded + make the transition better (fade to black and back maybe?)
|
||||
if(worldData.day%7==0) {
|
||||
++worldData.season;
|
||||
if(worldData.season==4) worldData.season = 0;
|
||||
}
|
||||
worldData.rain = false;
|
||||
if(worldData.season!=3 && rand()%5==0) worldData.rain = true;
|
||||
}
|
||||
|
||||
//update music
|
||||
updateMusic(getLocalPlayer()->entity.level, worldData.daytime);
|
||||
|
||||
//for every active level
|
||||
s8 level;
|
||||
for(level = 0; level < 6; level++) {
|
||||
bool hasPlayer = false;
|
||||
for(i=0; i<playerCount; i++) {
|
||||
if(players[i].entity.level==level) {
|
||||
hasPlayer = true;
|
||||
}
|
||||
}
|
||||
if(!hasPlayer) continue;
|
||||
//win/death menus
|
||||
for(i=0; i<playerCount; i++) {
|
||||
if (players[i].entity.p.isDead) {
|
||||
if (players[i].entity.p.endTimer < 1) {
|
||||
players[i].ingameMenu = MENU_LOSE;
|
||||
}
|
||||
--players[i].entity.p.endTimer;
|
||||
} else if (players[i].entity.p.hasWon) {
|
||||
if (players[i].entity.p.endTimer < 1) {
|
||||
players[i].ingameMenu = MENU_WIN;
|
||||
}
|
||||
--players[i].entity.p.endTimer;
|
||||
}
|
||||
}
|
||||
|
||||
//tick tiles
|
||||
for (i = 0; i < 324; ++i) {
|
||||
int xx = rand() & 127;
|
||||
int yy = rand() & 127;
|
||||
tickTile(level, xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(i=0; i<playerCount; i++) {
|
||||
ingameMenuTickTouch(players+i);
|
||||
|
||||
bool inmenu = false;
|
||||
if(players[i].ingameMenu != MENU_NONE) {
|
||||
ingameMenuTick(players+i, players[i].ingameMenu);
|
||||
inmenu = true;
|
||||
}
|
||||
|
||||
tickPlayer(players+i, inmenu);
|
||||
}
|
||||
//update worldData (daytime,season and weather)
|
||||
++worldData.daytime;
|
||||
if(worldData.daytime>=24000) {
|
||||
worldData.daytime -= 24000;
|
||||
++worldData.day;
|
||||
//TODO: maybe make season length not as hardcoded + make the transition better (fade to black and back maybe?)
|
||||
if(worldData.day%7==0) {
|
||||
++worldData.season;
|
||||
if(worldData.season==4) worldData.season = 0;
|
||||
}
|
||||
worldData.rain = false;
|
||||
if(worldData.season!=3 && rand()%5==0) worldData.rain = true;
|
||||
}
|
||||
|
||||
|
||||
//for every active level
|
||||
for(level = 0; level < 6; level++) {
|
||||
if(level==5 && !dungeonActive()) continue;
|
||||
|
||||
bool hasPlayer = false;
|
||||
for(i=0; i<playerCount; i++) {
|
||||
if(players[i].entity.level==level) {
|
||||
hasPlayer = true;
|
||||
}
|
||||
}
|
||||
if(!hasPlayer) continue;
|
||||
|
||||
//spawn entities
|
||||
if(eManager.lastSlot[level]<80 && level != 5) {
|
||||
trySpawn(1, level);
|
||||
}
|
||||
|
||||
//update entities
|
||||
for (i = 0; i < eManager.lastSlot[level]; ++i) {
|
||||
Entity * e = &eManager.entities[level][i];
|
||||
PlayerData * p = getNearestPlayer(level, e->x, e->y);
|
||||
|
||||
//should never happen, but just for safety to prevent hard crashes
|
||||
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)
|
||||
|| (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)) {
|
||||
tickEntity(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stallCounter = 0;
|
||||
//update music
|
||||
updateMusic(getLocalPlayer()->entity.level, worldData.daytime);
|
||||
|
||||
//for every active level
|
||||
s8 level;
|
||||
for(level = 0; level < 6; level++) {
|
||||
bool hasPlayer = false;
|
||||
for(i=0; i<playerCount; i++) {
|
||||
if(players[i].entity.level==level) {
|
||||
hasPlayer = true;
|
||||
}
|
||||
}
|
||||
if(!hasPlayer) continue;
|
||||
|
||||
//tick tiles
|
||||
for (i = 0; i < 324; ++i) {
|
||||
int xx = rand() & 127;
|
||||
int yy = rand() & 127;
|
||||
tickTile(level, xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(i=0; i<playerCount; i++) {
|
||||
ingameMenuTickTouch(players+i);
|
||||
|
||||
bool inmenu = false;
|
||||
if(players[i].ingameMenu != MENU_NONE) {
|
||||
ingameMenuTick(players+i, players[i].ingameMenu);
|
||||
inmenu = true;
|
||||
}
|
||||
|
||||
tickPlayer(players+i, inmenu);
|
||||
}
|
||||
|
||||
|
||||
//for every active level
|
||||
for(level = 0; level < 6; level++) {
|
||||
if(level==5 && !dungeonActive()) continue;
|
||||
|
||||
bool hasPlayer = false;
|
||||
for(i=0; i<playerCount; i++) {
|
||||
if(players[i].entity.level==level) {
|
||||
hasPlayer = true;
|
||||
}
|
||||
}
|
||||
if(!hasPlayer) continue;
|
||||
|
||||
//spawn entities
|
||||
if(eManager.lastSlot[level]<80 && level != 5) {
|
||||
trySpawn(1, level);
|
||||
}
|
||||
|
||||
//update entities
|
||||
for (i = 0; i < eManager.lastSlot[level]; ++i) {
|
||||
Entity * e = &eManager.entities[level][i];
|
||||
PlayerData * p = getNearestPlayer(level, e->x, e->y);
|
||||
|
||||
//should never happen, but just for safety to prevent hard crashes
|
||||
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)
|
||||
|| (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)) {
|
||||
tickEntity(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stallCounter = 0;
|
||||
}
|
||||
|
||||
void tickGame() {
|
||||
synchronizerTick(&syncedTick);
|
||||
|
||||
|
||||
if(synchronizerIsRunning()) {
|
||||
stallCounter++;
|
||||
//game stalled -> most likely a player disconnected -> present option to exit game
|
||||
if(stallCounter>=STALL_TIME) {
|
||||
if(stallCounter==STALL_TIME) stallAreYouSure = false;
|
||||
|
||||
//scan local inputs, because synchronizer only updates them when not stalled
|
||||
hidScanInput();
|
||||
tickKeys(&localInputs, hidKeysHeld(), hidKeysDown());
|
||||
|
||||
if (localInputs.k_accept.clicked) {
|
||||
if(stallAreYouSure) {
|
||||
//create backup save
|
||||
if(playerLocalID==0) {
|
||||
char backupSaveFileName[256+32];
|
||||
backupSaveFileName[0] = '\0';
|
||||
|
||||
strncat(backupSaveFileName, currentFileName, strlen(currentFileName)-4);
|
||||
strcat(backupSaveFileName, ".exit.msv");
|
||||
|
||||
saveWorld(backupSaveFileName, &eManager, &worldData, players, playerCount);
|
||||
}
|
||||
|
||||
exitGame();
|
||||
} else {
|
||||
stallAreYouSure = true;
|
||||
}
|
||||
}
|
||||
if (localInputs.k_decline.clicked) {
|
||||
stallAreYouSure = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronizerTick(&syncedTick);
|
||||
|
||||
|
||||
if(synchronizerIsRunning()) {
|
||||
stallCounter++;
|
||||
//game stalled -> most likely a player disconnected -> present option to exit game
|
||||
if(stallCounter>=STALL_TIME) {
|
||||
if(stallCounter==STALL_TIME) stallAreYouSure = false;
|
||||
|
||||
//scan local inputs, because synchronizer only updates them when not stalled
|
||||
hidScanInput();
|
||||
tickKeys(&localInputs, hidKeysHeld(), hidKeysDown());
|
||||
|
||||
if (localInputs.k_accept.clicked) {
|
||||
if(stallAreYouSure) {
|
||||
//create backup save
|
||||
if(playerLocalID==0) {
|
||||
char backupSaveFileName[256+32];
|
||||
backupSaveFileName[0] = '\0';
|
||||
|
||||
strncat(backupSaveFileName, currentFileName, strlen(currentFileName)-4);
|
||||
strcat(backupSaveFileName, ".exit.msv");
|
||||
|
||||
saveWorld(backupSaveFileName, &eManager, &worldData, players, playerCount);
|
||||
}
|
||||
|
||||
exitGame();
|
||||
} else {
|
||||
stallAreYouSure = true;
|
||||
}
|
||||
}
|
||||
if (localInputs.k_decline.clicked) {
|
||||
stallAreYouSure = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//for rendering -> move to a better place
|
||||
int xscr = 0, yscr = 0;
|
||||
|
||||
void renderGame() {
|
||||
//Important: all code called from this function should never affect game state!
|
||||
sf2d_start_frame(GFX_TOP, GFX_LEFT);
|
||||
//Important: all code called from this function should never affect game state!
|
||||
sf2d_start_frame(GFX_TOP, GFX_LEFT);
|
||||
|
||||
int xscr = getLocalPlayer()->entity.x - 100;
|
||||
int yscr = getLocalPlayer()->entity.y - 56;
|
||||
if (xscr < 16)
|
||||
xscr = 16;
|
||||
else if (xscr > 1832)
|
||||
xscr = 1832;
|
||||
if (yscr < 16)
|
||||
yscr = 16;
|
||||
else if (yscr > 1912)
|
||||
yscr = 1912;
|
||||
|
||||
|
||||
offsetX = xscr;
|
||||
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
|
||||
|
||||
renderLightsToStencil(getLocalPlayer(), false, false, true);
|
||||
int xscr = getLocalPlayer()->entity.x - 100;
|
||||
int yscr = getLocalPlayer()->entity.y - 56;
|
||||
if (xscr < 16)
|
||||
xscr = 16;
|
||||
else if (xscr > 1832)
|
||||
xscr = 1832;
|
||||
if (yscr < 16)
|
||||
yscr = 16;
|
||||
else if (yscr > 1912)
|
||||
yscr = 1912;
|
||||
|
||||
renderBackground(getLocalPlayer()->entity.level, xscr, yscr);
|
||||
renderEntities(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y, &eManager);
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
renderPlayer(players+i);
|
||||
}
|
||||
renderWeather(getLocalPlayer()->entity.level, xscr, yscr);
|
||||
|
||||
resetStencilStuff();
|
||||
|
||||
renderDayNight(getLocalPlayer());
|
||||
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
|
||||
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]);
|
||||
drawText(fpsstr, 2, 225);
|
||||
}
|
||||
|
||||
if(getLocalPlayer()->ingameMenu != MENU_NONE) {
|
||||
ingameMenuRender(getLocalPlayer(), getLocalPlayer()->ingameMenu);
|
||||
}
|
||||
|
||||
//game stalled -> most likely a player disconnected -> present option to exit game
|
||||
if(stallCounter>STALL_TIME) {
|
||||
renderFrame(1,1,24,14,0xFF1010AF);
|
||||
drawText("Waiting for a long time", (400 - (23 * 12))/2, 32);
|
||||
|
||||
char text[50];
|
||||
sprintf(text, "Last response %is ago", stallCounter/60);
|
||||
drawText(text, (400 - (strlen(text) * 12))/2, 64);
|
||||
|
||||
if(playerLocalID==0) {
|
||||
drawText("Press to leave the game", (400 - (25 * 12))/2, 160);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 157, 1);
|
||||
|
||||
drawText("A backup save will be created", (400 - (29 * 12))/2, 192);
|
||||
} else {
|
||||
drawText("Press to leave the game", (400 - (25 * 12))/2, 192);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 189, 1);
|
||||
}
|
||||
|
||||
if(stallAreYouSure){
|
||||
renderFrame(6,5,19,10,0xFF10108F);
|
||||
|
||||
drawText("Are you sure?",122,96);
|
||||
drawText(" Yes", 164, 117);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1);
|
||||
drawText(" No", 170, 133);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1);
|
||||
}
|
||||
}
|
||||
|
||||
sf2d_end_frame();
|
||||
offsetX = xscr;
|
||||
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_start_frame(GFX_BOTTOM, GFX_LEFT);
|
||||
if(!players[playerLocalID].mapShouldRender){
|
||||
sf2d_draw_texture(bottombg, 0, 0);
|
||||
renderGui(getLocalPlayer());
|
||||
} else {
|
||||
renderZoomedMap(getLocalPlayer());
|
||||
}
|
||||
sf2d_end_frame();
|
||||
renderLightsToStencil(getLocalPlayer(), false, false, true);
|
||||
|
||||
renderBackground(getLocalPlayer()->entity.level, xscr, yscr);
|
||||
renderEntities(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y, &eManager);
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
renderPlayer(players+i);
|
||||
}
|
||||
renderWeather(getLocalPlayer()->entity.level, xscr, yscr);
|
||||
|
||||
resetStencilStuff();
|
||||
|
||||
renderDayNight(getLocalPlayer());
|
||||
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
|
||||
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]);
|
||||
drawText(fpsstr, 2, 225);
|
||||
}
|
||||
|
||||
if(getLocalPlayer()->ingameMenu != MENU_NONE) {
|
||||
ingameMenuRender(getLocalPlayer(), getLocalPlayer()->ingameMenu);
|
||||
}
|
||||
|
||||
//game stalled -> most likely a player disconnected -> present option to exit game
|
||||
if(stallCounter>STALL_TIME) {
|
||||
renderFrame(1,1,24,14,0xFF1010AF);
|
||||
drawText("Waiting for a long time", (400 - (23 * 12))/2, 32);
|
||||
|
||||
char text[50];
|
||||
sprintf(text, "Last response %is ago", stallCounter/60);
|
||||
drawText(text, (400 - (strlen(text) * 12))/2, 64);
|
||||
|
||||
if(playerLocalID==0) {
|
||||
drawText("Press to leave the game", (400 - (25 * 12))/2, 160);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 157, 1);
|
||||
|
||||
drawText("A backup save will be created", (400 - (29 * 12))/2, 192);
|
||||
} else {
|
||||
drawText("Press to leave the game", (400 - (25 * 12))/2, 192);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 189, 1);
|
||||
}
|
||||
|
||||
if(stallAreYouSure){
|
||||
renderFrame(6,5,19,10,0xFF10108F);
|
||||
|
||||
drawText("Are you sure?",122,96);
|
||||
drawText(" Yes", 164, 117);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1);
|
||||
drawText(" No", 170, 133);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1);
|
||||
}
|
||||
}
|
||||
|
||||
sf2d_end_frame();
|
||||
|
||||
sf2d_start_frame(GFX_BOTTOM, GFX_LEFT);
|
||||
if(!players[playerLocalID].mapShouldRender){
|
||||
sf2d_draw_texture(bottombg, 0, 0);
|
||||
renderGui(getLocalPlayer());
|
||||
} else {
|
||||
renderZoomedMap(getLocalPlayer());
|
||||
}
|
||||
sf2d_end_frame();
|
||||
}
|
||||
|
||||
void exitGame() {
|
||||
romfsExit();
|
||||
networkDisconnect();
|
||||
synchronizerReset();
|
||||
|
||||
sf2d_set_clear_color(0xFF);
|
||||
currentSelection = 0;
|
||||
currentMenu = MENU_TITLE;
|
||||
|
||||
playMusic(&music_menu);
|
||||
networkDisconnect();
|
||||
synchronizerReset();
|
||||
|
||||
sf2d_set_clear_color(0xFF);
|
||||
currentSelection = 0;
|
||||
currentMenu = MENU_TITLE;
|
||||
|
||||
playMusic(&music_menu);
|
||||
}
|
||||
|
|
|
@ -10,104 +10,104 @@
|
|||
char pOptions[][24] = {"Return to game", "Save Progress", "Exit to title"};
|
||||
|
||||
void ingameMenuTick(PlayerData *pd, int menu) {
|
||||
switch(menu) {
|
||||
case MENU_PAUSED:
|
||||
if(!pd->ingameMenuAreYouSure && !pd->ingameMenuAreYouSureSave){
|
||||
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_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_accept.clicked){
|
||||
switch(pd->ingameMenuSelection){
|
||||
case 0:
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
break;
|
||||
case 1:
|
||||
if(!dungeonActive()) pd->ingameMenuAreYouSureSave = true;
|
||||
break;
|
||||
case 2:
|
||||
pd->ingameMenuAreYouSure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(pd->ingameMenuAreYouSureSave) {
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenuTimer = 60;
|
||||
|
||||
if(playerLocalID==0) {
|
||||
saveWorld(currentFileName, &eManager, &worldData, players, playerCount);
|
||||
}
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
} else if (pd->inputs.k_decline.clicked){
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
}
|
||||
} else if(pd->ingameMenuAreYouSure) {
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
|
||||
exitGame();
|
||||
} else if (pd->inputs.k_decline.clicked){
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENU_INVENTORY:
|
||||
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked){
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->activeItem = &noItem;
|
||||
pd->entity.p.isCarrying = false;
|
||||
}
|
||||
if (pd->inputs.k_accept.clicked){ // Select item from inventory
|
||||
if(pd->inventory.lastSlot!=0){
|
||||
Item median = pd->inventory.items[pd->ingameMenuInvSel]; // create copy of item.
|
||||
removeItemFromInventory(pd->ingameMenuInvSel, &(pd->inventory)); // remove original
|
||||
pushItemToInventoryFront(median, &(pd->inventory)); // add copy to front
|
||||
switch(menu) {
|
||||
case MENU_PAUSED:
|
||||
if(!pd->ingameMenuAreYouSure && !pd->ingameMenuAreYouSureSave){
|
||||
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_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_accept.clicked){
|
||||
switch(pd->ingameMenuSelection){
|
||||
case 0:
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
break;
|
||||
case 1:
|
||||
if(!dungeonActive()) pd->ingameMenuAreYouSureSave = true;
|
||||
break;
|
||||
case 2:
|
||||
pd->ingameMenuAreYouSure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if(pd->ingameMenuAreYouSureSave) {
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenuTimer = 60;
|
||||
|
||||
if(playerLocalID==0) {
|
||||
saveWorld(currentFileName, &eManager, &worldData, players, playerCount);
|
||||
}
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
} else if (pd->inputs.k_decline.clicked){
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
}
|
||||
} else if(pd->ingameMenuAreYouSure) {
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
|
||||
exitGame();
|
||||
} else if (pd->inputs.k_decline.clicked){
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENU_INVENTORY:
|
||||
if (pd->inputs.k_menu.clicked || pd->inputs.k_use.clicked || pd->inputs.k_decline.clicked){
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->activeItem = &noItem;
|
||||
pd->entity.p.isCarrying = false;
|
||||
}
|
||||
if (pd->inputs.k_accept.clicked){ // Select item from inventory
|
||||
if(pd->inventory.lastSlot!=0){
|
||||
Item median = pd->inventory.items[pd->ingameMenuInvSel]; // create copy of item.
|
||||
removeItemFromInventory(pd->ingameMenuInvSel, &(pd->inventory)); // remove original
|
||||
pushItemToInventoryFront(median, &(pd->inventory)); // add copy to front
|
||||
playerSetActiveItem(pd, &(pd->inventory.items[0])); // active item = copy.
|
||||
}
|
||||
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_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->inventory.lastSlot-1)pd->ingameMenuInvSel=0; }
|
||||
break;
|
||||
|
||||
case MENU_CRAFTING:
|
||||
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
if(craftItem(&(pd->currentRecipes), &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]), &(pd->inventory))){
|
||||
playSoundPositioned(snd_craft, pd->entity.level, pd->entity.x, pd->entity.y);
|
||||
//reset active item pointer, because it could posibly point to garbage now
|
||||
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_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->currentRecipes.size-1)pd->ingameMenuInvSel=0; }
|
||||
break;
|
||||
|
||||
case MENU_WIN:
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->entity.p.hasWon = false;
|
||||
}
|
||||
break;
|
||||
case MENU_LOSE:
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->entity.p.isDead = false;
|
||||
pd->entity.p.health = 10;
|
||||
pd->entity.level = 1;
|
||||
playerSpawn(pd);
|
||||
//TODO: This canceled to main menu, but what should I do in multiplayer?
|
||||
}
|
||||
pd->entity.hurtTime = 10;
|
||||
break;
|
||||
|
||||
case MENU_CONTAINER:
|
||||
}
|
||||
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_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->inventory.lastSlot-1)pd->ingameMenuInvSel=0; }
|
||||
break;
|
||||
|
||||
case MENU_CRAFTING:
|
||||
if (pd->inputs.k_menu.clicked || pd->inputs.k_use.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
if(craftItem(&(pd->currentRecipes), &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]), &(pd->inventory))){
|
||||
playSoundPositioned(snd_craft, pd->entity.level, pd->entity.x, pd->entity.y);
|
||||
//reset active item pointer, because it could posibly point to garbage now
|
||||
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_down.clicked) { ++pd->ingameMenuInvSel; if(pd->ingameMenuInvSel > pd->currentRecipes.size-1)pd->ingameMenuInvSel=0; }
|
||||
break;
|
||||
|
||||
case MENU_WIN:
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->entity.p.hasWon = false;
|
||||
}
|
||||
break;
|
||||
case MENU_LOSE:
|
||||
if (pd->inputs.k_accept.clicked){
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->entity.p.isDead = false;
|
||||
pd->entity.p.health = 10;
|
||||
pd->entity.level = 1;
|
||||
playerSpawn(pd);
|
||||
//TODO: This canceled to main menu, but what should I do in multiplayer?
|
||||
}
|
||||
pd->entity.hurtTime = 10;
|
||||
break;
|
||||
|
||||
case MENU_CONTAINER:
|
||||
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
|
||||
|
||||
|
||||
if (pd->inputs.k_left.clicked) {
|
||||
pd->curChestEntityR = 0;
|
||||
int tmp = pd->ingameMenuInvSel;
|
||||
|
@ -120,7 +120,7 @@ void ingameMenuTick(PlayerData *pd, int menu) {
|
|||
pd->ingameMenuInvSel = pd->ingameMenuInvSelOther;
|
||||
pd->ingameMenuInvSelOther = tmp;
|
||||
}
|
||||
|
||||
|
||||
Inventory* i1 = pd->curChestEntityR == 1 ? &(pd->inventory) : pd->curChestEntity->entityFurniture.inv;
|
||||
Inventory* i2 = pd->curChestEntityR == 0 ? &(pd->inventory) : pd->curChestEntity->entityFurniture.inv;
|
||||
int len = i1->lastSlot;
|
||||
|
@ -131,7 +131,7 @@ void ingameMenuTick(PlayerData *pd, int menu) {
|
|||
if (len == 0) pd->ingameMenuInvSel = 0;
|
||||
if (pd->ingameMenuInvSel < 0) pd->ingameMenuInvSel += len;
|
||||
if (pd->ingameMenuInvSel >= len) pd->ingameMenuInvSel -= len;
|
||||
|
||||
|
||||
if(pd->inputs.k_accept.clicked && len > 0){
|
||||
Item* pullItem = &i1->items[pd->ingameMenuInvSel];
|
||||
Item pushItem = newItem(pullItem->id, pullItem->countLevel);
|
||||
|
@ -146,11 +146,11 @@ void ingameMenuTick(PlayerData *pd, int menu) {
|
|||
removeItemFromCurrentInv(pullItem);
|
||||
if (pd->ingameMenuInvSel >= i1->lastSlot) pd->ingameMenuInvSel = i1->lastSlot - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case MENU_DUNGEON:
|
||||
if (pd->inputs.k_menu.clicked || pd->inputs.k_decline.clicked) pd->ingameMenu = MENU_NONE;
|
||||
|
||||
|
||||
if(pd->inputs.k_accept.clicked) {
|
||||
if(pd->entity.level!=5) {
|
||||
Item * item = getItemFromInventory(ITEM_DUNGEON_KEY, &(pd->inventory));
|
||||
|
@ -159,68 +159,68 @@ void ingameMenuTick(PlayerData *pd, int menu) {
|
|||
if(item->countLevel==0) {
|
||||
removeItemFromCurrentInv(item);
|
||||
}
|
||||
|
||||
|
||||
enterDungeon(pd);
|
||||
} else if(shouldRenderDebug) {
|
||||
enterDungeon(pd);
|
||||
}
|
||||
enterDungeon(pd);
|
||||
}
|
||||
} else {
|
||||
leaveDungeon(pd);
|
||||
}
|
||||
|
||||
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case MENU_NPC:
|
||||
tickNPCMenu(pd);
|
||||
break;
|
||||
|
||||
case MENU_CHARACTER_CUSTOMIZE:
|
||||
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; }
|
||||
|
||||
u8 wrap = 0;
|
||||
wrap = wrap - 1;
|
||||
|
||||
pd->entity.p.health = 10;
|
||||
pd->entity.hurtTime = 10;
|
||||
|
||||
//head
|
||||
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_right.clicked) { ++pd->sprite.head; if(pd->sprite.head > PLAYER_SPRITE_HEAD_COUNT-1) pd->sprite.head=0; }
|
||||
//eyes
|
||||
} 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_right.clicked) { ++pd->sprite.eyes; if(pd->sprite.eyes > PLAYER_SPRITE_EYES_COUNT-1) pd->sprite.eyes=0; }
|
||||
//body
|
||||
} 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_right.clicked) { ++pd->sprite.body; if(pd->sprite.body > PLAYER_SPRITE_BODY_COUNT-1) pd->sprite.body=0; }
|
||||
//arms
|
||||
} 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_right.clicked) { ++pd->sprite.arms; if(pd->sprite.arms > PLAYER_SPRITE_ARMS_COUNT-1) pd->sprite.arms=0; }
|
||||
//legs
|
||||
} 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_right.clicked) { ++pd->sprite.legs; if(pd->sprite.legs > PLAYER_SPRITE_LEGS_COUNT-1) pd->sprite.legs=0; }
|
||||
//rotation
|
||||
} 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_right.clicked) { ++pd->entity.p.dir; if(pd->entity.p.dir > 3) pd->entity.p.dir=0; }
|
||||
//done
|
||||
} else if(pd->ingameMenuSelection==6) {
|
||||
if(pd->inputs.k_accept.clicked) {
|
||||
//TODO: are you sure dialog?
|
||||
pd->ingameMenu = 0;
|
||||
pd->ingameMenuSelection = 0;
|
||||
pd->sprite.choosen = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_NPC:
|
||||
tickNPCMenu(pd);
|
||||
break;
|
||||
|
||||
case MENU_CHARACTER_CUSTOMIZE:
|
||||
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; }
|
||||
|
||||
u8 wrap = 0;
|
||||
wrap = wrap - 1;
|
||||
|
||||
pd->entity.p.health = 10;
|
||||
pd->entity.hurtTime = 10;
|
||||
|
||||
//head
|
||||
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_right.clicked) { ++pd->sprite.head; if(pd->sprite.head > PLAYER_SPRITE_HEAD_COUNT-1) pd->sprite.head=0; }
|
||||
//eyes
|
||||
} 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_right.clicked) { ++pd->sprite.eyes; if(pd->sprite.eyes > PLAYER_SPRITE_EYES_COUNT-1) pd->sprite.eyes=0; }
|
||||
//body
|
||||
} 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_right.clicked) { ++pd->sprite.body; if(pd->sprite.body > PLAYER_SPRITE_BODY_COUNT-1) pd->sprite.body=0; }
|
||||
//arms
|
||||
} 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_right.clicked) { ++pd->sprite.arms; if(pd->sprite.arms > PLAYER_SPRITE_ARMS_COUNT-1) pd->sprite.arms=0; }
|
||||
//legs
|
||||
} 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_right.clicked) { ++pd->sprite.legs; if(pd->sprite.legs > PLAYER_SPRITE_LEGS_COUNT-1) pd->sprite.legs=0; }
|
||||
//rotation
|
||||
} 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_right.clicked) { ++pd->entity.p.dir; if(pd->entity.p.dir > 3) pd->entity.p.dir=0; }
|
||||
//done
|
||||
} else if(pd->ingameMenuSelection==6) {
|
||||
if(pd->inputs.k_accept.clicked) {
|
||||
//TODO: are you sure dialog?
|
||||
pd->ingameMenu = 0;
|
||||
pd->ingameMenuSelection = 0;
|
||||
pd->sprite.choosen = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -229,291 +229,291 @@ bool rev = true;
|
|||
char scoreText[15];
|
||||
|
||||
void ingameMenuRender(PlayerData *pd, int menu) {
|
||||
int i;
|
||||
|
||||
switch(menu) {
|
||||
case MENU_PAUSED:
|
||||
renderFrame(1,1,24,14,0xFF1010AF);
|
||||
drawText("Paused",164,32);
|
||||
for(i = 3; i >= 0; --i){
|
||||
char* msg = pOptions[i];
|
||||
u32 color = 0xFF7F7F7F;
|
||||
if(i == pd->ingameMenuSelection) color = 0xFFFFFFFF;
|
||||
if((i == 1 && dungeonActive())) {
|
||||
color = 0xFF7F7FFF;
|
||||
if(i == pd->ingameMenuSelection) color = 0xFFAFAFFF;
|
||||
}
|
||||
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->ingameMenuAreYouSure || pd->ingameMenuAreYouSureSave){
|
||||
if(pd->ingameMenuAreYouSure)renderFrame(6,5,19,10,0xFF10108F);
|
||||
else renderFrame(6,5,19,10,0xFF108F10);
|
||||
|
||||
drawText("Are you sure?",122,96);
|
||||
drawText(" Yes", 164, 117);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1);
|
||||
drawText(" No", 170, 133);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1);
|
||||
}
|
||||
break;
|
||||
case MENU_WIN:
|
||||
renderFrame(5,3,21,12,0xFFFF1010);
|
||||
if(!rev){ opacity+=5; if(opacity == 255) rev = true; }
|
||||
else { opacity-=5; if(opacity == 100) rev = false; }
|
||||
sprintf(scoreText,"Score: %d", pd->score);
|
||||
drawTextColor("You Win!",158,76,0x0000AFAF + (opacity << 24));
|
||||
drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100);
|
||||
drawText("Press to continue", 96, 150);
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1);
|
||||
|
||||
//printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input);
|
||||
break;
|
||||
case MENU_LOSE:
|
||||
renderFrame(5,3,21,12,0xFFFF1010);
|
||||
if(!rev){ opacity+=5; if(opacity == 255) rev = true; }
|
||||
else { opacity-=5; if(opacity == 100) rev = false; }
|
||||
sprintf(scoreText,"Score: %d", pd->score);
|
||||
drawTextColor("You DIED!",158,76,0x000000AF + (opacity << 24));
|
||||
drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100);
|
||||
drawText("Press to continue", 96, 150);
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1);
|
||||
//printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input);
|
||||
break;
|
||||
case MENU_INVENTORY:
|
||||
renderFrame(1,1,24,14,0xFFFF1010);
|
||||
drawTextColor("Inventory",24+1,14+1,0xFF000000);
|
||||
drawTextColor("Inventory",24,14,0xFF6FE2E2);
|
||||
renderItemList(&(pd->inventory), 1,1,24,14, pd->ingameMenuInvSel);
|
||||
break;
|
||||
case MENU_CRAFTING:
|
||||
renderFrame(15,1,24,4,0xFFFF1010);
|
||||
drawTextColor("Have",248+1,14+1,0xFF000000);
|
||||
drawTextColor("Have",248,14,0xFF6FE2E2);
|
||||
renderFrame(15,5,24,14,0xFFFF1010);
|
||||
drawTextColor("Cost",248+1,78+1,0xFF000000);
|
||||
drawTextColor("Cost",248,78,0xFF6FE2E2);
|
||||
renderFrame(1,1,14,14,0xFFFF1010);
|
||||
drawTextColor(pd->currentCraftTitle,24+1,14+1,0xFF000000);
|
||||
drawTextColor(pd->currentCraftTitle,24,14,0xFF6FE2E2);
|
||||
renderRecipes(&(pd->currentRecipes), 1, 1, 14, 14, pd->ingameMenuInvSel);
|
||||
|
||||
Recipe* rec = &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]);
|
||||
renderItemIcon(rec->itemResult,rec->itemAmountLevel,128,16);
|
||||
char craftText[12];
|
||||
sprintf(craftText, "%d", countItemInv(rec->itemResult, rec->itemAmountLevel, &(pd->inventory)));
|
||||
drawText(craftText,274,34);
|
||||
|
||||
if(rec->numOfCosts > 0){
|
||||
int i;
|
||||
for(i = 0; i < rec->numOfCosts; i++){
|
||||
int amnt = countItemInv(rec->costs[i].costItem,0, &(pd->inventory));
|
||||
int ttlCst = rec->costs[i].costAmount;
|
||||
int col = 0xFFFFFFFF; if(amnt<ttlCst) col = 0xFF7F7F7F;
|
||||
renderItemIcon(rec->costs[i].costItem,1,128,48+(i*8));
|
||||
sprintf(craftText,"%d/%d",amnt,ttlCst);
|
||||
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);
|
||||
int i;
|
||||
|
||||
switch(menu) {
|
||||
case MENU_PAUSED:
|
||||
renderFrame(1,1,24,14,0xFF1010AF);
|
||||
drawText("Paused",164,32);
|
||||
for(i = 3; i >= 0; --i){
|
||||
char* msg = pOptions[i];
|
||||
u32 color = 0xFF7F7F7F;
|
||||
if(i == pd->ingameMenuSelection) color = 0xFFFFFFFF;
|
||||
if((i == 1 && dungeonActive())) {
|
||||
color = 0xFF7F7FFF;
|
||||
if(i == pd->ingameMenuSelection) color = 0xFFAFAFFF;
|
||||
}
|
||||
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->ingameMenuAreYouSure || pd->ingameMenuAreYouSureSave){
|
||||
if(pd->ingameMenuAreYouSure)renderFrame(6,5,19,10,0xFF10108F);
|
||||
else renderFrame(6,5,19,10,0xFF108F10);
|
||||
|
||||
drawText("Are you sure?",122,96);
|
||||
drawText(" Yes", 164, 117);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 166, 114, 1);
|
||||
drawText(" No", 170, 133);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 166, 130, 1);
|
||||
}
|
||||
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;
|
||||
}
|
||||
case MENU_WIN:
|
||||
renderFrame(5,3,21,12,0xFFFF1010);
|
||||
if(!rev){ opacity+=5; if(opacity == 255) rev = true; }
|
||||
else { opacity-=5; if(opacity == 100) rev = false; }
|
||||
sprintf(scoreText,"Score: %d", pd->score);
|
||||
drawTextColor("You Win!",158,76,0x0000AFAF + (opacity << 24));
|
||||
drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100);
|
||||
drawText("Press to continue", 96, 150);
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1);
|
||||
|
||||
//printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input);
|
||||
break;
|
||||
case MENU_LOSE:
|
||||
renderFrame(5,3,21,12,0xFFFF1010);
|
||||
if(!rev){ opacity+=5; if(opacity == 255) rev = true; }
|
||||
else { opacity-=5; if(opacity == 100) rev = false; }
|
||||
sprintf(scoreText,"Score: %d", pd->score);
|
||||
drawTextColor("You DIED!",158,76,0x000000AF + (opacity << 24));
|
||||
drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100);
|
||||
drawText("Press to continue", 96, 150);
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 166, 148, 1);
|
||||
//printf("0x%08X",localInputs.k_attack.input & -localInputs.k_attack.input);
|
||||
break;
|
||||
case MENU_INVENTORY:
|
||||
renderFrame(1,1,24,14,0xFFFF1010);
|
||||
drawTextColor("Inventory",24+1,14+1,0xFF000000);
|
||||
drawTextColor("Inventory",24,14,0xFF6FE2E2);
|
||||
renderItemList(&(pd->inventory), 1,1,24,14, pd->ingameMenuInvSel);
|
||||
break;
|
||||
case MENU_CRAFTING:
|
||||
renderFrame(15,1,24,4,0xFFFF1010);
|
||||
drawTextColor("Have",248+1,14+1,0xFF000000);
|
||||
drawTextColor("Have",248,14,0xFF6FE2E2);
|
||||
renderFrame(15,5,24,14,0xFFFF1010);
|
||||
drawTextColor("Cost",248+1,78+1,0xFF000000);
|
||||
drawTextColor("Cost",248,78,0xFF6FE2E2);
|
||||
renderFrame(1,1,14,14,0xFFFF1010);
|
||||
drawTextColor(pd->currentCraftTitle,24+1,14+1,0xFF000000);
|
||||
drawTextColor(pd->currentCraftTitle,24,14,0xFF6FE2E2);
|
||||
renderRecipes(&(pd->currentRecipes), 1, 1, 14, 14, pd->ingameMenuInvSel);
|
||||
|
||||
Recipe* rec = &(pd->currentRecipes.recipes[pd->ingameMenuInvSel]);
|
||||
renderItemIcon(rec->itemResult,rec->itemAmountLevel,128,16);
|
||||
char craftText[12];
|
||||
sprintf(craftText, "%d", countItemInv(rec->itemResult, rec->itemAmountLevel, &(pd->inventory)));
|
||||
drawText(craftText,274,34);
|
||||
|
||||
if(rec->numOfCosts > 0){
|
||||
int i;
|
||||
for(i = 0; i < rec->numOfCosts; i++){
|
||||
int amnt = countItemInv(rec->costs[i].costItem,0, &(pd->inventory));
|
||||
int ttlCst = rec->costs[i].costAmount;
|
||||
int col = 0xFFFFFFFF; if(amnt<ttlCst) col = 0xFF7F7F7F;
|
||||
renderItemIcon(rec->costs[i].costItem,1,128,48+(i*8));
|
||||
sprintf(craftText,"%d/%d",ttlCst,amnt);
|
||||
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;
|
||||
|
||||
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
|
||||
void tickTouchMap(PlayerData *pd){
|
||||
if(pd->mapShouldRender){
|
||||
if(pd->inputs.k_touch.px > 0 || pd->inputs.k_touch.py > 0){
|
||||
// Plus/Minus zoom button
|
||||
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->mapZoomLevel > 4) return;
|
||||
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
|
||||
pd->mapZoomLevel += 2;
|
||||
pd->mapScrollX -= (50 * (pd->mapZoomLevel/2));
|
||||
pd->mapScrollY -= (40 * (pd->mapZoomLevel/2));
|
||||
pd->touchIsChangingSize = true;
|
||||
sprintf(pd->mapText, "x%d", pd->mapZoomLevel);
|
||||
}
|
||||
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
|
||||
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
|
||||
return;
|
||||
} else if(pd->inputs.k_touch.px > 256 && pd->inputs.k_touch.px < 284){
|
||||
if(pd->mapZoomLevel < 4) return;
|
||||
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
|
||||
pd->mapScrollX += (50 * (pd->mapZoomLevel/2));
|
||||
pd->mapScrollY += (40 * (pd->mapZoomLevel/2));
|
||||
pd->mapZoomLevel -= 2;
|
||||
pd->touchIsChangingSize = true;
|
||||
sprintf(pd->mapText, "x%d", pd->mapZoomLevel);
|
||||
}
|
||||
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
|
||||
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
|
||||
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){
|
||||
// Exit Button
|
||||
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
|
||||
pd->mapShouldRender = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!pd->touchIsDraggingMap){
|
||||
pd->touchLastX = pd->inputs.k_touch.px;
|
||||
pd->touchLastY = pd->inputs.k_touch.py;
|
||||
}
|
||||
if(pd->mapZoomLevel > 2){
|
||||
int dx = pd->touchLastX - pd->inputs.k_touch.px;
|
||||
if(dx > 1 || dx < -1){
|
||||
pd->mapScrollX -= dx;
|
||||
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
|
||||
}
|
||||
pd->touchLastX = pd->inputs.k_touch.px;
|
||||
}
|
||||
|
||||
int dy = pd->touchLastY - pd->inputs.k_touch.py;
|
||||
if(dy > 1 || dy < -1){
|
||||
pd->mapScrollY -= dy;
|
||||
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
|
||||
}
|
||||
pd->touchLastY = pd->inputs.k_touch.py;
|
||||
pd->touchIsDraggingMap = true;
|
||||
} else {
|
||||
pd->touchIsDraggingMap = false;
|
||||
pd->touchIsChangingSize = false;
|
||||
}
|
||||
} else {
|
||||
// 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){
|
||||
pd->mapShouldRender = true;
|
||||
}
|
||||
}
|
||||
if(pd->mapShouldRender){
|
||||
if(pd->inputs.k_touch.px > 0 || pd->inputs.k_touch.py > 0){
|
||||
// Plus/Minus zoom button
|
||||
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->mapZoomLevel > 4) return;
|
||||
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
|
||||
pd->mapZoomLevel += 2;
|
||||
pd->mapScrollX -= (50 * (pd->mapZoomLevel/2));
|
||||
pd->mapScrollY -= (40 * (pd->mapZoomLevel/2));
|
||||
pd->touchIsChangingSize = true;
|
||||
sprintf(pd->mapText, "x%d", pd->mapZoomLevel);
|
||||
}
|
||||
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
|
||||
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
|
||||
return;
|
||||
} else if(pd->inputs.k_touch.px > 256 && pd->inputs.k_touch.px < 284){
|
||||
if(pd->mapZoomLevel < 4) return;
|
||||
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
|
||||
pd->mapScrollX += (50 * (pd->mapZoomLevel/2));
|
||||
pd->mapScrollY += (40 * (pd->mapZoomLevel/2));
|
||||
pd->mapZoomLevel -= 2;
|
||||
pd->touchIsChangingSize = true;
|
||||
sprintf(pd->mapText, "x%d", pd->mapZoomLevel);
|
||||
}
|
||||
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
|
||||
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
|
||||
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){
|
||||
// Exit Button
|
||||
if(!pd->touchIsChangingSize && !pd->touchIsDraggingMap){
|
||||
pd->mapShouldRender = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!pd->touchIsDraggingMap){
|
||||
pd->touchLastX = pd->inputs.k_touch.px;
|
||||
pd->touchLastY = pd->inputs.k_touch.py;
|
||||
}
|
||||
if(pd->mapZoomLevel > 2){
|
||||
int dx = pd->touchLastX - pd->inputs.k_touch.px;
|
||||
if(dx > 1 || dx < -1){
|
||||
pd->mapScrollX -= dx;
|
||||
if(pd->mapScrollX < 320-(128*pd->mapZoomLevel)) pd->mapScrollX = 320-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollX > 0) pd->mapScrollX = 0;
|
||||
}
|
||||
pd->touchLastX = pd->inputs.k_touch.px;
|
||||
}
|
||||
|
||||
int dy = pd->touchLastY - pd->inputs.k_touch.py;
|
||||
if(dy > 1 || dy < -1){
|
||||
pd->mapScrollY -= dy;
|
||||
if(pd->mapScrollY < 240-(128*pd->mapZoomLevel)) pd->mapScrollY = 240-(128*pd->mapZoomLevel);
|
||||
else if(pd->mapScrollY > 0) pd->mapScrollY = 0;
|
||||
}
|
||||
pd->touchLastY = pd->inputs.k_touch.py;
|
||||
pd->touchIsDraggingMap = true;
|
||||
} else {
|
||||
pd->touchIsDraggingMap = false;
|
||||
pd->touchIsChangingSize = false;
|
||||
}
|
||||
} else {
|
||||
// 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){
|
||||
pd->mapShouldRender = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tickTouchQuickSelect(PlayerData *pd) {
|
||||
if (pd->ingameMenu == MENU_NONE && !pd->mapShouldRender) {
|
||||
int i = 0;
|
||||
Inventory * inv = &(pd->inventory);
|
||||
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
if((inv->lastSlot) > i) {
|
||||
int xip = i % 4;
|
||||
int yip = i / 4;
|
||||
|
||||
|
||||
if(pd->inputs.k_touch.py > 72*2+yip*21*2 && pd->inputs.k_touch.py < 72*2+yip*21*2+21*2 && pd->inputs.k_touch.px > 76*2+xip*21*2 && pd->inputs.k_touch.px < 76*2+xip*21*2+21*2) {
|
||||
playerSetActiveItem(pd, &inv->items[i]);
|
||||
}
|
||||
|
@ -523,6 +523,6 @@ void tickTouchQuickSelect(PlayerData *pd) {
|
|||
}
|
||||
|
||||
void ingameMenuTickTouch(PlayerData *pd) {
|
||||
tickTouchMap(pd);
|
||||
tickTouchQuickSelect(pd);
|
||||
tickTouchMap(pd);
|
||||
tickTouchQuickSelect(pd);
|
||||
}
|
||||
|
|
|
@ -1,55 +1,61 @@
|
|||
#include "Input.h"
|
||||
|
||||
void toggleKey(Key* key, bool held, bool down){
|
||||
key->down = held;
|
||||
key->down = held;
|
||||
key->clicked = down;
|
||||
}
|
||||
|
||||
|
||||
void tickKeys(Inputs *inputs, u32 held, u32 down){
|
||||
hidTouchRead(&(inputs->k_touch)); // Update touch position
|
||||
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_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_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_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_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_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);
|
||||
hidTouchRead(&(inputs->k_touch)); // Update touch position
|
||||
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_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_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_pickup), held & localInputs.k_pickup.input, down & localInputs.k_pickup.input);
|
||||
toggleKey(&(inputs->k_use), held & localInputs.k_use.input, down & localInputs.k_use.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_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_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);
|
||||
}
|
||||
|
||||
void resetKeys(Inputs *inputs) {
|
||||
(inputs->k_touch).px = -1;
|
||||
(inputs->k_touch).py = -1;
|
||||
|
||||
toggleKey(&(inputs->k_up), false, false);
|
||||
toggleKey(&(inputs->k_down), false, false);
|
||||
toggleKey(&(inputs->k_left), false, false);
|
||||
toggleKey(&(inputs->k_right), false, false);
|
||||
toggleKey(&(inputs->k_pause), false, false);
|
||||
toggleKey(&(inputs->k_attack), false, false);
|
||||
toggleKey(&(inputs->k_menu), false, false);
|
||||
toggleKey(&(inputs->k_accept), false, false);
|
||||
toggleKey(&(inputs->k_decline), false, false);
|
||||
toggleKey(&(inputs->k_delete), false, false);
|
||||
toggleKey(&(inputs->k_menuNext), false, false);
|
||||
toggleKey(&(inputs->k_menuPrev), false, false);
|
||||
(inputs->k_touch).px = -1;
|
||||
(inputs->k_touch).py = -1;
|
||||
|
||||
toggleKey(&(inputs->k_up), false, false);
|
||||
toggleKey(&(inputs->k_down), false, false);
|
||||
toggleKey(&(inputs->k_left), false, false);
|
||||
toggleKey(&(inputs->k_right), false, false);
|
||||
toggleKey(&(inputs->k_pause), false, false);
|
||||
toggleKey(&(inputs->k_attack), false, false);
|
||||
toggleKey(&(inputs->k_pickup), false, false);
|
||||
toggleKey(&(inputs->k_use), false, false);
|
||||
toggleKey(&(inputs->k_menu), false, false);
|
||||
toggleKey(&(inputs->k_accept), false, false);
|
||||
toggleKey(&(inputs->k_decline), false, false);
|
||||
toggleKey(&(inputs->k_delete), false, false);
|
||||
toggleKey(&(inputs->k_menuNext), false, false);
|
||||
toggleKey(&(inputs->k_menuPrev), false, false);
|
||||
}
|
||||
|
||||
void resetClicked(Inputs *inputs) {
|
||||
inputs->k_up.clicked = false;
|
||||
inputs->k_down.clicked = false;
|
||||
inputs->k_left.clicked = false;
|
||||
inputs->k_right.clicked = false;
|
||||
inputs->k_pause.clicked = false;
|
||||
inputs->k_attack.clicked = false;
|
||||
inputs->k_menu.clicked = false;
|
||||
inputs->k_accept.clicked = false;
|
||||
inputs->k_decline.clicked = false;
|
||||
inputs->k_delete.clicked = false;
|
||||
inputs->k_menuNext.clicked = false;
|
||||
inputs->k_menuPrev.clicked = false;
|
||||
inputs->k_up.clicked = false;
|
||||
inputs->k_down.clicked = false;
|
||||
inputs->k_left.clicked = false;
|
||||
inputs->k_right.clicked = false;
|
||||
inputs->k_pause.clicked = false;
|
||||
inputs->k_attack.clicked = false;
|
||||
inputs->k_pickup.clicked = false;
|
||||
inputs->k_use.clicked = false;
|
||||
inputs->k_menu.clicked = false;
|
||||
inputs->k_accept.clicked = false;
|
||||
inputs->k_decline.clicked = false;
|
||||
inputs->k_delete.clicked = false;
|
||||
inputs->k_menuNext.clicked = false;
|
||||
inputs->k_menuPrev.clicked = false;
|
||||
}
|
||||
|
|
|
@ -9,20 +9,22 @@ typedef struct {
|
|||
} Key;
|
||||
|
||||
typedef struct {
|
||||
Key k_null;
|
||||
Key k_up;
|
||||
Key k_down;
|
||||
Key k_left;
|
||||
Key k_right;
|
||||
Key k_attack;
|
||||
Key k_menu;
|
||||
Key k_pause;
|
||||
Key k_accept;
|
||||
Key k_decline;
|
||||
Key k_delete;
|
||||
Key k_menuNext;
|
||||
Key k_menuPrev;
|
||||
touchPosition k_touch;
|
||||
Key k_null;
|
||||
Key k_up;
|
||||
Key k_down;
|
||||
Key k_left;
|
||||
Key k_right;
|
||||
Key k_attack;
|
||||
Key k_pickup;
|
||||
Key k_use;
|
||||
Key k_menu;
|
||||
Key k_pause;
|
||||
Key k_accept;
|
||||
Key k_decline;
|
||||
Key k_delete;
|
||||
Key k_menuNext;
|
||||
Key k_menuPrev;
|
||||
touchPosition k_touch;
|
||||
} Inputs;
|
||||
|
||||
Inputs localInputs;
|
||||
|
|
474
source/Item.c
474
source/Item.c
|
@ -3,168 +3,168 @@
|
|||
char currentName[16];
|
||||
|
||||
bool isItemEmpty(Item* item) {
|
||||
if(item->id < 6 || item->id > 100 || item->onlyOne == true) return false;
|
||||
if(item->countLevel < 1) return true;
|
||||
return false;
|
||||
if(item->id < 6 || item->id > 100 || item->onlyOne == true) return false;
|
||||
if(item->countLevel < 1) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void pushItemToInventoryFront(Item item, Inventory * inv) {
|
||||
if(inv->lastSlot < 300) ++inv->lastSlot;
|
||||
int i;
|
||||
for(i = inv->lastSlot;i > 0;--i){
|
||||
inv->items[i] = inv->items[i-1]; // Move the items up the list.
|
||||
inv->items[i].slotNum = i;
|
||||
}
|
||||
item.invPtr = (int*)inv;
|
||||
inv->items[0] = item;
|
||||
inv->items[0].slotNum = 0;
|
||||
|
||||
if(inv->lastSlot < 300) ++inv->lastSlot;
|
||||
int i;
|
||||
for(i = inv->lastSlot;i > 0;--i){
|
||||
inv->items[i] = inv->items[i-1]; // Move the items up the list.
|
||||
inv->items[i].slotNum = i;
|
||||
}
|
||||
item.invPtr = (int*)inv;
|
||||
inv->items[0] = item;
|
||||
inv->items[0].slotNum = 0;
|
||||
|
||||
}
|
||||
|
||||
void addItemToInventory(Item item, Inventory * inv) {
|
||||
if(!item.onlyOne){
|
||||
int i;
|
||||
for(i = 0;i < inv->lastSlot;++i){ //Search inventory if item already exists.
|
||||
if(inv->items[i].id == item.id){
|
||||
inv->items[i].countLevel+=item.countLevel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.slotNum = inv->lastSlot;
|
||||
item.invPtr = (int*)inv;
|
||||
inv->items[inv->lastSlot] = item;
|
||||
++inv->lastSlot;
|
||||
if(!item.onlyOne){
|
||||
int i;
|
||||
for(i = 0;i < inv->lastSlot;++i){ //Search inventory if item already exists.
|
||||
if(inv->items[i].id == item.id){
|
||||
inv->items[i].countLevel+=item.countLevel;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item.slotNum = inv->lastSlot;
|
||||
item.invPtr = (int*)inv;
|
||||
inv->items[inv->lastSlot] = item;
|
||||
++inv->lastSlot;
|
||||
}
|
||||
|
||||
void removeItemFromCurrentInv(Item* item) {
|
||||
removeItemFromInventory(item->slotNum, (Inventory*)item->invPtr);
|
||||
removeItemFromInventory(item->slotNum, (Inventory*)item->invPtr);
|
||||
}
|
||||
|
||||
Item nullItem;
|
||||
void removeItemFromInventory(int slot, Inventory * inv) {
|
||||
int i;
|
||||
for(i = slot;i < inv->lastSlot - 1;++i){
|
||||
inv->items[i] = inv->items[i + 1]; // Move the items down.
|
||||
inv->items[i].slotNum--;
|
||||
}
|
||||
--inv->lastSlot;
|
||||
inv->items[inv->lastSlot] = nullItem; // Make the last slot null.
|
||||
int i;
|
||||
for(i = slot;i < inv->lastSlot - 1;++i){
|
||||
inv->items[i] = inv->items[i + 1]; // Move the items down.
|
||||
inv->items[i].slotNum--;
|
||||
}
|
||||
--inv->lastSlot;
|
||||
inv->items[inv->lastSlot] = nullItem; // Make the last slot null.
|
||||
}
|
||||
|
||||
Item newItem(int id, int cLevel) {
|
||||
Item item;
|
||||
item.id = id;
|
||||
if(id != ITEM_NULL){
|
||||
if(cLevel > 999) cLevel = 999;
|
||||
item.countLevel = cLevel;
|
||||
if(id < 7 || (id > 27 && id < 51) || id > 100) item.onlyOne = true; // Tools + Furniture.
|
||||
else item.onlyOne = false;
|
||||
}
|
||||
item.chestPtr = NULL;
|
||||
return item;
|
||||
Item item;
|
||||
item.id = id;
|
||||
if(id != ITEM_NULL){
|
||||
if(cLevel > 999) cLevel = 999;
|
||||
item.countLevel = cLevel;
|
||||
if(id < 7 || (id > 27 && id < 51) || id > 100) item.onlyOne = true; // Tools + Furniture.
|
||||
else item.onlyOne = false;
|
||||
}
|
||||
item.chestPtr = NULL;
|
||||
return item;
|
||||
}
|
||||
|
||||
Item* getItemFromInventory(int itemID, Inventory * inv) {
|
||||
int i;
|
||||
for(i = 0;i < inv->lastSlot;++i){
|
||||
if(inv->items[i].id == itemID){
|
||||
return &inv->items[i];
|
||||
}
|
||||
}
|
||||
return (Item*)NULL;
|
||||
int i;
|
||||
for(i = 0;i < inv->lastSlot;++i){
|
||||
if(inv->items[i].id == itemID){
|
||||
return &inv->items[i];
|
||||
}
|
||||
}
|
||||
return (Item*)NULL;
|
||||
}
|
||||
|
||||
int countItemInv(int itemID, int level, Inventory* inv) {
|
||||
int i, count = 0;
|
||||
for(i = 0;i < inv->lastSlot;++i){
|
||||
if(inv->items[i].id == itemID){
|
||||
if(inv->items[i].onlyOne){
|
||||
if(level == inv->items[i].countLevel) count++;
|
||||
} else count += inv->items[i].countLevel;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
int i, count = 0;
|
||||
for(i = 0;i < inv->lastSlot;++i){
|
||||
if(inv->items[i].id == itemID){
|
||||
if(inv->items[i].onlyOne){
|
||||
if(level == inv->items[i].countLevel) count++;
|
||||
} else count += inv->items[i].countLevel;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
char* getItemName(int itemID, int countLevel) {
|
||||
switch(itemID){
|
||||
case TOOL_SHOVEL:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Shovel";
|
||||
case 2: return "Iron Shovel";
|
||||
case 3: return "Gold Shovel";
|
||||
case 4: return "Gem Shovel";
|
||||
default: return "Wood Shovel";
|
||||
}
|
||||
case TOOL_HOE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Hoe";
|
||||
case 2: return "Iron Hoe";
|
||||
case 3: return "Gold Hoe";
|
||||
case 4: return "Gem Hoe";
|
||||
default: return "Wood Hoe";
|
||||
}
|
||||
case TOOL_SWORD:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Sword";
|
||||
case 2: return "Iron Sword";
|
||||
case 3: return "Gold Sword";
|
||||
case 4: return "Gem Sword";
|
||||
default: return "Wood Sword";
|
||||
}
|
||||
case TOOL_PICKAXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Pickaxe";
|
||||
case 2: return "Iron Pickaxe";
|
||||
case 3: return "Gold Pickaxe";
|
||||
case 4: return "Gem Pickaxe";
|
||||
default: return "Wood Pickaxe";
|
||||
}
|
||||
case TOOL_AXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Axe";
|
||||
case 2: return "Iron Axe";
|
||||
case 3: return "Gold Axe";
|
||||
case 4: return "Gem Axe";
|
||||
default: return "Wood Axe";
|
||||
}
|
||||
case ITEM_ANVIL: return "Anvil";
|
||||
case ITEM_CHEST: return "Chest";
|
||||
case ITEM_OVEN: return "Oven";
|
||||
case ITEM_FURNACE: return "Furnace";
|
||||
case ITEM_WORKBENCH: return "Workbench";
|
||||
switch(itemID){
|
||||
case TOOL_SHOVEL:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Shovel";
|
||||
case 2: return "Iron Shovel";
|
||||
case 3: return "Gold Shovel";
|
||||
case 4: return "Gem Shovel";
|
||||
default: return "Wood Shovel";
|
||||
}
|
||||
case TOOL_HOE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Hoe";
|
||||
case 2: return "Iron Hoe";
|
||||
case 3: return "Gold Hoe";
|
||||
case 4: return "Gem Hoe";
|
||||
default: return "Wood Hoe";
|
||||
}
|
||||
case TOOL_SWORD:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Sword";
|
||||
case 2: return "Iron Sword";
|
||||
case 3: return "Gold Sword";
|
||||
case 4: return "Gem Sword";
|
||||
default: return "Wood Sword";
|
||||
}
|
||||
case TOOL_PICKAXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Pickaxe";
|
||||
case 2: return "Iron Pickaxe";
|
||||
case 3: return "Gold Pickaxe";
|
||||
case 4: return "Gem Pickaxe";
|
||||
default: return "Wood Pickaxe";
|
||||
}
|
||||
case TOOL_AXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Axe";
|
||||
case 2: return "Iron Axe";
|
||||
case 3: return "Gold Axe";
|
||||
case 4: return "Gem Axe";
|
||||
default: return "Wood Axe";
|
||||
}
|
||||
case ITEM_ANVIL: return "Anvil";
|
||||
case ITEM_CHEST: return "Chest";
|
||||
case ITEM_OVEN: return "Oven";
|
||||
case ITEM_FURNACE: return "Furnace";
|
||||
case ITEM_WORKBENCH: return "Workbench";
|
||||
case ITEM_POTION_MAKER: return "Potion Maker";
|
||||
case ITEM_LANTERN: return "Lantern";
|
||||
case ITEM_POWGLOVE: return "Power Glove";
|
||||
case ITEM_FLOWER: sprintf(currentName,"%d Flower", 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_SAND: sprintf(currentName,"%d Sand", 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_ACORN: sprintf(currentName,"%d Acorn", 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_WHEAT: sprintf(currentName,"%d Wheat", 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_APPLE: sprintf(currentName,"%d Apple", countLevel); return currentName;
|
||||
case ITEM_LANTERN: return "Lantern";
|
||||
case ITEM_POWGLOVE: return "Power Glove";
|
||||
case ITEM_FLOWER: sprintf(currentName,"%d Flower", 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_SAND: sprintf(currentName,"%d Sand", 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_ACORN: sprintf(currentName,"%d Acorn", 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_WHEAT: sprintf(currentName,"%d Wheat", 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_APPLE: sprintf(currentName,"%d 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_SPEED_POTION: sprintf(currentName,"%d Speed 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_COAL: sprintf(currentName,"%d Coal", 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_IRONINGOT: sprintf(currentName,"%d Iron 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_GEM: sprintf(currentName,"%d Gem", countLevel); return currentName;
|
||||
case ITEM_SLIME: sprintf(currentName,"%d Slime", 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_GOLDORE: sprintf(currentName,"%d Gold ore", 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_GLASS: sprintf(currentName,"%d Glass", 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_LOOM: return "Loom";
|
||||
case ITEM_ENCHANTER: return "Enchanter";
|
||||
case ITEM_WALL_WOOD: sprintf(currentName,"%d Wood Wall", countLevel); return currentName;
|
||||
|
@ -190,93 +190,107 @@ char* getItemName(int itemID, int countLevel) {
|
|||
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_BOOKSHELVES: sprintf(currentName,"%d Bookshelves", 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_MAGIC_DUST: sprintf(currentName,"%d Magic Dust", countLevel); return currentName;
|
||||
case ITEM_COIN: sprintf(currentName,"%d Coins", countLevel); return currentName;
|
||||
case TOOL_BUCKET:
|
||||
switch(countLevel){
|
||||
case 1: return "Water Bucket";
|
||||
case 2: return "Lava Bucket";
|
||||
default: return "Empty Bucket";
|
||||
}
|
||||
case 1: return "Water Bucket";
|
||||
case 2: return "Lava Bucket";
|
||||
default: return "Empty Bucket";
|
||||
}
|
||||
case TOOL_BOW: return "Bow";
|
||||
case TOOL_MAGIC_COMPASS: return "Magic Compass";
|
||||
default: return ""; // null
|
||||
}
|
||||
case TOOL_MAGIC_COMPASS: return "Magic Compass";
|
||||
case TOOL_CLAYMORE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Claymore";
|
||||
case 2: return "Iron Claymore";
|
||||
case 3: return "Gold Claymore";
|
||||
case 4: return "Gem Claymore";
|
||||
default: return "Wood Claymore";
|
||||
}
|
||||
case ITEM_TORCH: return "Torch";
|
||||
case ITEM_BED: return "Bed";
|
||||
case ITEM_FISHING_ROD: return "Fishing Rod";
|
||||
case ITEM_SHEARS: return "Shears";
|
||||
case ITEM_FISH_RAW: sprintf(currentName,"%d Fish", countLevel); return currentName;
|
||||
case ITEM_FISH_COOKED: sprintf(currentName,"%d Cooked Fish", countLevel); return currentName;
|
||||
default: return ""; // null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char* getBasicItemName(int itemID, int countLevel) {
|
||||
switch(itemID){
|
||||
case TOOL_SHOVEL:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Shovel";
|
||||
case 2: return "Iron Shovel";
|
||||
case 3: return "Gold Shovel";
|
||||
case 4: return "Gem Shovel";
|
||||
default: return "Wood Shovel";
|
||||
}
|
||||
case TOOL_HOE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Hoe";
|
||||
case 2: return "Iron Hoe";
|
||||
case 3: return "Gold Hoe";
|
||||
case 4: return "Gem Hoe";
|
||||
default: return "Wood Hoe";
|
||||
}
|
||||
case TOOL_SWORD:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Sword";
|
||||
case 2: return "Iron Sword";
|
||||
case 3: return "Gold Sword";
|
||||
case 4: return "Gem Sword";
|
||||
default: return "Wood Sword";
|
||||
}
|
||||
case TOOL_PICKAXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Pickaxe";
|
||||
case 2: return "Iron Pickaxe";
|
||||
case 3: return "Gold Pickaxe";
|
||||
case 4: return "Gem Pickaxe";
|
||||
default: return "Wood Pickaxe";
|
||||
}
|
||||
case TOOL_AXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Axe";
|
||||
case 2: return "Iron Axe";
|
||||
case 3: return "Gold Axe";
|
||||
case 4: return "Gem Axe";
|
||||
default: return "Wood Axe";
|
||||
}
|
||||
case ITEM_ANVIL: return "Anvil";
|
||||
case ITEM_CHEST: return "Chest";
|
||||
case ITEM_OVEN: return "Oven";
|
||||
case ITEM_FURNACE: return "Furnace";
|
||||
case ITEM_WORKBENCH: return "Workbench";
|
||||
switch(itemID){
|
||||
case TOOL_SHOVEL:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Shovel";
|
||||
case 2: return "Iron Shovel";
|
||||
case 3: return "Gold Shovel";
|
||||
case 4: return "Gem Shovel";
|
||||
default: return "Wood Shovel";
|
||||
}
|
||||
case TOOL_HOE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Hoe";
|
||||
case 2: return "Iron Hoe";
|
||||
case 3: return "Gold Hoe";
|
||||
case 4: return "Gem Hoe";
|
||||
default: return "Wood Hoe";
|
||||
}
|
||||
case TOOL_SWORD:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Sword";
|
||||
case 2: return "Iron Sword";
|
||||
case 3: return "Gold Sword";
|
||||
case 4: return "Gem Sword";
|
||||
default: return "Wood Sword";
|
||||
}
|
||||
case TOOL_PICKAXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Pickaxe";
|
||||
case 2: return "Iron Pickaxe";
|
||||
case 3: return "Gold Pickaxe";
|
||||
case 4: return "Gem Pickaxe";
|
||||
default: return "Wood Pickaxe";
|
||||
}
|
||||
case TOOL_AXE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Axe";
|
||||
case 2: return "Iron Axe";
|
||||
case 3: return "Gold Axe";
|
||||
case 4: return "Gem Axe";
|
||||
default: return "Wood Axe";
|
||||
}
|
||||
case ITEM_ANVIL: return "Anvil";
|
||||
case ITEM_CHEST: return "Chest";
|
||||
case ITEM_OVEN: return "Oven";
|
||||
case ITEM_FURNACE: return "Furnace";
|
||||
case ITEM_WORKBENCH: return "Workbench";
|
||||
case ITEM_POTION_MAKER: return "Potion Maker";
|
||||
case ITEM_LANTERN: return "Lantern";
|
||||
case ITEM_POWGLOVE: return "Power Glove";
|
||||
case ITEM_FLOWER: return "Flower";
|
||||
case ITEM_WOOD: return "Wood";
|
||||
case ITEM_STONE: return "Stone";
|
||||
case ITEM_SAND: return "Sand";
|
||||
case ITEM_DIRT: return "Dirt";
|
||||
case ITEM_CLOUD: return "Cloud";
|
||||
case ITEM_ACORN: return "Acorn";
|
||||
case ITEM_CACTUS: return "Cactus";
|
||||
case ITEM_SEEDS: return "Seeds";
|
||||
case ITEM_WHEAT: return "Wheat";
|
||||
case ITEM_FLESH: return "Flesh";
|
||||
case ITEM_BREAD: return "Bread";
|
||||
case ITEM_APPLE: return "Apple";
|
||||
case ITEM_GOLD_APPLE: return "Gold Apple";
|
||||
case ITEM_COAL: return "Coal";
|
||||
case ITEM_IRONORE: return "Iron ore";
|
||||
case ITEM_GOLDORE: return "Gold ore";
|
||||
case ITEM_IRONINGOT: return "Iron ingot";
|
||||
case ITEM_GOLDINGOT: return "Gold ingot";
|
||||
case ITEM_GLASS: return "Glass";
|
||||
case ITEM_GEM: return "Gem";
|
||||
case ITEM_SLIME: return "Slime";
|
||||
|
||||
case ITEM_LANTERN: return "Lantern";
|
||||
case ITEM_POWGLOVE: return "Power Glove";
|
||||
case ITEM_FLOWER: return "Flower";
|
||||
case ITEM_WOOD: return "Wood";
|
||||
case ITEM_STONE: return "Stone";
|
||||
case ITEM_SAND: return "Sand";
|
||||
case ITEM_DIRT: return "Dirt";
|
||||
case ITEM_CLOUD: return "Cloud";
|
||||
case ITEM_ACORN: return "Acorn";
|
||||
case ITEM_CACTUS: return "Cactus";
|
||||
case ITEM_SEEDS: return "Seeds";
|
||||
case ITEM_WHEAT: return "Wheat";
|
||||
case ITEM_FLESH: return "Flesh";
|
||||
case ITEM_BREAD: return "Bread";
|
||||
case ITEM_APPLE: return "Apple";
|
||||
case ITEM_GOLD_APPLE: return "Gold Apple";
|
||||
case ITEM_COAL: return "Coal";
|
||||
case ITEM_IRONORE: return "Iron ore";
|
||||
case ITEM_GOLDORE: return "Gold ore";
|
||||
case ITEM_IRONINGOT: return "Iron ingot";
|
||||
case ITEM_GOLDINGOT: return "Gold ingot";
|
||||
case ITEM_GLASS: return "Glass";
|
||||
case ITEM_GEM: return "Gem";
|
||||
case ITEM_SLIME: return "Slime";
|
||||
|
||||
case ITEM_LOOM: return "Loom";
|
||||
case ITEM_ENCHANTER: return "Enchanter";
|
||||
case ITEM_WALL_WOOD: return "Wood Wall";
|
||||
|
@ -302,21 +316,35 @@ char* getBasicItemName(int itemID, int countLevel) {
|
|||
case ITEM_DRAGON_EGG: return "Dragon Egg";
|
||||
case ITEM_DRAGON_SCALE: return "Dragon Scale";
|
||||
case ITEM_BOOKSHELVES: return "Bookshelves";
|
||||
case ITEM_MAGIC_DUST: return "Magic Dust";
|
||||
case ITEM_COIN: return "Coin";
|
||||
case ITEM_MAGIC_DUST: return "Magic Dust";
|
||||
case ITEM_COIN: return "Coin";
|
||||
case ITEM_STRENGTH_POTION: return "Strength Potion";
|
||||
case ITEM_SPEED_POTION: return "Speed Potion";
|
||||
case ITEM_REGEN_POTION: return "Regen Potion";
|
||||
case ITEM_SWIM_BREATH_POTION: return "Water Potion";
|
||||
case TOOL_BUCKET:
|
||||
switch(countLevel){
|
||||
case 1: return "Water Bucket";
|
||||
case 2: return "Lava Bucket";
|
||||
default: return "Empty Bucket";
|
||||
}
|
||||
case 1: return "Water Bucket";
|
||||
case 2: return "Lava Bucket";
|
||||
default: return "Empty Bucket";
|
||||
}
|
||||
case TOOL_BOW: return "Bow";
|
||||
case TOOL_MAGIC_COMPASS: return "Magic Compass";
|
||||
default: return ""; // null
|
||||
}
|
||||
|
||||
case TOOL_MAGIC_COMPASS: return "Magic Compass";
|
||||
case TOOL_CLAYMORE:
|
||||
switch(countLevel){
|
||||
case 1: return "Rock Claymore";
|
||||
case 2: return "Iron Claymore";
|
||||
case 3: return "Gold Claymore";
|
||||
case 4: return "Gem Claymore";
|
||||
default: return "Wood Claymore";
|
||||
}
|
||||
case ITEM_TORCH: return "Torch";
|
||||
case ITEM_BED: return "Bed";
|
||||
case ITEM_FISHING_ROD: return "Fishing Rod";
|
||||
case ITEM_SHEARS: return "Shears";
|
||||
case ITEM_FISH_RAW: return "Fish";
|
||||
case ITEM_FISH_COOKED: return "Cooked Fish";
|
||||
default: return ""; // null
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
#define ITEM_LOOM 34
|
||||
#define ITEM_ENCHANTER 35
|
||||
#define ITEM_POTION_MAKER 36
|
||||
#define TOOL_CLAYMORE 37
|
||||
#define ITEM_TORCH 38
|
||||
#define ITEM_BED 39
|
||||
|
||||
#define ITEM_WALL_WOOD 51
|
||||
#define ITEM_WALL_STONE 52
|
||||
|
@ -77,27 +80,31 @@
|
|||
#define ITEM_SPEED_POTION 78
|
||||
#define ITEM_REGEN_POTION 79
|
||||
#define ITEM_SWIM_BREATH_POTION 80
|
||||
#define ITEM_FISH_RAW 81
|
||||
#define ITEM_FISH_COOKED 82
|
||||
|
||||
#define TOOL_BUCKET 101
|
||||
#define TOOL_BOW 102
|
||||
#define TOOL_MAGIC_COMPASS 103
|
||||
#define ITEM_FISHING_ROD 104
|
||||
#define ITEM_SHEARS 105
|
||||
|
||||
#define ARMOR_TEST 120
|
||||
|
||||
typedef struct Inventory Inventory;
|
||||
|
||||
typedef struct {
|
||||
s16 id;
|
||||
s16 countLevel; // Count for items, Level for tools.
|
||||
s16 slotNum; // Read-only. Do not mess with this.
|
||||
bool onlyOne;
|
||||
int* invPtr; // pointer to current inventory.
|
||||
Inventory * chestPtr; // pointer to chest inventory for chest item.
|
||||
s16 id;
|
||||
s16 countLevel; // Count for items, Level for tools.
|
||||
s16 slotNum; // Read-only. Do not mess with this.
|
||||
bool onlyOne;
|
||||
int* invPtr; // pointer to current inventory.
|
||||
Inventory * chestPtr; // pointer to chest inventory for chest item.
|
||||
} Item;
|
||||
|
||||
struct 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.
|
||||
Item items[300]; // Maximum of 300 slots in every inventory.
|
||||
s16 lastSlot; // lastSlot can also be used to read the size of the inventory.
|
||||
};
|
||||
|
||||
bool isItemEmpty(Item* item);
|
||||
|
|
817
source/MapGen.c
817
source/MapGen.c
File diff suppressed because it is too large
Load diff
|
@ -26,4 +26,4 @@ void createVillage(int w, int h, int level, u8 * map, u8 * data);
|
|||
void createDwarfHouse(int w, int h, int level, u8 * map, u8 * data);
|
||||
|
||||
bool hasNPC;
|
||||
void createDungeonRoom(int w, int h, bool dragon, int level, u8 * map, u8 * data);
|
||||
void createDungeonRoom(int w, int h, bool dragon, int level, u8 * map, u8 * data);
|
||||
|
|
2247
source/Menu.c
2247
source/Menu.c
File diff suppressed because it is too large
Load diff
|
@ -4,257 +4,257 @@ u8 pageNum = 0;
|
|||
u8 maxPageNum = 7;
|
||||
|
||||
u32 biasedCirclePad(u32 in){
|
||||
if(in & KEY_CPAD_UP) return KEY_CPAD_UP;
|
||||
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_RIGHT) return KEY_CPAD_RIGHT;
|
||||
else return (in & -in);
|
||||
if(in & KEY_CPAD_UP) return KEY_CPAD_UP;
|
||||
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_RIGHT) return KEY_CPAD_RIGHT;
|
||||
else return (in & -in);
|
||||
}
|
||||
|
||||
u32 biasedMenuXY(u32 in){
|
||||
if(in & KEY_X) return KEY_X;
|
||||
else if(in & KEY_Y) return KEY_Y;
|
||||
else return (in & -in);
|
||||
if(in & KEY_X) return KEY_X;
|
||||
else if(in & KEY_Y) return KEY_Y;
|
||||
else return (in & -in);
|
||||
}
|
||||
|
||||
/** Oh my god, this was so damn tedious to make. */
|
||||
void renderTutorialPage(bool topScreen){
|
||||
if(topScreen){
|
||||
drawTextColor("How to Play",(400-11*12)/2,12,0xFF00AFAF);
|
||||
switch(pageNum){
|
||||
case 0: // Moving the character
|
||||
drawTextColor("Movement",(400-8*12)/2,40,0xFF007FBF);
|
||||
drawText("Press to move up",92,90);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 164, 88, 1);
|
||||
drawText("Press to move down",80,120);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 152, 118, 1);
|
||||
drawText("Press to move left",80,150);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 152, 148, 1);
|
||||
drawText("Press to move right",74,180);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 146, 178, 1);
|
||||
break;
|
||||
case 1: // Attacking
|
||||
drawTextColor("Attacking",(400-9*12)/2,40,0xFF007FBF);
|
||||
drawText("Press to Attack",98,80);
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 168, 78, 1);
|
||||
drawText("Attack with an item to use it",26,120);
|
||||
drawText("Use the axe to cut down trees",26,140);
|
||||
drawText("Use the sword to attack enemies",14,160);
|
||||
drawText("Use the shovel to dig ground",32,180);
|
||||
drawText("Use the pickaxe to mine rock/ore",8,200);
|
||||
break;
|
||||
case 2: // Inventory
|
||||
drawTextColor("Inventory",(400-9*12)/2,40,0xFF007FBF);
|
||||
drawText("Press to open the menu",56,80);
|
||||
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 78, 1);
|
||||
drawText("Press to scroll up",80,110);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 152, 108, 1);
|
||||
drawText("Press to scroll down",68,140);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 140, 138, 1);
|
||||
drawText("Press to select an item",50,170);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 168, 1);
|
||||
drawText("Press to close the menu",50,200);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 120, 198, 1);
|
||||
break;
|
||||
case 3: // Furniture
|
||||
drawTextColor("Furniture",(400-9*12)/2,40,0xFF007FBF);
|
||||
drawText("Use furniture for item crafting",(400-31*12)/2,74);
|
||||
drawText("Press to open the menu",56,100);
|
||||
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 98, 1);
|
||||
drawText("while infront of the furniture",(400-30*12)/2,116);
|
||||
drawText("Use the lantern item to light",(400-29*12)/2,144);
|
||||
drawText("up underground areas",(400-20*12)/2,160);
|
||||
drawText("Use the power glove item to",(400-27*12)/2,184);
|
||||
drawText("pick up furniture",(400-17*12)/2,200);
|
||||
break;
|
||||
case 4: // Crafting
|
||||
drawTextColor("Crafting",(400-8*12)/2,40,0xFF007FBF);
|
||||
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("Press to open the menu",56,120);
|
||||
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 118, 1);
|
||||
drawText("Gather up the required materials",(400-32*12)/2,150);
|
||||
drawText("and then press to craft it",(400-28*12)/2,166);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 210, 164, 1);
|
||||
break;
|
||||
case 5: // Farming
|
||||
drawTextColor("Farming",(400-7*12)/2,40,0xFF007FBF);
|
||||
drawText("Grow wheat to make bread",(400-24*12)/2,74);
|
||||
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("Harvest wheat when it is yellow",(400-31*12)/2,134);
|
||||
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);
|
||||
break;
|
||||
case 6: // Mining
|
||||
drawTextColor("Mining",(400-6*12)/2,40,0xFF007FBF);
|
||||
drawText("Use a pickaxe tool for mining",(400-29*12)/2,74);
|
||||
drawText("Mine rocks for stone",(400-20*12)/2,94);
|
||||
drawText("Mine iron ore for iron",(400-22*12)/2,114);
|
||||
drawText("Mine gold ore for gold",(400-22*12)/2,134);
|
||||
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("make an ingot inside a furnace",(400-30*12)/2,210);
|
||||
break;
|
||||
if(topScreen){
|
||||
drawTextColor("How to Play",(400-11*12)/2,12,0xFF00AFAF);
|
||||
switch(pageNum){
|
||||
case 0: // Moving the character
|
||||
drawTextColor("Movement",(400-8*12)/2,40,0xFF007FBF);
|
||||
drawText("Press to move up",92,90);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 164, 88, 1);
|
||||
drawText("Press to move down",80,120);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 152, 118, 1);
|
||||
drawText("Press to move left",80,150);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 152, 148, 1);
|
||||
drawText("Press to move right",74,180);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 146, 178, 1);
|
||||
break;
|
||||
case 1: // Attacking
|
||||
drawTextColor("Attacking",(400-9*12)/2,40,0xFF007FBF);
|
||||
drawText("Press to Attack",98,80);
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 168, 78, 1);
|
||||
drawText("Attack with an item to use it",26,120);
|
||||
drawText("Use the axe to cut down trees",26,140);
|
||||
drawText("Use the sword to attack enemies",14,160);
|
||||
drawText("Use the shovel to dig ground",32,180);
|
||||
drawText("Use the pickaxe to mine rock/ore",8,200);
|
||||
break;
|
||||
case 2: // Inventory
|
||||
drawTextColor("Inventory",(400-9*12)/2,40,0xFF007FBF);
|
||||
drawText("Press to open the menu",56,80);
|
||||
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 78, 1);
|
||||
drawText("Press to scroll up",80,110);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 152, 108, 1);
|
||||
drawText("Press to scroll down",68,140);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 140, 138, 1);
|
||||
drawText("Press to select an item",50,170);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 120, 168, 1);
|
||||
drawText("Press to close the menu",50,200);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 120, 198, 1);
|
||||
break;
|
||||
case 3: // Furniture
|
||||
drawTextColor("Furniture",(400-9*12)/2,40,0xFF007FBF);
|
||||
drawText("Use furniture for item crafting",(400-31*12)/2,74);
|
||||
drawText("Press to open the menu",56,100);
|
||||
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 98, 1);
|
||||
drawText("while infront of the furniture",(400-30*12)/2,116);
|
||||
drawText("Use the lantern item to light",(400-29*12)/2,144);
|
||||
drawText("up underground areas",(400-20*12)/2,160);
|
||||
drawText("Use the power glove item to",(400-27*12)/2,184);
|
||||
drawText("pick up furniture",(400-17*12)/2,200);
|
||||
break;
|
||||
case 4: // Crafting
|
||||
drawTextColor("Crafting",(400-8*12)/2,40,0xFF007FBF);
|
||||
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("Press to open the menu",56,120);
|
||||
renderButtonIcon(biasedMenuXY(localInputs.k_menu.input), 126, 118, 1);
|
||||
drawText("Gather up the required materials",(400-32*12)/2,150);
|
||||
drawText("and then press to craft it",(400-28*12)/2,166);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 210, 164, 1);
|
||||
break;
|
||||
case 5: // Farming
|
||||
drawTextColor("Farming",(400-7*12)/2,40,0xFF007FBF);
|
||||
drawText("Grow wheat to make bread",(400-24*12)/2,74);
|
||||
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("Harvest wheat when it is yellow",(400-31*12)/2,134);
|
||||
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);
|
||||
break;
|
||||
case 6: // Mining
|
||||
drawTextColor("Mining",(400-6*12)/2,40,0xFF007FBF);
|
||||
drawText("Use a pickaxe tool for mining",(400-29*12)/2,74);
|
||||
drawText("Mine rocks for stone",(400-20*12)/2,94);
|
||||
drawText("Mine iron ore for iron",(400-22*12)/2,114);
|
||||
drawText("Mine gold ore for gold",(400-22*12)/2,134);
|
||||
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("make an ingot inside a furnace",(400-30*12)/2,210);
|
||||
break;
|
||||
case 7: // Potion Brewing
|
||||
drawTextColor("Brewing",(400-6*12)/2,40,0xFF007FBF);
|
||||
drawText("Create potions.",(400-13*12)/2,74);
|
||||
drawText("The potions give you abilities",(400-29*12)/2,94);
|
||||
drawText("Like speed and strength",(400-22*12)/2,114);
|
||||
drawText("They are hard to obtain",(400-22*12)/2,134);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(pageNum){
|
||||
case 0: // Moving the character
|
||||
render16(30,56,16,112,0);//Player up
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 30,40, 2);
|
||||
render16(60,56,0,112,0);//Player down
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 60,40, 2);
|
||||
render16(90,56,48,112,1);//Player left
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 90,40, 2);
|
||||
render16(120,56,48,112,0);//Player right
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 120,40, 2);
|
||||
break;
|
||||
case 1: // Attacking
|
||||
render16(60,56,0,112,0);//Player-down
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 80, 56, 2);
|
||||
renderc(60,68,16,160,16,8,2);//Slash
|
||||
|
||||
drawTextColor("Brewing",(400-6*12)/2,40,0xFF007FBF);
|
||||
drawText("Create potions.",(400-13*12)/2,74);
|
||||
drawText("The potions give you abilities",(400-29*12)/2,94);
|
||||
drawText("Like speed and strength",(400-22*12)/2,114);
|
||||
drawText("They are hard to obtain",(400-22*12)/2,134);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(pageNum){
|
||||
case 0: // Moving the character
|
||||
render16(30,56,16,112,0);//Player up
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 30,40, 2);
|
||||
render16(60,56,0,112,0);//Player down
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 60,40, 2);
|
||||
render16(90,56,48,112,1);//Player left
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_left.input), 90,40, 2);
|
||||
render16(120,56,48,112,0);//Player right
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_right.input), 120,40, 2);
|
||||
break;
|
||||
case 1: // Attacking
|
||||
render16(60,56,0,112,0);//Player-down
|
||||
renderButtonIcon(localInputs.k_attack.input & -localInputs.k_attack.input, 80, 56, 2);
|
||||
renderc(60,68,16,160,16,8,2);//Slash
|
||||
|
||||
menuRenderTilePit(12,20,256,0);// grass pit
|
||||
render16(12+8,20+4,256,48,0);//Tree
|
||||
renderc(12+9,20+14,16,160,16,8,0);//Slash
|
||||
render(12+9+4,20+14,192,144,0);//Axe
|
||||
render16(12+9,20+18,16,112,0);//Player-up
|
||||
|
||||
menuRenderTilePit(122,62,320,0);// sand pit
|
||||
render16(130,70,256,16,0);// hole
|
||||
render16(116,70,48,112,0);//Player-right
|
||||
renderb(136,76,16,152,0,sandColor);// Sand item
|
||||
renderc(128,70,40,160,8,16,0);//Slash
|
||||
render(130,74,0,144,0);//Shovel
|
||||
break;
|
||||
case 2: // Inventory
|
||||
renderFrame(4,4,17,11,0xFFFF1010);
|
||||
renderItemStuffWithText(ITEM_APPLE,5,false,80,78);
|
||||
renderItemStuffWithText(ITEM_SLIME,11,false,80,94);
|
||||
renderItemStuffWithText(TOOL_SWORD,4,true,80,110);
|
||||
renderItemStuffWithText(ITEM_IRONORE,3,false,80,126);
|
||||
renderItemStuffWithText(ITEM_IRONINGOT,11,false,80,142);
|
||||
sf2d_draw_rectangle(64, 110, 12, 12, 0xFF);
|
||||
drawText(">", 64, 110);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 44, 92, 1);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 44, 108, 1);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 44, 125, 1);
|
||||
break;
|
||||
case 3: // Furniture
|
||||
sf2d_draw_rectangle(64, 48, 192, 32, grassColor);
|
||||
renderc(32,24,64,128,96,16,0);//Furniture entities
|
||||
|
||||
renderFurniture(ITEM_WORKBENCH, 50,60);
|
||||
render16(50,46,0,112,0);//Player-down
|
||||
renderc(50,58,16,160,16,8,2);//Slash
|
||||
render(54,58,56,152,0);//Power glove
|
||||
|
||||
render16(92,56,0,128,0);//Player(Carrying)
|
||||
render16(92,44,128,128,0);//Workbench
|
||||
break;
|
||||
case 4: // Crafting
|
||||
renderFrame(11,3,19,6,0xFFFF1010);
|
||||
renderFrame(11,7,19,12,0xFFFF1010);
|
||||
renderFrame(1,3,10,12,0xFFFF1010);
|
||||
renderItemStuffWithText(TOOL_AXE,0,true,28,64);
|
||||
renderItemIcon(TOOL_AXE, 0, 94, 32);
|
||||
drawText("0", 206, 66);
|
||||
renderItemIcon(ITEM_WOOD, 0, 94, 64);
|
||||
drawText("16/5", 206, 130);
|
||||
break;
|
||||
case 5: // Farming (Bottom screen)
|
||||
renderc(24,16,352,48,112,16,0); // Wheat Stages
|
||||
|
||||
render16(20,40,352,48,0); // Farm Tile
|
||||
render16(36,40,448,48,0); // Wheat Tile
|
||||
render16(52,40,448,48,0); // Wheat Tile
|
||||
render16(20,54,16,112,0); // Player (Up)
|
||||
renderc(20,50,16,160,16,8,0); // Slash (Up)
|
||||
render(19,45,40,152,0); // Seeds
|
||||
render(26,39,48,152,0); // Wheat1
|
||||
render(29,44,48,152,0); // Wheat2
|
||||
|
||||
renderc(72,40,352,48,32,16,0); // Farm Tile + Seeded Wheat Tile
|
||||
render16(72,54,16,112,0); // Player (Up)
|
||||
renderc(72,50,16,160,16,8,0); // Slash (Up)
|
||||
render(76,48,40,152,0); // Seeds
|
||||
|
||||
sf2d_draw_rectangle(216, 80, 32, 32, dirtColor[1]); // Dirt color for grass
|
||||
render16(108, 40, 256, 0, 0); // Grass
|
||||
render16(124, 40,352,48,0); // Farm Tile
|
||||
render16(108,54,16,112,0); // Player (Up)
|
||||
renderc(108,50,16,160,16,8,0); // Slash (Up)
|
||||
render(112,48,72,144,0); // Gem Hoe
|
||||
|
||||
sf2d_draw_rectangle(112, 156, 32, 32, dirtColor[1]); // Dirt color for grass
|
||||
render16(56, 78, 256, 0, 0); // Grass
|
||||
sf2d_draw_rectangle(80, 156, 32, 32, dirtColor[1]); // Dirt color
|
||||
render16(40, 78, 336, 80, 0); // Dirt Dots
|
||||
render(44, 82, 40,152,0); // Seeds
|
||||
|
||||
render16(24,78,48,112,0); // Player (Right)
|
||||
renderc(36,78,40,160,8,16,0); // Slash (Right)
|
||||
render(38,82,32,144,0); // Gem Shovel
|
||||
|
||||
render(82,78,48,152,0); // Wheat
|
||||
render(90,78,48,152,0); // Wheat
|
||||
render(82,86,48,152,0); // Wheat
|
||||
render(90,86,48,152,0); // Wheat
|
||||
drawText(">",203,164);
|
||||
render16(108,76,96,128,0); // Oven
|
||||
drawText(">",246,164);
|
||||
render(132,82,72,152,0); // Bread
|
||||
break;
|
||||
case 6: //Mining
|
||||
render16(23,32,464,48,0); // iron ore
|
||||
render16(23,52,480,48,0); // gold ore
|
||||
render16(23,72,496,48,0); // gem ore
|
||||
renderb(41,38,88,152,0,ironColor); // Iron ore item
|
||||
renderb(41,58,88,152,0,goldColor); // Gold ore item
|
||||
render(41,78,112,152,0); // Gem item
|
||||
drawText(">",104,74);
|
||||
drawText(">",104,114);
|
||||
drawText(">",104,154);
|
||||
render16(60,32,112,128,0); // Furnace
|
||||
render16(60,52,112,128,0); // Furnace
|
||||
render16(60,72,240,128,0); // Enchanter
|
||||
drawText(">",160,74);
|
||||
drawText(">",160,114);
|
||||
drawText(">",160,154);
|
||||
renderb(88,36,96,152,0,ironColor); // Iron ingot item
|
||||
renderb(88,56,96,152,0,goldColor); // Gold ingot item
|
||||
renderb(88,76,152,144,0,goldColor); // Gem Pickaxe
|
||||
drawText(">",200,74);
|
||||
drawText(">",200,114);
|
||||
render16(106,32,64,128,0); // Anvil
|
||||
render16(106,52,64,128,0); // Anvil
|
||||
drawText(">",244,74);
|
||||
drawText(">",244,114);
|
||||
render(130,36,136,144,0); // Iron Pickaxe
|
||||
render(130,56,144,144,0); // Gold Pickaxe
|
||||
break;
|
||||
render16(12+8,20+4,256,48,0);//Tree
|
||||
renderc(12+9,20+14,16,160,16,8,0);//Slash
|
||||
render(12+9+4,20+14,192,144,0);//Axe
|
||||
render16(12+9,20+18,16,112,0);//Player-up
|
||||
|
||||
menuRenderTilePit(122,62,320,0);// sand pit
|
||||
render16(130,70,256,16,0);// hole
|
||||
render16(116,70,48,112,0);//Player-right
|
||||
renderb(136,76,16,152,0,sandColor);// Sand item
|
||||
renderc(128,70,40,160,8,16,0);//Slash
|
||||
render(130,74,0,144,0);//Shovel
|
||||
break;
|
||||
case 2: // Inventory
|
||||
renderFrame(4,4,17,11,0xFFFF1010);
|
||||
renderItemStuffWithText(ITEM_APPLE,5,false,80,78);
|
||||
renderItemStuffWithText(ITEM_SLIME,11,false,80,94);
|
||||
renderItemStuffWithText(TOOL_SWORD,4,true,80,110);
|
||||
renderItemStuffWithText(ITEM_IRONORE,3,false,80,126);
|
||||
renderItemStuffWithText(ITEM_IRONINGOT,11,false,80,142);
|
||||
sf2d_draw_rectangle(64, 110, 12, 12, 0xFF);
|
||||
drawText(">", 64, 110);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_up.input), 44, 92, 1);
|
||||
renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 44, 108, 1);
|
||||
renderButtonIcon(biasedCirclePad(localInputs.k_down.input), 44, 125, 1);
|
||||
break;
|
||||
case 3: // Furniture
|
||||
sf2d_draw_rectangle(64, 48, 192, 32, grassColor);
|
||||
renderc(32,24,64,128,96,16,0);//Furniture entities
|
||||
|
||||
renderFurniture(ITEM_WORKBENCH, 50,60);
|
||||
render16(50,46,0,112,0);//Player-down
|
||||
renderc(50,58,16,160,16,8,2);//Slash
|
||||
render(54,58,56,152,0);//Power glove
|
||||
|
||||
render16(92,56,0,128,0);//Player(Carrying)
|
||||
render16(92,44,128,128,0);//Workbench
|
||||
break;
|
||||
case 4: // Crafting
|
||||
renderFrame(11,3,19,6,0xFFFF1010);
|
||||
renderFrame(11,7,19,12,0xFFFF1010);
|
||||
renderFrame(1,3,10,12,0xFFFF1010);
|
||||
renderItemStuffWithText(TOOL_AXE,0,true,28,64);
|
||||
renderItemIcon(TOOL_AXE, 0, 94, 32);
|
||||
drawText("0", 206, 66);
|
||||
renderItemIcon(ITEM_WOOD, 0, 94, 64);
|
||||
drawText("16/5", 206, 130);
|
||||
break;
|
||||
case 5: // Farming (Bottom screen)
|
||||
renderc(24,16,352,48,112,16,0); // Wheat Stages
|
||||
|
||||
render16(20,40,352,48,0); // Farm Tile
|
||||
render16(36,40,448,48,0); // Wheat Tile
|
||||
render16(52,40,448,48,0); // Wheat Tile
|
||||
render16(20,54,16,112,0); // Player (Up)
|
||||
renderc(20,50,16,160,16,8,0); // Slash (Up)
|
||||
render(19,45,40,152,0); // Seeds
|
||||
render(26,39,48,152,0); // Wheat1
|
||||
render(29,44,48,152,0); // Wheat2
|
||||
|
||||
renderc(72,40,352,48,32,16,0); // Farm Tile + Seeded Wheat Tile
|
||||
render16(72,54,16,112,0); // Player (Up)
|
||||
renderc(72,50,16,160,16,8,0); // Slash (Up)
|
||||
render(76,48,40,152,0); // Seeds
|
||||
|
||||
sf2d_draw_rectangle(216, 80, 32, 32, dirtColor[1]); // Dirt color for grass
|
||||
render16(108, 40, 256, 0, 0); // Grass
|
||||
render16(124, 40,352,48,0); // Farm Tile
|
||||
render16(108,54,16,112,0); // Player (Up)
|
||||
renderc(108,50,16,160,16,8,0); // Slash (Up)
|
||||
render(112,48,72,144,0); // Gem Hoe
|
||||
|
||||
sf2d_draw_rectangle(112, 156, 32, 32, dirtColor[1]); // Dirt color for grass
|
||||
render16(56, 78, 256, 0, 0); // Grass
|
||||
sf2d_draw_rectangle(80, 156, 32, 32, dirtColor[1]); // Dirt color
|
||||
render16(40, 78, 336, 80, 0); // Dirt Dots
|
||||
render(44, 82, 40,152,0); // Seeds
|
||||
|
||||
render16(24,78,48,112,0); // Player (Right)
|
||||
renderc(36,78,40,160,8,16,0); // Slash (Right)
|
||||
render(38,82,32,144,0); // Gem Shovel
|
||||
|
||||
render(82,78,48,152,0); // Wheat
|
||||
render(90,78,48,152,0); // Wheat
|
||||
render(82,86,48,152,0); // Wheat
|
||||
render(90,86,48,152,0); // Wheat
|
||||
drawText(">",203,164);
|
||||
render16(108,76,96,128,0); // Oven
|
||||
drawText(">",246,164);
|
||||
render(132,82,72,152,0); // Bread
|
||||
break;
|
||||
case 6: //Mining
|
||||
render16(23,32,464,48,0); // iron ore
|
||||
render16(23,52,480,48,0); // gold ore
|
||||
render16(23,72,496,48,0); // gem ore
|
||||
renderb(41,38,88,152,0,ironColor); // Iron ore item
|
||||
renderb(41,58,88,152,0,goldColor); // Gold ore item
|
||||
render(41,78,112,152,0); // Gem item
|
||||
drawText(">",104,74);
|
||||
drawText(">",104,114);
|
||||
drawText(">",104,154);
|
||||
render16(60,32,112,128,0); // Furnace
|
||||
render16(60,52,112,128,0); // Furnace
|
||||
render16(60,72,240,128,0); // Enchanter
|
||||
drawText(">",160,74);
|
||||
drawText(">",160,114);
|
||||
drawText(">",160,154);
|
||||
renderb(88,36,96,152,0,ironColor); // Iron ingot item
|
||||
renderb(88,56,96,152,0,goldColor); // Gold ingot item
|
||||
renderb(88,76,152,144,0,goldColor); // Gem Pickaxe
|
||||
drawText(">",200,74);
|
||||
drawText(">",200,114);
|
||||
render16(106,32,64,128,0); // Anvil
|
||||
render16(106,52,64,128,0); // Anvil
|
||||
drawText(">",244,74);
|
||||
drawText(">",244,114);
|
||||
render(130,36,136,144,0); // Iron Pickaxe
|
||||
render(130,56,144,144,0); // Gold Pickaxe
|
||||
break;
|
||||
case 7: // Brewing
|
||||
render16(65, 56, 240, 96, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
drawText(pageText,(320-(strlen(pageText))*12)/2,12);
|
||||
if(pageNum > 0){
|
||||
drawText("<",2,16);
|
||||
renderButtonIcon(localInputs.k_menuPrev.input & -localInputs.k_menuPrev.input, 8, 2, 2);
|
||||
}
|
||||
if(pageNum < maxPageNum){
|
||||
drawText(">",306,16);
|
||||
renderButtonIcon(localInputs.k_menuNext.input & -localInputs.k_menuNext.input, 136, 2, 2);
|
||||
}
|
||||
drawText("Press to exit",(320-(15*12))/2,218);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 140, 216, 1);
|
||||
}
|
||||
render16(65, 56, 240, 96, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
drawText(pageText,(320-(strlen(pageText))*12)/2,12);
|
||||
if(pageNum > 0){
|
||||
drawText("<",2,16);
|
||||
renderButtonIcon(localInputs.k_menuPrev.input & -localInputs.k_menuPrev.input, 8, 2, 2);
|
||||
}
|
||||
if(pageNum < maxPageNum){
|
||||
drawText(">",306,16);
|
||||
renderButtonIcon(localInputs.k_menuNext.input & -localInputs.k_menuNext.input, 136, 2, 2);
|
||||
}
|
||||
drawText("Press to exit",(320-(15*12))/2,218);
|
||||
renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 140, 216, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <3ds.h>
|
||||
#include <string.h>
|
||||
#include <string.h>
|
||||
#include <sf2d.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
|
762
source/Network.c
762
source/Network.c
|
@ -46,211 +46,211 @@ void clearSendAckedBuffer();
|
|||
bool sendAck(u16 target, u16 ack);
|
||||
|
||||
void networkThreadMain(void *arg) {
|
||||
while(networkRunThread) {
|
||||
if(udsRunning && isConnected) {
|
||||
networkUpdateStatus();
|
||||
networkHandleRecieve();
|
||||
networkHandleSend();
|
||||
}
|
||||
|
||||
//TODO: Set meaningfull value, WARNING: Setting this near 1ms (1000*1000) will make everything super laggy, higher values actually work better!
|
||||
svcSleepThread(10000 * 1000);
|
||||
}
|
||||
while(networkRunThread) {
|
||||
if(udsRunning && isConnected) {
|
||||
networkUpdateStatus();
|
||||
networkHandleRecieve();
|
||||
networkHandleSend();
|
||||
}
|
||||
|
||||
//TODO: Set meaningfull value, WARNING: Setting this near 1ms (1000*1000) will make everything super laggy, higher values actually work better!
|
||||
svcSleepThread(10000 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void networkUpdateStatus() {
|
||||
/*for(int i=0; i<10; i++) {
|
||||
Result ret = udsGetConnectionStatus(&networkStatus);
|
||||
if(!R_FAILED(ret)) {
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
if(udsWaitConnectionStatusEvent(false, false)) {
|
||||
udsGetConnectionStatus(&networkStatus);
|
||||
}
|
||||
/*for(int i=0; i<10; i++) {
|
||||
Result ret = udsGetConnectionStatus(&networkStatus);
|
||||
if(!R_FAILED(ret)) {
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
if(udsWaitConnectionStatusEvent(false, false)) {
|
||||
udsGetConnectionStatus(&networkStatus);
|
||||
}
|
||||
}
|
||||
|
||||
void networkHandleRecieve() {
|
||||
bool recieved = false;
|
||||
do {
|
||||
recieved = false;
|
||||
|
||||
size_t actualSize = 0;
|
||||
bool recieved = false;
|
||||
do {
|
||||
recieved = false;
|
||||
|
||||
size_t actualSize = 0;
|
||||
u16 sourceNetworkNodeID;
|
||||
u32 ackToSend = 0;
|
||||
|
||||
u32 ackToSend = 0;
|
||||
|
||||
memset(networkBuffer, 0, networkBufferSize);
|
||||
|
||||
|
||||
Result ret = udsPullPacket(&networkBindCtx, networkBuffer, networkBufferSize, &actualSize, &sourceNetworkNodeID);
|
||||
if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
|
||||
|
||||
//actualSize will be 0 if no packet is available
|
||||
} else if(actualSize) {
|
||||
void *readPointer = networkBuffer;
|
||||
|
||||
//ack frame
|
||||
if(actualSize==sizeof(u16)) {
|
||||
networkSeqSendConf[sourceNetworkNodeID] = *((u16*) readPointer);
|
||||
clearSendAckedBuffer();
|
||||
//normal frame
|
||||
} else {
|
||||
while(actualSize>0) {
|
||||
//read seqID and size
|
||||
u16 seqID = *((u16*) readPointer);
|
||||
readPointer += sizeof(u16);
|
||||
actualSize -= sizeof(u16);
|
||||
|
||||
u16 size = *((u16*) readPointer);
|
||||
readPointer += sizeof(u16);
|
||||
actualSize -= sizeof(u16);
|
||||
|
||||
//if the seq id was expected handle the packet
|
||||
u32 nextID = networkSeqRecvLast[sourceNetworkNodeID]+1;
|
||||
if(seqID==nextID) {
|
||||
networkSeqRecvLast[sourceNetworkNodeID] = seqID;
|
||||
ackToSend = seqID;
|
||||
|
||||
//handle data - TODO: WARNING: Do not send sizeof(u16) packets or else they will get confused with this one
|
||||
if(size==sizeof(u16)) {
|
||||
networkConnectedMask = *((u16*) readPointer);
|
||||
} else {
|
||||
processPacket(readPointer, size);
|
||||
}
|
||||
} else if(seqID<=nextID-1) {
|
||||
ackToSend = nextID-1;
|
||||
}
|
||||
readPointer += size;
|
||||
actualSize -= size;
|
||||
}
|
||||
|
||||
if(ackToSend!=0) {
|
||||
if(sendAck(sourceNetworkNodeID, ackToSend)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recieved = true;
|
||||
}
|
||||
} while(recieved);
|
||||
void *readPointer = networkBuffer;
|
||||
|
||||
//ack frame
|
||||
if(actualSize==sizeof(u16)) {
|
||||
networkSeqSendConf[sourceNetworkNodeID] = *((u16*) readPointer);
|
||||
clearSendAckedBuffer();
|
||||
//normal frame
|
||||
} else {
|
||||
while(actualSize>0) {
|
||||
//read seqID and size
|
||||
u16 seqID = *((u16*) readPointer);
|
||||
readPointer += sizeof(u16);
|
||||
actualSize -= sizeof(u16);
|
||||
|
||||
u16 size = *((u16*) readPointer);
|
||||
readPointer += sizeof(u16);
|
||||
actualSize -= sizeof(u16);
|
||||
|
||||
//if the seq id was expected handle the packet
|
||||
u16 nextID = networkGetExpectedSeqFrom(sourceNetworkNodeID);
|
||||
if(seqID==nextID) {
|
||||
networkSeqRecvLast[sourceNetworkNodeID] = seqID;
|
||||
ackToSend = seqID;
|
||||
|
||||
//handle data - TODO: WARNING: Do not send sizeof(u16) packets or else they will get confused with this one
|
||||
if(size==sizeof(u16)) {
|
||||
networkConnectedMask = *((u16*) readPointer);
|
||||
} else {
|
||||
processPacket(readPointer, size);
|
||||
}
|
||||
} else if(networkSeqIsLowerThan(seqID, nextID)) {
|
||||
ackToSend = seqID;
|
||||
}
|
||||
readPointer += size;
|
||||
actualSize -= size;
|
||||
}
|
||||
|
||||
if(ackToSend!=0) {
|
||||
if(sendAck(sourceNetworkNodeID, ackToSend)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recieved = true;
|
||||
}
|
||||
} while(recieved);
|
||||
}
|
||||
|
||||
void networkHandleSend() {
|
||||
if(networkSendBufferStartPos!=networkSendBufferEndPos) {
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
|
||||
//determine send size
|
||||
size_t currentSize = 0;
|
||||
while(networkSendBufferStartPos+currentSize<networkSendBufferWrapPos && networkSendBufferStartPos+currentSize!=networkSendBufferEndPos) {
|
||||
//size of "header info" (seqid,size)
|
||||
size_t extraSize = sizeof(u16) + sizeof(u16);
|
||||
//data size
|
||||
extraSize += *((u16*) ((networkSendBuffer+networkSendBufferStartPos+currentSize) + sizeof(u16)));
|
||||
|
||||
//if next packet can fit in frame include it
|
||||
if(currentSize+extraSize < UDS_DATAFRAME_MAXSIZE) {
|
||||
currentSize += extraSize;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//send frame
|
||||
if(currentSize>0) {
|
||||
//TODO: Once we have our own custom mask, no longer broadcast, but send directly because bcast doesn't always reach everyone?
|
||||
if(networkConnectedMask==0) {
|
||||
//send frame
|
||||
Result ret = udsSendTo(UDS_BROADCAST_NETWORKNODEID, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize);
|
||||
if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
|
||||
//TODO: what do?
|
||||
} else if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
}
|
||||
} else {
|
||||
for(int i=1; i<=UDS_MAXNODES; i++) {
|
||||
if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) {
|
||||
//send frame
|
||||
Result ret = udsSendTo(i, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize);
|
||||
if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
|
||||
//TODO: what do?
|
||||
} else if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
}
|
||||
if(networkSendBufferStartPos!=networkSendBufferEndPos) {
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
|
||||
//determine send size
|
||||
size_t currentSize = 0;
|
||||
while(networkSendBufferStartPos+currentSize<networkSendBufferWrapPos && networkSendBufferStartPos+currentSize!=networkSendBufferEndPos) {
|
||||
//size of "header info" (seqid,size)
|
||||
size_t extraSize = sizeof(u16) + sizeof(u16);
|
||||
//data size
|
||||
extraSize += *((u16*) ((networkSendBuffer+networkSendBufferStartPos+currentSize) + sizeof(u16)));
|
||||
|
||||
//if next packet can fit in frame include it
|
||||
if(currentSize+extraSize < UDS_DATAFRAME_MAXSIZE) {
|
||||
currentSize += extraSize;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//send frame
|
||||
if(currentSize>0) {
|
||||
//TODO: Once we have our own custom mask, no longer broadcast, but send directly because bcast doesn't always reach everyone?
|
||||
if(networkConnectedMask==0) {
|
||||
//send frame
|
||||
Result ret = udsSendTo(UDS_BROADCAST_NETWORKNODEID, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize);
|
||||
if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
|
||||
//TODO: what do?
|
||||
} else if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
}
|
||||
} else {
|
||||
for(int i=1; i<=UDS_MAXNODES; i++) {
|
||||
if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) {
|
||||
//send frame
|
||||
Result ret = udsSendTo(i, NETWORK_CHANNEL, UDS_SENDFLAG_Default, networkSendBuffer+networkSendBufferStartPos, currentSize);
|
||||
if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
|
||||
//TODO: what do?
|
||||
} else if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
}
|
||||
}
|
||||
|
||||
void clearSendAckedBuffer() {
|
||||
//find last ack recieved from all com partners
|
||||
u16 ackID = 0;
|
||||
for(int i=1; i<=UDS_MAXNODES; i++) {
|
||||
if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) {
|
||||
if(networkSeqSendConf[i]==0) {
|
||||
ackID = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ackID==0) {
|
||||
ackID = networkSeqSendConf[i];
|
||||
} else if(networkSeqSendConf[i]<100) {
|
||||
if(ackID > networkSeqSendConf[i] && ackID<65535-100) ackID = networkSeqSendConf[i];
|
||||
} else if(networkSeqSendConf[i]>65535-100) {
|
||||
if(ackID > networkSeqSendConf[i] || ackID<100) ackID = networkSeqSendConf[i];
|
||||
} else {
|
||||
if(ackID > networkSeqSendConf[i]) ackID = networkSeqSendConf[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ackID==0) return;
|
||||
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
|
||||
//clear buffer of acknowledgt packets
|
||||
while(networkSendBufferStartPos!=networkSendBufferEndPos) {
|
||||
//find current seqid and size
|
||||
u16 seqID = *((u16*) (networkSendBuffer+networkSendBufferStartPos));
|
||||
u16 size = *((u16*) (networkSendBuffer+networkSendBufferStartPos+sizeof(u16)));
|
||||
|
||||
if(seqID<=ackID || (ackID<100 && seqID>65535-100)) {
|
||||
|
||||
size_t currentSize = sizeof(u16)*2 + size;
|
||||
|
||||
//adjust buffer "pointers"
|
||||
networkSendBufferStartPos += currentSize;
|
||||
if(networkSendBufferStartPos==networkSendBufferEndPos) {
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferEndPos = 0;
|
||||
networkSendBufferWrapPos = 0;
|
||||
}
|
||||
|
||||
//wrap
|
||||
if(networkSendBufferStartPos==networkSendBufferWrapPos) {
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferWrapPos = networkSendBufferEndPos;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
//find last ack recieved from all com partners
|
||||
u16 ackID = 0;
|
||||
for(int i=1; i<=UDS_MAXNODES; i++) {
|
||||
if(i!=networkGetLocalNodeID()/* && networkIsNodeConnected(i)*/ && networkConnectedMask & (1 << (i-1))) {
|
||||
if(networkSeqSendConf[i]==0) {
|
||||
ackID = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(ackID==0) {
|
||||
ackID = networkSeqSendConf[i];
|
||||
} else if(networkSeqSendConf[i]<100) {
|
||||
if(ackID > networkSeqSendConf[i] && ackID<65535-100) ackID = networkSeqSendConf[i];
|
||||
} else if(networkSeqSendConf[i]>65535-100) {
|
||||
if(ackID > networkSeqSendConf[i] || ackID<100) ackID = networkSeqSendConf[i];
|
||||
} else {
|
||||
if(ackID > networkSeqSendConf[i]) ackID = networkSeqSendConf[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ackID==0) return;
|
||||
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
|
||||
//clear buffer of acknowledgt packets
|
||||
while(networkSendBufferStartPos!=networkSendBufferEndPos) {
|
||||
//find current seqid and size
|
||||
u16 seqID = *((u16*) (networkSendBuffer+networkSendBufferStartPos));
|
||||
u16 size = *((u16*) (networkSendBuffer+networkSendBufferStartPos+sizeof(u16)));
|
||||
|
||||
if(seqID<=ackID || (ackID<100 && seqID>65535-100)) {
|
||||
|
||||
size_t currentSize = sizeof(u16)*2 + size;
|
||||
|
||||
//adjust buffer "pointers"
|
||||
networkSendBufferStartPos += currentSize;
|
||||
if(networkSendBufferStartPos==networkSendBufferEndPos) {
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferEndPos = 0;
|
||||
networkSendBufferWrapPos = 0;
|
||||
}
|
||||
|
||||
//wrap
|
||||
if(networkSendBufferStartPos==networkSendBufferWrapPos) {
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferWrapPos = networkSendBufferEndPos;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
}
|
||||
|
||||
bool sendAck(u16 target, u16 ack) {
|
||||
Result ret = udsSendTo(target, NETWORK_CHANNEL, UDS_SENDFLAG_Default, &ack, sizeof(u16));
|
||||
if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
|
||||
//TODO: what do?
|
||||
return false;
|
||||
} else if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
Result ret = udsSendTo(target, NETWORK_CHANNEL, UDS_SENDFLAG_Default, &ack, sizeof(u16));
|
||||
if(UDS_CHECK_SENDTO_FATALERROR(ret)) {
|
||||
//TODO: what do?
|
||||
return false;
|
||||
} else if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void networkInit() {
|
||||
|
@ -259,87 +259,87 @@ void networkInit() {
|
|||
udsRunning = false;
|
||||
} else {
|
||||
udsRunning = true;
|
||||
|
||||
|
||||
scannedNetworksCount = 0;
|
||||
scannedNetworks = NULL;
|
||||
isConnected = false;
|
||||
isServer = false;
|
||||
networkConnectedMask = 0;
|
||||
networkConnectedMask = 0;
|
||||
|
||||
networkWriteBuffer = malloc(NETWORK_MAXDATASIZE);
|
||||
if(networkWriteBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
networkBufferSize = 0x4000;
|
||||
networkWriteBuffer = malloc(NETWORK_MAXDATASIZE);
|
||||
if(networkWriteBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
networkBufferSize = 0x4000;
|
||||
networkBuffer = malloc(networkBufferSize);
|
||||
if(networkBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferEndPos = 0;
|
||||
networkSendBufferWrapPos = 0;
|
||||
networkSendBuffer = malloc(NETWORK_SENDBUFFERSIZE);
|
||||
if(networkSendBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
networkSeqSendNext = 1;
|
||||
for(int i=0; i<UDS_MAXNODES+1; i++) {
|
||||
networkSeqSendConf[i] = 0;
|
||||
networkSeqRecvLast[i] = 0;
|
||||
}
|
||||
|
||||
networkAckBuffer = malloc(sizeof(u16)+sizeof(u16)+sizeof(u16));
|
||||
if(networkAckBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
LightLock_Init(&sendBufferLock);
|
||||
|
||||
s32 prio = 0;
|
||||
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
|
||||
networkRunThread = true;
|
||||
networkThread = threadCreate(networkThreadMain, NULL, NETWORK_STACKSIZE, prio-1, -2, false);
|
||||
if(networkBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferEndPos = 0;
|
||||
networkSendBufferWrapPos = 0;
|
||||
networkSendBuffer = malloc(NETWORK_SENDBUFFERSIZE);
|
||||
if(networkSendBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
networkSeqSendNext = 1;
|
||||
for(int i=0; i<UDS_MAXNODES+1; i++) {
|
||||
networkSeqSendConf[i] = 0;
|
||||
networkSeqRecvLast[i] = 0;
|
||||
}
|
||||
|
||||
networkAckBuffer = malloc(sizeof(u16)+sizeof(u16)+sizeof(u16));
|
||||
if(networkAckBuffer==NULL) {
|
||||
networkExit();
|
||||
return;
|
||||
}
|
||||
|
||||
LightLock_Init(&sendBufferLock);
|
||||
|
||||
s32 prio = 0;
|
||||
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
|
||||
networkRunThread = true;
|
||||
networkThread = threadCreate(networkThreadMain, NULL, NETWORK_STACKSIZE, prio-1, -2, false);
|
||||
}
|
||||
}
|
||||
|
||||
void networkExit() {
|
||||
//Additionally to shutting down the service, clear any left over memory!
|
||||
if(udsRunning) {
|
||||
udsRunning = false;
|
||||
|
||||
if(networkRunThread) {
|
||||
networkRunThread = false;
|
||||
threadJoin(networkThread, U64_MAX);
|
||||
threadFree(networkThread);
|
||||
}
|
||||
|
||||
udsRunning = false;
|
||||
|
||||
if(networkRunThread) {
|
||||
networkRunThread = false;
|
||||
threadJoin(networkThread, U64_MAX);
|
||||
threadFree(networkThread);
|
||||
}
|
||||
|
||||
//cleanup any dynamically reserved memory
|
||||
if(scannedNetworks!=NULL) free(scannedNetworks);
|
||||
scannedNetworks = NULL;
|
||||
|
||||
if(networkWriteBuffer!=NULL) free(networkWriteBuffer);
|
||||
networkWriteBuffer = NULL;
|
||||
|
||||
|
||||
if(networkWriteBuffer!=NULL) free(networkWriteBuffer);
|
||||
networkWriteBuffer = NULL;
|
||||
|
||||
if(networkBuffer!=NULL) free(networkBuffer);
|
||||
networkBuffer = NULL;
|
||||
|
||||
if(networkSendBuffer!=NULL) free(networkSendBuffer);
|
||||
networkSendBuffer = NULL;
|
||||
|
||||
if(networkAckBuffer!=NULL) free(networkAckBuffer);
|
||||
networkAckBuffer = NULL;
|
||||
|
||||
networkBuffer = NULL;
|
||||
|
||||
if(networkSendBuffer!=NULL) free(networkSendBuffer);
|
||||
networkSendBuffer = NULL;
|
||||
|
||||
if(networkAckBuffer!=NULL) free(networkAckBuffer);
|
||||
networkAckBuffer = NULL;
|
||||
|
||||
networkDisconnect();
|
||||
|
||||
|
||||
udsExit();
|
||||
}
|
||||
}
|
||||
|
@ -355,17 +355,17 @@ bool networkAvailable() {
|
|||
bool networkHost() {
|
||||
if(udsRunning && !isConnected) {
|
||||
udsGenerateDefaultNetworkStruct(&networkStruct, NETWORK_WLANCOMMID, 0, NETWORK_MAXPLAYERS);
|
||||
|
||||
|
||||
Result ret = udsCreateNetwork(&networkStruct, NETWORK_PASSPHRASE, strlen(NETWORK_PASSPHRASE)+1, &networkBindCtx, NETWORK_CHANNEL, NETWORK_RECVBUFSIZE);
|
||||
if(R_FAILED(ret)) {
|
||||
return false;
|
||||
} else {
|
||||
if(udsWaitConnectionStatusEvent(false, false)) {}
|
||||
udsGetConnectionStatus(&networkStatus);
|
||||
udsSetNewConnectionsBlocked(false, true, false);
|
||||
if(udsWaitConnectionStatusEvent(false, false)) {}
|
||||
udsGetConnectionStatus(&networkStatus);
|
||||
udsSetNewConnectionsBlocked(false, true, false);
|
||||
isConnected = true;
|
||||
isServer = true;
|
||||
networkConnectedMask = 0;
|
||||
networkConnectedMask = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -373,7 +373,7 @@ bool networkHost() {
|
|||
}
|
||||
|
||||
void networkHostStopConnections() {
|
||||
udsSetNewConnectionsBlocked(true, true, false);
|
||||
udsSetNewConnectionsBlocked(true, true, false);
|
||||
}
|
||||
|
||||
void networkScan() {
|
||||
|
@ -382,7 +382,7 @@ void networkScan() {
|
|||
if(scannedNetworks!=NULL) free(scannedNetworks);
|
||||
scannedNetworks = NULL;
|
||||
scannedNetworksCount = 0;
|
||||
|
||||
|
||||
//scan
|
||||
memset(networkBuffer, 0, networkBufferSize);
|
||||
Result ret = udsScanBeacons(networkBuffer, networkBufferSize, &scannedNetworks, &scannedNetworksCount, NETWORK_WLANCOMMID, 0, NULL, isConnected);
|
||||
|
@ -404,7 +404,7 @@ int networkGetScanCount() {
|
|||
bool networkGetScanName(char *name, int pos) {
|
||||
if(udsRunning) {
|
||||
if(pos<0 || pos>=scannedNetworksCount) return false;
|
||||
|
||||
|
||||
Result ret = udsGetNodeInfoUsername(&(scannedNetworks[pos].nodes[0]), name);
|
||||
if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
|
@ -418,16 +418,16 @@ bool networkGetScanName(char *name, int pos) {
|
|||
bool networkConnect(int pos) {
|
||||
if(udsRunning && !isConnected) {
|
||||
if(pos<0 || pos>=scannedNetworksCount) return false;
|
||||
|
||||
|
||||
Result ret = udsConnectNetwork(&scannedNetworks[pos].network, NETWORK_PASSPHRASE, strlen(NETWORK_PASSPHRASE)+1, &networkBindCtx, UDS_BROADCAST_NETWORKNODEID, UDSCONTYPE_Client, NETWORK_CHANNEL, NETWORK_RECVBUFSIZE);
|
||||
if(R_FAILED(ret)) {
|
||||
return false;
|
||||
} else {
|
||||
if(udsWaitConnectionStatusEvent(false, false)) {}
|
||||
udsGetConnectionStatus(&networkStatus);
|
||||
if(udsWaitConnectionStatusEvent(false, false)) {}
|
||||
udsGetConnectionStatus(&networkStatus);
|
||||
isConnected = true;
|
||||
isServer = false;
|
||||
networkConnectedMask = 0;
|
||||
networkConnectedMask = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -438,25 +438,25 @@ void networkDisconnect() {
|
|||
//For clients this just means disconnect, for the server it means destroy the network
|
||||
if(udsRunning && isConnected) {
|
||||
isConnected = false;
|
||||
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
//reset send buffer
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferEndPos = 0;
|
||||
networkSendBufferWrapPos = 0;
|
||||
|
||||
//reset ack status
|
||||
networkSeqSendNext = 1;
|
||||
for(int i=0; i<UDS_MAXNODES+1; i++) {
|
||||
networkSeqSendConf[i] = 0;
|
||||
networkSeqRecvLast[i] = 0;
|
||||
}
|
||||
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
|
||||
svcSleepThread(220000 * 1000); //HACK: prevent citra crash (>20*networkthreadsleep) (wait unti no more stuff gets send)
|
||||
|
||||
//TODO
|
||||
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
//reset send buffer
|
||||
networkSendBufferStartPos = 0;
|
||||
networkSendBufferEndPos = 0;
|
||||
networkSendBufferWrapPos = 0;
|
||||
|
||||
//reset ack status
|
||||
networkSeqSendNext = 1;
|
||||
for(int i=0; i<UDS_MAXNODES+1; i++) {
|
||||
networkSeqSendConf[i] = 0;
|
||||
networkSeqRecvLast[i] = 0;
|
||||
}
|
||||
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
|
||||
svcSleepThread(220000 * 1000); //HACK: prevent citra crash (>20*networkthreadsleep) (wait unti no more stuff gets send)
|
||||
|
||||
//TODO
|
||||
if(isServer) {
|
||||
//TODO: Clients need to cleanup too, how can I tell they got disconnected
|
||||
udsDestroyNetwork();
|
||||
|
@ -464,59 +464,59 @@ void networkDisconnect() {
|
|||
udsDisconnectNetwork();
|
||||
}
|
||||
udsUnbind(&networkBindCtx);
|
||||
|
||||
|
||||
isServer = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void networkStart() {
|
||||
//TODO: This sends the node_bitmask from server to everyone else, because it is uncorrect on some clients?
|
||||
if(udsRunning && isConnected && isServer) {
|
||||
void *buffer = networkWriteBuffer;
|
||||
|
||||
*((u16*) buffer) = networkStatus.node_bitmask;
|
||||
networkConnectedMask = networkStatus.node_bitmask;
|
||||
|
||||
networkSend(networkWriteBuffer, sizeof(u16));
|
||||
networkSendWaitFlush();
|
||||
}
|
||||
//TODO: This sends the node_bitmask from server to everyone else, because it is uncorrect on some clients?
|
||||
if(udsRunning && isConnected && isServer) {
|
||||
void *buffer = networkWriteBuffer;
|
||||
|
||||
*((u16*) buffer) = networkStatus.node_bitmask;
|
||||
networkConnectedMask = networkStatus.node_bitmask;
|
||||
|
||||
networkSend(networkWriteBuffer, sizeof(u16));
|
||||
networkSendWaitFlush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool networkConnected() {
|
||||
return isConnected;
|
||||
}
|
||||
}
|
||||
|
||||
int networkGetNodeCount() {
|
||||
if(udsRunning && isConnected) {
|
||||
return networkStatus.total_nodes;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if(udsRunning && isConnected) {
|
||||
return networkStatus.total_nodes;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u16 networkGetLocalNodeID() {
|
||||
if(udsRunning && isConnected) {
|
||||
return networkStatus.cur_NetworkNodeID;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if(udsRunning && isConnected) {
|
||||
return networkStatus.cur_NetworkNodeID;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool networkIsNodeConnected(u16 id) {
|
||||
if(udsRunning && isConnected) {
|
||||
return networkStatus.node_bitmask & (1 << (id-1));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if(udsRunning && isConnected) {
|
||||
return networkStatus.node_bitmask & (1 << (id-1));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool networkGetNodeName(u16 id, char *name) {
|
||||
if(udsRunning && isConnected && networkIsNodeConnected(id)) {
|
||||
udsNodeInfo nodeInfo;
|
||||
udsGetNodeInformation(id, &nodeInfo);
|
||||
|
||||
if(udsRunning && isConnected && networkIsNodeConnected(id)) {
|
||||
udsNodeInfo nodeInfo;
|
||||
udsGetNodeInformation(id, &nodeInfo);
|
||||
|
||||
Result ret = udsGetNodeInfoUsername(&nodeInfo, name);
|
||||
if(R_FAILED(ret)) {
|
||||
//TODO: what do?
|
||||
|
@ -527,76 +527,94 @@ bool networkGetNodeName(u16 id, char *name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
u16 networkGetExpectedSeqFrom(u16 id) {
|
||||
u16 nextID = networkSeqRecvLast[id];
|
||||
nextID += 1;
|
||||
if(nextID==0) {
|
||||
nextID = 1;
|
||||
}
|
||||
return nextID;
|
||||
}
|
||||
|
||||
bool networkSeqIsLowerThan(u16 firstID, u16 secondID) {
|
||||
if (secondID < 100) {
|
||||
return (firstID < secondID) || (firstID > 65536-100);
|
||||
} else if (secondID > 65536-100) {
|
||||
return (firstID < secondID) && (firstID > 100);
|
||||
} else {
|
||||
return (firstID < secondID);
|
||||
}
|
||||
}
|
||||
|
||||
int fitInSendBuffer(size_t size) {
|
||||
//add "header" length
|
||||
size += sizeof(u16)*2;
|
||||
|
||||
//we have no wrap currently
|
||||
if(networkSendBufferStartPos<=networkSendBufferEndPos) {
|
||||
//and can fit without wrap
|
||||
if(networkSendBufferEndPos+size<NETWORK_SENDBUFFERSIZE) {
|
||||
networkSendBufferEndPos += size;
|
||||
networkSendBufferWrapPos = networkSendBufferEndPos;
|
||||
|
||||
return networkSendBufferEndPos-size;
|
||||
//we need to wrap
|
||||
} else {
|
||||
if(size<networkSendBufferStartPos) {
|
||||
networkSendBufferEndPos = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//we have wrap currently
|
||||
} else {
|
||||
int available = networkSendBufferStartPos - networkSendBufferEndPos - 1;
|
||||
if(available>size) {
|
||||
networkSendBufferEndPos += size;
|
||||
|
||||
return networkSendBufferEndPos-size;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
//add "header" length
|
||||
size += sizeof(u16)*2;
|
||||
|
||||
//we have no wrap currently
|
||||
if(networkSendBufferStartPos<=networkSendBufferEndPos) {
|
||||
//and can fit without wrap
|
||||
if(networkSendBufferEndPos+size<NETWORK_SENDBUFFERSIZE) {
|
||||
networkSendBufferEndPos += size;
|
||||
networkSendBufferWrapPos = networkSendBufferEndPos;
|
||||
|
||||
return networkSendBufferEndPos-size;
|
||||
//we need to wrap
|
||||
} else {
|
||||
if(size<networkSendBufferStartPos) {
|
||||
networkSendBufferEndPos = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//we have wrap currently
|
||||
} else {
|
||||
int available = networkSendBufferStartPos - networkSendBufferEndPos - 1;
|
||||
if(available>size) {
|
||||
networkSendBufferEndPos += size;
|
||||
|
||||
return networkSendBufferEndPos-size;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
int pos = fitInSendBuffer(size);
|
||||
while(pos==-1) {
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
svcSleepThread(4500 * 1000); //TODO: Set meaningfull value
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
|
||||
pos = fitInSendBuffer(size);
|
||||
}
|
||||
|
||||
//fit found -> space is allready "reserved" -> write packet to buffer
|
||||
void *writePointer = networkSendBuffer + pos;
|
||||
|
||||
//write seq number
|
||||
*((u16*) writePointer) = networkSeqSendNext;
|
||||
networkSeqSendNext++;
|
||||
if(networkSeqSendNext==0) {
|
||||
networkSeqSendNext = 1;
|
||||
}
|
||||
writePointer += sizeof(u16);
|
||||
|
||||
//write size
|
||||
*((u16*) writePointer) = (u16) size;
|
||||
writePointer += sizeof(u16);
|
||||
|
||||
//write data
|
||||
memcpy(writePointer, packet, size);
|
||||
writePointer += size;
|
||||
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
int pos = fitInSendBuffer(size);
|
||||
while(pos==-1) {
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
svcSleepThread(4500 * 1000); //TODO: Set meaningfull value
|
||||
LightLock_Lock(&sendBufferLock);
|
||||
|
||||
pos = fitInSendBuffer(size);
|
||||
}
|
||||
|
||||
//fit found -> space is allready "reserved" -> write packet to buffer
|
||||
void *writePointer = networkSendBuffer + pos;
|
||||
|
||||
//write seq number
|
||||
*((u16*) writePointer) = networkSeqSendNext;
|
||||
networkSeqSendNext++;
|
||||
if(networkSeqSendNext==0) {
|
||||
networkSeqSendNext = 1;
|
||||
}
|
||||
writePointer += sizeof(u16);
|
||||
|
||||
//write size
|
||||
*((u16*) writePointer) = (u16) size;
|
||||
writePointer += sizeof(u16);
|
||||
|
||||
//write data
|
||||
memcpy(writePointer, packet, size);
|
||||
writePointer += size;
|
||||
|
||||
LightLock_Unlock(&sendBufferLock);
|
||||
}
|
||||
|
||||
void networkSendWaitFlush() {
|
||||
while(networkSendBufferStartPos!=networkSendBufferEndPos) {
|
||||
svcSleepThread(4500 * 1000);
|
||||
}
|
||||
while(networkSendBufferStartPos!=networkSendBufferEndPos) {
|
||||
svcSleepThread(4500 * 1000);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,5 +40,8 @@ u16 networkGetLocalNodeID();
|
|||
bool networkIsNodeConnected(u16 id);
|
||||
bool networkGetNodeName(u16 id, char *name);
|
||||
|
||||
u16 networkGetExpectedSeqFrom(u16 id);
|
||||
bool networkSeqIsLowerThan(u16 firstID, u16 secondID);
|
||||
|
||||
void networkSend(void *packet, size_t size);
|
||||
void networkSendWaitFlush();
|
||||
|
|
|
@ -5,359 +5,353 @@
|
|||
FILE *recvFile;
|
||||
size_t recvFileSize;
|
||||
|
||||
|
||||
|
||||
|
||||
void * writeBool(void *buffer, size_t *size, bool value) {
|
||||
*((bool*) buffer) = value;
|
||||
*(size) += sizeof(bool);
|
||||
return buffer + sizeof(bool);
|
||||
*((bool*) buffer) = value;
|
||||
*(size) += sizeof(bool);
|
||||
return buffer + sizeof(bool);
|
||||
}
|
||||
|
||||
void * writeU8(void *buffer, size_t *size, u8 value) {
|
||||
*((u8*) buffer) = value;
|
||||
*(size) += sizeof(u8);
|
||||
return buffer + sizeof(u8);
|
||||
*((u8*) buffer) = value;
|
||||
*(size) += sizeof(u8);
|
||||
return buffer + sizeof(u8);
|
||||
}
|
||||
|
||||
void * writeU16(void *buffer, size_t *size, u16 value) {
|
||||
*((u16*) buffer) = value;
|
||||
*(size) += sizeof(u16);
|
||||
return buffer + sizeof(u16);
|
||||
*((u16*) buffer) = value;
|
||||
*(size) += sizeof(u16);
|
||||
return buffer + sizeof(u16);
|
||||
}
|
||||
|
||||
void * writeU32(void *buffer, size_t *size, u32 value) {
|
||||
*((u32*) buffer) = value;
|
||||
*(size) += sizeof(u32);
|
||||
return buffer + sizeof(u32);
|
||||
*((u32*) buffer) = value;
|
||||
*(size) += sizeof(u32);
|
||||
return buffer + sizeof(u32);
|
||||
}
|
||||
|
||||
void * writeSizeT(void *buffer, size_t *size, size_t value) {
|
||||
*((size_t*) buffer) = value;
|
||||
*(size) += sizeof(size_t);
|
||||
return buffer + sizeof(size_t);
|
||||
*((size_t*) buffer) = value;
|
||||
*(size) += sizeof(size_t);
|
||||
return buffer + sizeof(size_t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void * readBool(void *buffer, size_t *size, bool *value) {
|
||||
*value = *((bool*) buffer);
|
||||
*(size) -= sizeof(bool);
|
||||
return buffer + sizeof(bool);
|
||||
*value = *((bool*) buffer);
|
||||
*(size) -= sizeof(bool);
|
||||
return buffer + sizeof(bool);
|
||||
}
|
||||
|
||||
void * readU8(void *buffer, size_t *size, u8 *value) {
|
||||
*value = *((u8*) buffer);
|
||||
*(size) -= sizeof(u8);
|
||||
return buffer + sizeof(u8);
|
||||
*value = *((u8*) buffer);
|
||||
*(size) -= sizeof(u8);
|
||||
return buffer + sizeof(u8);
|
||||
}
|
||||
|
||||
void * readU16(void *buffer, size_t *size, u16 *value) {
|
||||
*value = *((u16*) buffer);
|
||||
*(size) -= sizeof(u16);
|
||||
return buffer + sizeof(u16);
|
||||
*value = *((u16*) buffer);
|
||||
*(size) -= sizeof(u16);
|
||||
return buffer + sizeof(u16);
|
||||
}
|
||||
|
||||
void * readU32(void *buffer, size_t *size, u32 *value) {
|
||||
*value = *((u32*) buffer);
|
||||
*(size) -= sizeof(u32);
|
||||
return buffer + sizeof(u32);
|
||||
*value = *((u32*) buffer);
|
||||
*(size) -= sizeof(u32);
|
||||
return buffer + sizeof(u32);
|
||||
}
|
||||
|
||||
void * readSizeT(void *buffer, size_t *size, size_t *value) {
|
||||
*value = *((size_t*) buffer);
|
||||
*(size) -= sizeof(size_t);
|
||||
return buffer + sizeof(size_t);
|
||||
*value = *((size_t*) buffer);
|
||||
*(size) -= sizeof(size_t);
|
||||
return buffer + sizeof(size_t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void processPacket(void *packet, size_t size) {
|
||||
//Differenciate the packets and process them
|
||||
switch(packetGetID(packet)) {
|
||||
case PACKET_START: {
|
||||
void *buffer = packetGetDataStart(packet);
|
||||
size = packetGetDataSize(size);
|
||||
|
||||
//find player index based on network node id
|
||||
//and set player uuid in synchronizer
|
||||
u32 seed;
|
||||
u32 playerCount = 1;
|
||||
int playerIndex = 0;
|
||||
|
||||
buffer = readU32(buffer, &size, &seed);
|
||||
buffer = readU32(buffer, &size, &playerCount);
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
u16 nodeID;
|
||||
|
||||
buffer = readU16(buffer, &size, &nodeID);
|
||||
|
||||
if(nodeID==networkGetLocalNodeID()) {
|
||||
playerIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup transfer tmp file
|
||||
FILE *file = fopen("tmpTransfer.bin", "wb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
remove("tmpTransfer.bin");
|
||||
}
|
||||
|
||||
//init synchronizer
|
||||
synchronizerInit(seed, playerCount, playerIndex);
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKET_START_FILEHEADER: {
|
||||
void *data = packetGetDataStart(packet);
|
||||
|
||||
u8 type;
|
||||
u8 id;
|
||||
size_t fsize;
|
||||
|
||||
data = readU8(data, &size, &type);
|
||||
data = readU8(data, &size, &id);
|
||||
data = readSizeT(data, &size, &fsize);
|
||||
|
||||
recvFile = fopen("tmpTransfer.bin", "wb");
|
||||
recvFileSize = fsize;
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKET_START_FILEDATA: {
|
||||
void *data = packetGetDataStart(packet);
|
||||
size_t dsize = packetGetDataSize(size);
|
||||
|
||||
size_t toread = dsize;
|
||||
|
||||
fwrite(data, 1, toread, recvFile);
|
||||
|
||||
recvFileSize -= toread;
|
||||
if(recvFileSize<=0) {
|
||||
fclose(recvFile);
|
||||
recvFile = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKET_START_REQUEST_IDS: {
|
||||
synchronizerSendUID();
|
||||
break;
|
||||
}
|
||||
case PACKET_START_ID: {
|
||||
u8 playerID = packetGetSender(packet);
|
||||
u32 uid;
|
||||
|
||||
void *data = packetGetDataStart(packet);
|
||||
size_t dsize = packetGetDataSize(size);
|
||||
|
||||
data = readU32(data, &dsize, &uid);
|
||||
|
||||
synchronizerSetPlayerUID(playerID, uid);
|
||||
synchronizerSendIfReady();
|
||||
break;
|
||||
}
|
||||
case PACKET_START_READY: {
|
||||
synchronizerSetPlayerReady(packetGetSender(packet));
|
||||
if(playerLocalID==0) {
|
||||
if(synchronizerAllReady()) {
|
||||
sendStartSyncPacket();
|
||||
synchronizerStart(); //server needs to call this here, all others do when they recieve the packet
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_TURN_START: {
|
||||
synchronizerStart();
|
||||
break;
|
||||
}
|
||||
case PACKET_TURN_INPUT: {
|
||||
synchronizerOnInputPacket(packetGetSender(packet), packetGetTurn(packet), packetGetDataStart(packet), packetGetDataSize(size));
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Differenciate the packets and process them
|
||||
switch(packetGetID(packet)) {
|
||||
case PACKET_START: {
|
||||
void *buffer = packetGetDataStart(packet);
|
||||
size = packetGetDataSize(size);
|
||||
|
||||
//find player index based on network node id
|
||||
//and set player uuid in synchronizer
|
||||
u32 seed;
|
||||
u32 playerCount = 1;
|
||||
int playerIndex = 0;
|
||||
|
||||
buffer = readU32(buffer, &size, &seed);
|
||||
buffer = readU32(buffer, &size, &playerCount);
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
u16 nodeID;
|
||||
|
||||
buffer = readU16(buffer, &size, &nodeID);
|
||||
|
||||
if(nodeID==networkGetLocalNodeID()) {
|
||||
playerIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup transfer tmp file
|
||||
FILE *file = fopen("tmpTransfer.bin", "wb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
remove("tmpTransfer.bin");
|
||||
}
|
||||
|
||||
//init synchronizer
|
||||
synchronizerInit(seed, playerCount, playerIndex);
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKET_START_FILEHEADER: {
|
||||
void *data = packetGetDataStart(packet);
|
||||
|
||||
u8 type;
|
||||
u8 id;
|
||||
size_t fsize;
|
||||
|
||||
data = readU8(data, &size, &type);
|
||||
data = readU8(data, &size, &id);
|
||||
data = readSizeT(data, &size, &fsize);
|
||||
|
||||
recvFile = fopen("tmpTransfer.bin", "wb");
|
||||
recvFileSize = fsize;
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKET_START_FILEDATA: {
|
||||
void *data = packetGetDataStart(packet);
|
||||
size_t dsize = packetGetDataSize(size);
|
||||
|
||||
size_t toread = dsize;
|
||||
|
||||
fwrite(data, 1, toread, recvFile);
|
||||
|
||||
recvFileSize -= toread;
|
||||
if(recvFileSize<=0) {
|
||||
fclose(recvFile);
|
||||
recvFile = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKET_START_REQUEST_IDS: {
|
||||
synchronizerSendUID();
|
||||
break;
|
||||
}
|
||||
case PACKET_START_ID: {
|
||||
u8 playerID = packetGetSender(packet);
|
||||
u32 uid;
|
||||
|
||||
void *data = packetGetDataStart(packet);
|
||||
size_t dsize = packetGetDataSize(size);
|
||||
|
||||
data = readU32(data, &dsize, &uid);
|
||||
|
||||
synchronizerSetPlayerUID(playerID, uid);
|
||||
synchronizerSendIfReady();
|
||||
break;
|
||||
}
|
||||
case PACKET_START_READY: {
|
||||
synchronizerSetPlayerReady(packetGetSender(packet));
|
||||
if(playerLocalID==0) {
|
||||
if(synchronizerAllReady()) {
|
||||
sendStartSyncPacket();
|
||||
synchronizerStart(); //server needs to call this here, all others do when they recieve the packet
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_TURN_START: {
|
||||
synchronizerStart();
|
||||
break;
|
||||
}
|
||||
case PACKET_TURN_INPUT: {
|
||||
synchronizerOnInputPacket(packetGetSender(packet), packetGetTurn(packet), packetGetDataStart(packet), packetGetDataSize(size));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 packetGetID(void *packet) {
|
||||
return *((u8*) packet);
|
||||
return *((u8*) packet);
|
||||
}
|
||||
|
||||
u8 packetGetSender(void *packet) {
|
||||
return *((u8*) packet+sizeof(u8));
|
||||
return *((u8*) packet+sizeof(u8));
|
||||
}
|
||||
|
||||
u32 packetGetTurn(void *packet) {
|
||||
return *((u32*) (packet+sizeof(u8)+sizeof(u8)));
|
||||
return *((u32*) (packet+sizeof(u8)+sizeof(u8)));
|
||||
}
|
||||
|
||||
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) {
|
||||
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 size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
buffer = writeU32(buffer, &size, seed);
|
||||
buffer = writeU32(buffer, &size, (u32)networkGetNodeCount());
|
||||
for(int i=1; i<=UDS_MAXNODES; i++) {
|
||||
if(networkIsNodeConnected(i)) {
|
||||
buffer = writeU16(buffer, &size, (u16)i);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
size_t size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
buffer = writeU32(buffer, &size, seed);
|
||||
buffer = writeU32(buffer, &size, (u32)networkGetNodeCount());
|
||||
for(int i=1; i<=UDS_MAXNODES; i++) {
|
||||
if(networkIsNodeConnected(i)) {
|
||||
buffer = writeU16(buffer, &size, (u16)i);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t writeStartRequestPacket(void *buffer) {
|
||||
size_t size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START_REQUEST_IDS);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
return size;
|
||||
size_t size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START_REQUEST_IDS);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t writeInputPacket(void *buffer, Inputs *inputs, u8 playerID, u32 turnNumber) {
|
||||
size_t size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_TURN_INPUT);
|
||||
buffer = writeU8(buffer, &size, playerID);
|
||||
buffer = writeU32(buffer, &size, turnNumber);
|
||||
|
||||
buffer = writeU16(buffer, &size, inputs->k_touch.px);
|
||||
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_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_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_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_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_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_menuPrev.down); buffer = writeBool(buffer, &size, inputs->k_menuPrev.clicked);
|
||||
|
||||
return size;
|
||||
size_t size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_TURN_INPUT);
|
||||
buffer = writeU8(buffer, &size, playerID);
|
||||
buffer = writeU32(buffer, &size, turnNumber);
|
||||
|
||||
buffer = writeU16(buffer, &size, inputs->k_touch.px);
|
||||
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_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_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_pickup.down); buffer = writeBool(buffer, &size, inputs->k_pickup.clicked);
|
||||
buffer = writeBool(buffer, &size, inputs->k_use.down); buffer = writeBool(buffer, &size, inputs->k_use.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_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_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_menuPrev.down); buffer = writeBool(buffer, &size, inputs->k_menuPrev.clicked);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool readInputPacketData(void *buffer, size_t size, Inputs *inputs) {
|
||||
buffer = readU16(buffer, &size, &(inputs->k_touch.px));
|
||||
if(size<=0) return false;
|
||||
buffer = readU16(buffer, &size, &(inputs->k_touch.py));
|
||||
if(size<=0) return false;
|
||||
|
||||
buffer = readBool(buffer, &size, &(inputs->k_up.down)); buffer = readBool(buffer, &size, &(inputs->k_up.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_down.down)); buffer = readBool(buffer, &size, &(inputs->k_down.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_left.down)); buffer = readBool(buffer, &size, &(inputs->k_left.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_right.down)); buffer = readBool(buffer, &size, &(inputs->k_right.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_attack.down)); buffer = readBool(buffer, &size, &(inputs->k_attack.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_menu.down)); buffer = readBool(buffer, &size, &(inputs->k_menu.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_pause.down)); buffer = readBool(buffer, &size, &(inputs->k_pause.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_accept.down)); buffer = readBool(buffer, &size, &(inputs->k_accept.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_decline.down)); buffer = readBool(buffer, &size, &(inputs->k_decline.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_delete.down)); buffer = readBool(buffer, &size, &(inputs->k_delete.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_menuNext.down)); buffer = readBool(buffer, &size, &(inputs->k_menuNext.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_menuPrev.down)); buffer = readBool(buffer, &size, &(inputs->k_menuPrev.clicked));
|
||||
buffer = readU16(buffer, &size, &(inputs->k_touch.px));
|
||||
if(size<=0) return false;
|
||||
buffer = readU16(buffer, &size, &(inputs->k_touch.py));
|
||||
if(size<=0) return false;
|
||||
|
||||
return size==0;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_up.down)); buffer = readBool(buffer, &size, &(inputs->k_up.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_down.down)); buffer = readBool(buffer, &size, &(inputs->k_down.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_left.down)); buffer = readBool(buffer, &size, &(inputs->k_left.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_right.down)); buffer = readBool(buffer, &size, &(inputs->k_right.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_attack.down)); buffer = readBool(buffer, &size, &(inputs->k_attack.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_pickup.down)); buffer = readBool(buffer, &size, &(inputs->k_pickup.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_use.down)); buffer = readBool(buffer, &size, &(inputs->k_use.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_menu.down)); buffer = readBool(buffer, &size, &(inputs->k_menu.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_pause.down)); buffer = readBool(buffer, &size, &(inputs->k_pause.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_accept.down)); buffer = readBool(buffer, &size, &(inputs->k_accept.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_decline.down)); buffer = readBool(buffer, &size, &(inputs->k_decline.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_delete.down)); buffer = readBool(buffer, &size, &(inputs->k_delete.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_menuNext.down)); buffer = readBool(buffer, &size, &(inputs->k_menuNext.clicked));
|
||||
if(size<=0) return false;
|
||||
buffer = readBool(buffer, &size, &(inputs->k_menuPrev.down)); buffer = readBool(buffer, &size, &(inputs->k_menuPrev.clicked));
|
||||
|
||||
return size==0;
|
||||
}
|
||||
|
||||
void sendFile(FILE *file, u8 fileType, u8 id) {
|
||||
fseek(file, 0, SEEK_END); // seek to end of file
|
||||
size_t fsize = ftell(file); // get current file pointer
|
||||
fseek(file, 0, SEEK_SET); // seek back to beginning of file
|
||||
|
||||
//send file header
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START_FILEHEADER);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
buffer = writeU8(buffer, &size, fileType);
|
||||
buffer = writeU8(buffer, &size, id);
|
||||
buffer = writeSizeT(buffer, &size, fsize);
|
||||
networkSend(networkWriteBuffer, size);
|
||||
|
||||
//send file data
|
||||
while(fsize>0) {
|
||||
buffer = networkWriteBuffer;
|
||||
size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START_FILEDATA);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
//read file data
|
||||
size_t towrite = NETWORK_MAXDATASIZE - size;
|
||||
if(towrite>fsize) towrite = fsize;
|
||||
|
||||
fread(buffer, 1, towrite, file);
|
||||
|
||||
size += towrite;
|
||||
fsize -= towrite;
|
||||
|
||||
//send file data
|
||||
networkSend(networkWriteBuffer, size);
|
||||
}
|
||||
fseek(file, 0, SEEK_END); // seek to end of file
|
||||
size_t fsize = ftell(file); // get current file pointer
|
||||
fseek(file, 0, SEEK_SET); // seek back to beginning of file
|
||||
|
||||
//send file header
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START_FILEHEADER);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
buffer = writeU8(buffer, &size, fileType);
|
||||
buffer = writeU8(buffer, &size, id);
|
||||
buffer = writeSizeT(buffer, &size, fsize);
|
||||
networkSend(networkWriteBuffer, size);
|
||||
|
||||
//send file data
|
||||
while(fsize>0) {
|
||||
buffer = networkWriteBuffer;
|
||||
size = 0;
|
||||
buffer = writeU8(buffer, &size, PACKET_START_FILEDATA);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
//read file data
|
||||
size_t towrite = NETWORK_MAXDATASIZE - size;
|
||||
if(towrite>fsize) towrite = fsize;
|
||||
|
||||
fread(buffer, 1, towrite, file);
|
||||
|
||||
size += towrite;
|
||||
fsize -= towrite;
|
||||
|
||||
//send file data
|
||||
networkSend(networkWriteBuffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
void sendIDPacket(u8 playerID, u32 uid) {
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
|
||||
buffer = writeU8(buffer, &size, PACKET_START_ID);
|
||||
buffer = writeU8(buffer, &size, playerID);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
buffer = writeU32(buffer, &size, uid);
|
||||
|
||||
networkSend(networkWriteBuffer, size);
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
|
||||
buffer = writeU8(buffer, &size, PACKET_START_ID);
|
||||
buffer = writeU8(buffer, &size, playerID);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
buffer = writeU32(buffer, &size, uid);
|
||||
|
||||
networkSend(networkWriteBuffer, size);
|
||||
}
|
||||
|
||||
void sendStartReadyPacket(u8 playerID) {
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
|
||||
buffer = writeU8(buffer, &size, PACKET_START_READY);
|
||||
buffer = writeU8(buffer, &size, playerID);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
networkSend(networkWriteBuffer, size);
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
|
||||
buffer = writeU8(buffer, &size, PACKET_START_READY);
|
||||
buffer = writeU8(buffer, &size, playerID);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
networkSend(networkWriteBuffer, size);
|
||||
}
|
||||
|
||||
void sendStartSyncPacket() {
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
|
||||
buffer = writeU8(buffer, &size, PACKET_TURN_START);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
networkSend(networkWriteBuffer, size);
|
||||
void *buffer = networkWriteBuffer;
|
||||
size_t size = 0;
|
||||
|
||||
buffer = writeU8(buffer, &size, PACKET_TURN_START);
|
||||
buffer = writeU8(buffer, &size, 0);
|
||||
buffer = writeU32(buffer, &size, 0);
|
||||
|
||||
networkSend(networkWriteBuffer, size);
|
||||
}
|
||||
|
|
752
source/Player.c
752
source/Player.c
|
@ -19,15 +19,15 @@ void potionEffect(int type) {
|
|||
}
|
||||
|
||||
void initPlayers() {
|
||||
for(int i=0; i<MAX_PLAYERS; i++) {
|
||||
initPlayer(players+i);
|
||||
}
|
||||
for(int i=0; i<MAX_PLAYERS; i++) {
|
||||
initPlayer(players+i);
|
||||
}
|
||||
}
|
||||
|
||||
void freePlayers() {
|
||||
for(int i=0; i<MAX_PLAYERS; i++) {
|
||||
freePlayer(players+i);
|
||||
}
|
||||
for(int i=0; i<MAX_PLAYERS; i++) {
|
||||
freePlayer(players+i);
|
||||
}
|
||||
}
|
||||
|
||||
void playerInitMiniMapData(u8 *minimapData) {
|
||||
|
@ -38,287 +38,286 @@ void playerInitMiniMapData(u8 *minimapData) {
|
|||
}
|
||||
|
||||
void playerInitEntity(PlayerData *pd) {
|
||||
pd->entity.type = ENTITY_PLAYER;
|
||||
pd->entity.level = 1;
|
||||
pd->entity.xr = 4;
|
||||
pd->entity.yr = 3;
|
||||
pd->entity.canSwim = true;
|
||||
pd->entity.p.ax = 0;
|
||||
pd->entity.p.ay = 0;
|
||||
pd->entity.p.health = 10;
|
||||
pd->entity.p.stamina = 10;
|
||||
pd->entity.p.walkDist = 0;
|
||||
pd->entity.p.attackTimer = 0;
|
||||
pd->entity.p.dir = 0;
|
||||
pd->entity.p.isDead = false;
|
||||
pd->entity.p.hasWon = false;
|
||||
|
||||
pd->entity.p.data = pd;
|
||||
pd->entity.type = ENTITY_PLAYER;
|
||||
pd->entity.level = 1;
|
||||
pd->entity.xr = 4;
|
||||
pd->entity.yr = 3;
|
||||
pd->entity.canSwim = true;
|
||||
pd->entity.p.ax = 0;
|
||||
pd->entity.p.ay = 0;
|
||||
pd->entity.p.health = 10;
|
||||
pd->entity.p.stamina = 10;
|
||||
pd->entity.p.walkDist = 0;
|
||||
pd->entity.p.attackTimer = 0;
|
||||
pd->entity.p.dir = 0;
|
||||
pd->entity.p.isDead = false;
|
||||
pd->entity.p.hasWon = false;
|
||||
|
||||
pd->entity.p.data = pd;
|
||||
}
|
||||
|
||||
void playerInitInventory(PlayerData *pd) {
|
||||
//reset inventory
|
||||
pd->inventory.lastSlot = 0;
|
||||
pd->activeItem = &noItem;
|
||||
|
||||
addItemToInventory(newItem(ITEM_WORKBENCH,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_POWGLOVE,0), &(pd->inventory));
|
||||
|
||||
if(shouldRenderDebug && playerCount < 1) {
|
||||
//reset inventory
|
||||
pd->inventory.lastSlot = 0;
|
||||
pd->activeItem = &noItem;
|
||||
|
||||
if(shouldRenderDebug && playerCount < 2) {
|
||||
addItemToInventory(newItem(ITEM_POWGLOVE,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_WORKBENCH,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_GOLD_APPLE,1), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_STRENGTH_POTION,1), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_REGEN_POTION,1), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_SWIM_BREATH_POTION,1), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_SPEED_POTION,1), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_POTION_MAKER,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_SHOVEL,1), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_HOE,4), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_SWORD,4), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_PICKAXE,4), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_AXE,4), &(pd->inventory));
|
||||
|
||||
addItemToInventory(newItem(ITEM_ANVIL,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_CHEST,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_OVEN,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_FURNACE,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_LANTERN,0), &(pd->inventory));
|
||||
|
||||
addItemToInventory(newItem(TOOL_MAGIC_COMPASS,1), &(pd->inventory));
|
||||
|
||||
int i;
|
||||
for (i = 7;i < 28;++i) addItemToInventory(newItem(i,50), &(pd->inventory));
|
||||
}
|
||||
addItemToInventory(newItem(TOOL_SHOVEL,1), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_HOE,4), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_SWORD,4), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_PICKAXE,4), &(pd->inventory));
|
||||
addItemToInventory(newItem(TOOL_AXE,4), &(pd->inventory));
|
||||
|
||||
addItemToInventory(newItem(ITEM_ANVIL,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_CHEST,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_OVEN,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_FURNACE,0), &(pd->inventory));
|
||||
addItemToInventory(newItem(ITEM_LANTERN,0), &(pd->inventory));
|
||||
|
||||
addItemToInventory(newItem(TOOL_MAGIC_COMPASS,1), &(pd->inventory));
|
||||
|
||||
int i;
|
||||
for (i = 7;i < 28;++i) addItemToInventory(newItem(i,50), &(pd->inventory));
|
||||
}
|
||||
}
|
||||
|
||||
void playerInitSprite(PlayerData *pd) {
|
||||
pd->sprite.choosen = false;
|
||||
|
||||
pd->sprite.legs = 0;
|
||||
pd->sprite.body = 0;
|
||||
pd->sprite.arms = 0;
|
||||
pd->sprite.head = 0;
|
||||
pd->sprite.eyes = 0;
|
||||
pd->sprite.choosen = false;
|
||||
|
||||
pd->sprite.legs = 0;
|
||||
pd->sprite.body = 0;
|
||||
pd->sprite.arms = 0;
|
||||
pd->sprite.head = 0;
|
||||
pd->sprite.eyes = 0;
|
||||
}
|
||||
|
||||
void playerInitMenus(PlayerData *pd) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->ingameMenuSelection = 0;
|
||||
pd->ingameMenuInvSel = 0;
|
||||
pd->ingameMenuInvSelOther = 0;
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
pd->ingameMenuTimer = 0;
|
||||
|
||||
resetNPCMenuData(&(pd->npcMenuData));
|
||||
|
||||
pd->mapShouldRender = false;
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
pd->ingameMenuSelection = 0;
|
||||
pd->ingameMenuInvSel = 0;
|
||||
pd->ingameMenuInvSelOther = 0;
|
||||
pd->ingameMenuAreYouSure = false;
|
||||
pd->ingameMenuAreYouSureSave = false;
|
||||
pd->ingameMenuTimer = 0;
|
||||
|
||||
resetNPCMenuData(&(pd->npcMenuData));
|
||||
|
||||
pd->mapShouldRender = false;
|
||||
pd->mapScrollX = 0;
|
||||
pd->mapScrollY = 0;
|
||||
pd->mapZoomLevel = 2;
|
||||
sprintf(pd->mapText,"x%d", pd->mapZoomLevel);
|
||||
|
||||
pd->touchLastX = -1;
|
||||
pd->touchLastY = -1;
|
||||
pd->touchIsDraggingMap = false;
|
||||
pd->touchIsChangingSize = false;
|
||||
sprintf(pd->mapText,"x%d", pd->mapZoomLevel);
|
||||
|
||||
pd->touchLastX = -1;
|
||||
pd->touchLastY = -1;
|
||||
pd->touchIsDraggingMap = false;
|
||||
pd->touchIsChangingSize = false;
|
||||
}
|
||||
|
||||
void initPlayer(PlayerData *pd) {
|
||||
pd->isSpawned = false;
|
||||
|
||||
playerInitMiniMapData(pd->minimapData);
|
||||
playerInitEntity(pd);
|
||||
playerInitInventory(pd);
|
||||
|
||||
playerInitSprite(pd);
|
||||
|
||||
initQuests(&(pd->questManager));
|
||||
resetQuests(&(pd->questManager));
|
||||
|
||||
playerInitMenus(pd);
|
||||
|
||||
pd->score = 0;
|
||||
pd->isSpawned = false;
|
||||
|
||||
playerInitMiniMapData(pd->minimapData);
|
||||
playerInitEntity(pd);
|
||||
playerInitInventory(pd);
|
||||
|
||||
playerInitSprite(pd);
|
||||
|
||||
initQuests(&(pd->questManager));
|
||||
resetQuests(&(pd->questManager));
|
||||
|
||||
playerInitMenus(pd);
|
||||
|
||||
pd->score = 0;
|
||||
}
|
||||
|
||||
void freePlayer(PlayerData *pd) {
|
||||
freeQuests(&(pd->questManager));
|
||||
freeQuests(&(pd->questManager));
|
||||
}
|
||||
|
||||
PlayerData* getNearestPlayer(s8 level, s16 x, s16 y) {
|
||||
int nearest = -1;
|
||||
unsigned int nearestDist = UINT_MAX;
|
||||
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(players[i].entity.level!=level) continue;
|
||||
|
||||
int xdif = players[i].entity.x - x;
|
||||
int ydif = players[i].entity.y - y;
|
||||
|
||||
unsigned int dist = xdif*xdif + ydif*ydif;
|
||||
if(dist<nearestDist) {
|
||||
nearest = i;
|
||||
nearestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if(nearest==-1) return NULL;
|
||||
|
||||
return players+nearest;
|
||||
int nearest = -1;
|
||||
unsigned int nearestDist = UINT_MAX;
|
||||
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(players[i].entity.level!=level) continue;
|
||||
|
||||
int xdif = players[i].entity.x - x;
|
||||
int ydif = players[i].entity.y - y;
|
||||
|
||||
unsigned int dist = xdif*xdif + ydif*ydif;
|
||||
if(dist<nearestDist) {
|
||||
nearest = i;
|
||||
nearestDist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if(nearest==-1) return NULL;
|
||||
|
||||
return players+nearest;
|
||||
}
|
||||
|
||||
PlayerData* getLocalPlayer() {
|
||||
return players+playerLocalID;
|
||||
return players+playerLocalID;
|
||||
}
|
||||
|
||||
//player update functions
|
||||
bool playerUseItem(PlayerData *pd) {
|
||||
int aitemID = 0;
|
||||
Item * aitem;
|
||||
Item * item ;
|
||||
|
||||
switch(pd->activeItem->id){
|
||||
//shooting arrows
|
||||
case TOOL_BOW:
|
||||
item = getItemFromInventory(ITEM_ARROW_WOOD, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_WOOD;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_STONE, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_STONE;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_IRON, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_IRON;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_GOLD, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_GOLD;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_GEM, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_GEM;
|
||||
aitem = item;
|
||||
}
|
||||
|
||||
if(aitemID!=0) {
|
||||
--aitem->countLevel;
|
||||
if (isItemEmpty(aitem)) {
|
||||
removeItemFromInventory(aitem->slotNum, &(pd->inventory));
|
||||
}
|
||||
|
||||
switch(pd->entity.p.dir) {
|
||||
case 0:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, 2, pd->entity.level), &eManager);
|
||||
break;
|
||||
case 1:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, -2, pd->entity.level), &eManager);
|
||||
break;
|
||||
case 2:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, -2, 0, pd->entity.level), &eManager);
|
||||
break;
|
||||
case 3:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 2, 0, pd->entity.level), &eManager);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
// Health items
|
||||
case ITEM_APPLE:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 2)){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
int aitemID = 0;
|
||||
Item * aitem;
|
||||
Item * item ;
|
||||
|
||||
switch(pd->activeItem->id){
|
||||
//shooting arrows
|
||||
case TOOL_BOW:
|
||||
item = getItemFromInventory(ITEM_ARROW_WOOD, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_WOOD;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_STONE, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_STONE;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_IRON, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_IRON;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_GOLD, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_GOLD;
|
||||
aitem = item;
|
||||
}
|
||||
item = getItemFromInventory(ITEM_ARROW_GEM, &(pd->inventory));
|
||||
if(item!=NULL) {
|
||||
aitemID = ITEM_ARROW_GEM;
|
||||
aitem = item;
|
||||
}
|
||||
|
||||
if(aitemID!=0) {
|
||||
--aitem->countLevel;
|
||||
if (isItemEmpty(aitem)) {
|
||||
removeItemFromInventory(aitem->slotNum, &(pd->inventory));
|
||||
}
|
||||
|
||||
switch(pd->entity.p.dir) {
|
||||
case 0:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, 2, pd->entity.level), &eManager);
|
||||
break;
|
||||
case 1:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 0, -2, pd->entity.level), &eManager);
|
||||
break;
|
||||
case 2:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, -2, 0, pd->entity.level), &eManager);
|
||||
break;
|
||||
case 3:
|
||||
addEntityToList(newArrowEntity(&(pd->entity), aitemID, 2, 0, pd->entity.level), &eManager);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
// Health items
|
||||
case ITEM_APPLE:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 2)){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
case ITEM_STRENGTH_POTION:
|
||||
if(pd->entity.p.health < 20 && pd->entity.p.strengthTimer == 0){
|
||||
potionEffect(1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
case ITEM_SPEED_POTION:
|
||||
if(pd->entity.p.health < 20 && pd->entity.p.speedTimer == 0){
|
||||
potionEffect(2);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
case ITEM_REGEN_POTION:
|
||||
if(pd->entity.p.health < 20 && pd->entity.p.regenTimer == 0){
|
||||
potionEffect(3);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
case ITEM_SWIM_BREATH_POTION:
|
||||
if(pd->entity.p.health < 20 && pd->entity.p.swimBreathTimer == 0){
|
||||
potionEffect(4);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
case ITEM_GOLD_APPLE:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 1)){
|
||||
playerHeal(pd, 8);
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 1)){
|
||||
playerHeal(pd, 8);
|
||||
playerUseEnergy(pd, -10);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
return 0;
|
||||
case ITEM_FLESH:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
case ITEM_BREAD:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
|
||||
playerHeal(pd, 2);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
return 0;
|
||||
case ITEM_FLESH:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
case ITEM_BREAD:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
|
||||
playerHeal(pd, 2);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
case ITEM_PORK_RAW:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
case ITEM_PORK_COOKED:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
|
||||
playerHeal(pd, 3);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
|
||||
playerHeal(pd, 3);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
case ITEM_BEEF_RAW:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 4+(rand()%4))){
|
||||
playerHeal(pd, 1);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
case ITEM_BEEF_COOKED:
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
|
||||
playerHeal(pd, 4);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
if(pd->entity.p.health < 10 && playerUseEnergy(pd, 3)){
|
||||
playerHeal(pd, 4);
|
||||
--(pd->activeItem->countLevel);
|
||||
}
|
||||
break;
|
||||
//special item
|
||||
case ITEM_WIZARD_SUMMON:
|
||||
if(pd->entity.level==0) {
|
||||
--(pd->activeItem->countLevel);
|
||||
|
||||
--(pd->activeItem->countLevel);
|
||||
|
||||
airWizardHealthDisplay = 2000;
|
||||
addEntityToList(newAirWizardEntity(630, 820, 0), &eManager);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (isItemEmpty(pd->activeItem)) {
|
||||
removeItemFromInventory(pd->activeItem->slotNum, &(pd->inventory));
|
||||
pd->activeItem = &noItem;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (isItemEmpty(pd->activeItem)) {
|
||||
removeItemFromInventory(pd->activeItem->slotNum, &(pd->inventory));
|
||||
pd->activeItem = &noItem;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -329,28 +328,28 @@ bool playerInteract(PlayerData *pd, int x0, int y0, int x1, int y1) {
|
|||
for (i = 0; i < eSize; ++i) {
|
||||
Entity * ent = es[i];
|
||||
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;
|
||||
}
|
||||
|
||||
void playerAttack(PlayerData *pd) {
|
||||
bool done = false;
|
||||
bool done = false;
|
||||
pd->entity.p.attackTimer = 5;
|
||||
int yo = -2;
|
||||
int range = 12;
|
||||
|
||||
//directly using an item
|
||||
int range = 12;
|
||||
|
||||
//directly using an item
|
||||
if(playerUseItem(pd)) return;
|
||||
|
||||
//interacting with entities
|
||||
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 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 3: if(playerInteract(pd, pd->entity.x + 4, pd->entity.y - 8 + yo, pd->entity.x + range, pd->entity.y + 8 + yo)) return; break;
|
||||
}
|
||||
|
||||
//interacting with entities
|
||||
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 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 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 yt = (pd->entity.y + yo) >> 4;
|
||||
|
@ -360,37 +359,37 @@ void playerAttack(PlayerData *pd) {
|
|||
if (pd->entity.p.dir == 2) 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) {
|
||||
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==2) pd->entity.p.isCarrying = false;
|
||||
done = true;
|
||||
}
|
||||
|
||||
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==2) pd->entity.p.isCarrying = false;
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (pd->activeItem != &noItem && isItemEmpty(pd->activeItem)) {
|
||||
removeItemFromInventory(pd->activeItem->slotNum, &(pd->inventory));
|
||||
pd->activeItem = &noItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(done) return;
|
||||
|
||||
//breaking tiles
|
||||
if (pd->activeItem == &noItem || pd->activeItem->id == TOOL_SWORD || pd->activeItem->id == TOOL_AXE) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//breaking tiles
|
||||
if (pd->activeItem == &noItem || pd->activeItem->id == TOOL_SWORD || pd->activeItem->id == TOOL_AXE) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool playerUseArea(PlayerData *pd, int x0, int y0, int x1, int y1) {
|
||||
Entity * entities[eManager.lastSlot[pd->entity.level]];
|
||||
int i;
|
||||
int ae = getEntities(entities, pd->entity.level, x0, y0, x1, y1);
|
||||
for(i = 0; i < ae; ++i){
|
||||
if(useEntity(pd, entities[i])) return true;
|
||||
}
|
||||
int ae = getEntities(entities, pd->entity.level, x0, y0, x1, y1);
|
||||
for(i = 0; i < ae; ++i){
|
||||
if(useEntity(pd, entities[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -404,14 +403,14 @@ bool playerUse(PlayerData *pd) {
|
|||
}
|
||||
|
||||
void tickPlayer(PlayerData *pd, bool inmenu) {
|
||||
if (pd->entity.p.isDead) return;
|
||||
|
||||
//invincibility time
|
||||
if (pd->entity.hurtTime > 0) pd->entity.hurtTime--;
|
||||
|
||||
//stamina recharging
|
||||
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.isDead) return;
|
||||
|
||||
//invincibility time
|
||||
if (pd->entity.hurtTime > 0) pd->entity.hurtTime--;
|
||||
|
||||
//stamina recharging
|
||||
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) {
|
||||
pd->entity.p.staminaRechargeDelay = 40;
|
||||
}
|
||||
|
||||
|
@ -422,25 +421,25 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
|
|||
if (pd->entity.p.staminaRechargeDelay == 0) {
|
||||
++pd->entity.p.staminaRecharge;
|
||||
if (swimming) pd->entity.p.staminaRecharge = 0;
|
||||
|
||||
|
||||
while (pd->entity.p.staminaRecharge > 10) {
|
||||
pd->entity.p.staminaRecharge -= 10;
|
||||
if (pd->entity.p.stamina < 10) ++pd->entity.p.stamina;
|
||||
}
|
||||
}
|
||||
|
||||
if(!inmenu) {
|
||||
if(!pd->sprite.choosen) {
|
||||
pd->ingameMenu = MENU_CHARACTER_CUSTOMIZE;
|
||||
pd->ingameMenuSelection = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//movement
|
||||
pd->entity.p.ax = 0;
|
||||
pd->entity.p.ay = 0;
|
||||
|
||||
if (pd->inputs.k_left.down){
|
||||
|
||||
if(!inmenu) {
|
||||
if(!pd->sprite.choosen) {
|
||||
pd->ingameMenu = MENU_CHARACTER_CUSTOMIZE;
|
||||
pd->ingameMenuSelection = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//movement
|
||||
pd->entity.p.ax = 0;
|
||||
pd->entity.p.ay = 0;
|
||||
|
||||
if (pd->inputs.k_left.down){
|
||||
if(UnderSpeedEffect) {
|
||||
pd->entity.p.ax -= 2;
|
||||
pd->entity.p.dir = 2;
|
||||
|
@ -451,9 +450,9 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
|
|||
pd->entity.p.dir = 2;
|
||||
++pd->entity.p.walkDist;
|
||||
}
|
||||
}
|
||||
if (pd->inputs.k_right.down){
|
||||
if(UnderSpeedEffect) {
|
||||
}
|
||||
if (pd->inputs.k_right.down){
|
||||
if(UnderSpeedEffect) {
|
||||
pd->entity.p.ax += 2;
|
||||
pd->entity.p.dir = 3;
|
||||
++pd->entity.p.walkDist;
|
||||
|
@ -463,9 +462,9 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
|
|||
pd->entity.p.dir = 3;
|
||||
++pd->entity.p.walkDist;
|
||||
}
|
||||
}
|
||||
if (pd->inputs.k_up.down){
|
||||
if(UnderSpeedEffect) {
|
||||
}
|
||||
if (pd->inputs.k_up.down){
|
||||
if(UnderSpeedEffect) {
|
||||
pd->entity.p.ay -= 2;
|
||||
pd->entity.p.dir = 1;
|
||||
++pd->entity.p.walkDist;
|
||||
|
@ -475,9 +474,9 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
|
|||
pd->entity.p.dir = 1;
|
||||
++pd->entity.p.walkDist;
|
||||
}
|
||||
}
|
||||
if (pd->inputs.k_down.down){
|
||||
if(UnderSpeedEffect) {
|
||||
}
|
||||
if (pd->inputs.k_down.down){
|
||||
if(UnderSpeedEffect) {
|
||||
pd->entity.p.ay += 2;
|
||||
pd->entity.p.dir = 0;
|
||||
++pd->entity.p.walkDist;
|
||||
|
@ -487,52 +486,127 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
|
|||
pd->entity.p.dir = 0;
|
||||
++pd->entity.p.walkDist;
|
||||
}
|
||||
}
|
||||
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
|
||||
if (pd->inputs.k_pause.clicked){
|
||||
pd->ingameMenuSelection = 0;
|
||||
pd->ingameMenu = MENU_PAUSED;
|
||||
}
|
||||
|
||||
//attacking
|
||||
if(pd->inputs.k_attack.clicked){
|
||||
if (pd->entity.p.stamina != 0) {
|
||||
if(!shouldRenderDebug) pd->entity.p.stamina--;
|
||||
pd->entity.p.staminaRecharge = 0;
|
||||
|
||||
playerAttack(pd);
|
||||
}
|
||||
}
|
||||
|
||||
if (pd->inputs.k_menu.clicked){
|
||||
pd->ingameMenuInvSel = 0;
|
||||
if(!playerUse(pd)) pd->ingameMenu = MENU_INVENTORY;
|
||||
}
|
||||
}
|
||||
|
||||
//swimming stamina and drowning
|
||||
}
|
||||
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
|
||||
if (pd->inputs.k_pause.clicked){
|
||||
pd->ingameMenuSelection = 0;
|
||||
pd->ingameMenu = MENU_PAUSED;
|
||||
}
|
||||
|
||||
//attacking
|
||||
if(pd->inputs.k_attack.clicked){
|
||||
if (pd->entity.p.stamina != 0) {
|
||||
if(!shouldRenderDebug) pd->entity.p.stamina--;
|
||||
pd->entity.p.staminaRecharge = 0;
|
||||
|
||||
playerAttack(pd);
|
||||
}
|
||||
}
|
||||
|
||||
//picking up furniture
|
||||
if(pd->inputs.k_pickup.clicked){
|
||||
if (pd->entity.p.isCarrying){
|
||||
if (pd->entity.p.stamina != 0) {
|
||||
if(!shouldRenderDebug) pd->entity.p.stamina--;
|
||||
pd->entity.p.staminaRecharge = 0;
|
||||
playerAttack(pd);
|
||||
}
|
||||
}else{
|
||||
int yo = -2;
|
||||
int range = 12;
|
||||
// see if entity near player
|
||||
int x0, y0, x1, y1 = 0;
|
||||
switch(pd->entity.p.dir){
|
||||
case 0:
|
||||
x0 = pd->entity.x - 8;
|
||||
y0 = pd->entity.y + 4 + yo;
|
||||
x1 = pd->entity.x + 8;
|
||||
y1 = pd->entity.y + range + yo;
|
||||
break;
|
||||
case 1:
|
||||
x0 = pd->entity.x - 8;
|
||||
y0 = pd->entity.y - range + yo;
|
||||
x1 = pd->entity.x + 8;
|
||||
y1 = pd->entity.y - 4 + yo;
|
||||
break;
|
||||
case 2:
|
||||
x0 = pd->entity.x - range;
|
||||
y0 = pd->entity.y - 8 + yo;
|
||||
x1 = pd->entity.x - 4;
|
||||
y1 = pd->entity.y + 8 + yo;
|
||||
break;
|
||||
case 3:
|
||||
x0 = pd->entity.x + 4;
|
||||
y0 = pd->entity.y - 8 + yo;
|
||||
x1 = pd->entity.x + range;
|
||||
y1 = pd->entity.y + 8 + yo;
|
||||
break;
|
||||
}
|
||||
Entity * es[eManager.lastSlot[pd->entity.level]];
|
||||
int eSize = getEntities(es, pd->entity.level, x0, y0, x1, y1);
|
||||
int i;
|
||||
for (i = 0; i < eSize; ++i) {
|
||||
Entity * ent = es[i];
|
||||
if (ent != &(pd->entity)){
|
||||
if(ent->type == ENTITY_FURNITURE){
|
||||
//Important: close all crafting windows using this furniture (only applies to chest) or else they will write invalid memory
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(players[i].curChestEntity==ent) {
|
||||
players[i].ingameMenu = MENU_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
Item nItem = newItem(ent->entityFurniture.itemID,0);
|
||||
if(ent->entityFurniture.itemID == ITEM_CHEST) nItem.chestPtr = ent->entityFurniture.inv;
|
||||
pushItemToInventoryFront(nItem, &(pd->inventory));
|
||||
|
||||
removeEntityFromList(ent, ent->level, &eManager);
|
||||
pd->activeItem = &(pd->inventory.items[0]);
|
||||
pd->entity.p.isCarrying = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// in head crafting
|
||||
if(pd->inputs.k_use.clicked){
|
||||
pd->ingameMenuInvSel = 0;
|
||||
if(!playerUse(pd)){
|
||||
pd->currentCraftTitle = "Crafting";
|
||||
openCraftingMenu(pd, &inHeadRecipes, "Crafting");
|
||||
}
|
||||
}
|
||||
|
||||
if (pd->inputs.k_menu.clicked){
|
||||
pd->ingameMenuInvSel = 0;
|
||||
if(!playerUse(pd)) pd->ingameMenu = MENU_INVENTORY;
|
||||
}
|
||||
}
|
||||
|
||||
//swimming stamina and drowning
|
||||
if (swimming && pd->entity.p.swimTimer % 60 == 0 && UnderSwimBreathEffect != true) {
|
||||
if (pd->entity.p.stamina > 0) {
|
||||
if(!shouldRenderDebug) --pd->entity.p.stamina;
|
||||
} else {
|
||||
hurtEntity(&(pd->entity), 1, -1, 0xFFAF00FF, NULL);
|
||||
hurtEntity(&(pd->entity), 1, -1, 0xFFAF00FF, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Regen healing
|
||||
if (regening && pd->entity.p.regenTimer % 75 == 0) {
|
||||
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(UnderSpeedEffect) ++pd->entity.p.speedTimer;
|
||||
if(UnderStrengthEffect) ++pd->entity.p.strengthTimer;
|
||||
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
|
||||
//Update Minimap
|
||||
int xp;
|
||||
|
@ -549,35 +623,35 @@ void tickPlayer(PlayerData *pd, bool inmenu) {
|
|||
}
|
||||
|
||||
void playerSetActiveItem(PlayerData *pd, Item *item) {
|
||||
pd->activeItem = item;
|
||||
if(pd->activeItem->id > 27 && pd->activeItem->id < 51) pd->entity.p.isCarrying = true;
|
||||
else pd->entity.p.isCarrying = false;
|
||||
pd->activeItem = item;
|
||||
if(pd->activeItem->id > 27 && pd->activeItem->id < 51) pd->entity.p.isCarrying = true;
|
||||
else pd->entity.p.isCarrying = false;
|
||||
}
|
||||
|
||||
bool playerUseEnergy(PlayerData *pd, int amount) {
|
||||
if(shouldRenderDebug) return true;
|
||||
if(amount > pd->entity.p.stamina) return false;
|
||||
pd->entity.p.stamina -= amount;
|
||||
return true;
|
||||
if(shouldRenderDebug) return true;
|
||||
if(amount > pd->entity.p.stamina) return false;
|
||||
pd->entity.p.stamina -= amount;
|
||||
return true;
|
||||
}
|
||||
|
||||
void playerHeal(PlayerData *pd, int amount) {
|
||||
pd->entity.p.health += amount;
|
||||
if(pd->entity.p.health > 10) pd->entity.p.health = 10;
|
||||
char healText[11];
|
||||
sprintf(healText, "%d", amount);
|
||||
addEntityToList(newTextParticleEntity(healText,0xFF00FF00, pd->entity.x, pd->entity.y, pd->entity.level), &eManager);
|
||||
pd->entity.p.health += amount;
|
||||
if(pd->entity.p.health > 10) pd->entity.p.health = 10;
|
||||
char healText[11];
|
||||
sprintf(healText, "%d", amount);
|
||||
addEntityToList(newTextParticleEntity(healText,0xFF00FF00, pd->entity.x, pd->entity.y, pd->entity.level), &eManager);
|
||||
}
|
||||
|
||||
void playerSpawn(PlayerData *pd) {
|
||||
while(true){
|
||||
int rx = rand()%128;
|
||||
int ry = rand()%128;
|
||||
if(getTile(pd->entity.level, rx, ry) == TILE_GRASS){
|
||||
pd->entity.x = (rx << 4) + 8;
|
||||
pd->entity.y = (ry << 4) + 8;
|
||||
pd->isSpawned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(true){
|
||||
int rx = rand()%128;
|
||||
int ry = rand()%128;
|
||||
if(getTile(pd->entity.level, rx, ry) == TILE_GRASS){
|
||||
pd->entity.x = (rx << 4) + 8;
|
||||
pd->entity.y = (ry << 4) + 8;
|
||||
pd->isSpawned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
108
source/Player.h
108
source/Player.h
|
@ -16,64 +16,64 @@
|
|||
|
||||
|
||||
typedef struct _plrsp {
|
||||
bool choosen;
|
||||
|
||||
u8 legs;
|
||||
u8 body;
|
||||
u8 arms;
|
||||
u8 head;
|
||||
u8 eyes;
|
||||
bool choosen;
|
||||
|
||||
u8 legs;
|
||||
u8 body;
|
||||
u8 arms;
|
||||
u8 head;
|
||||
u8 eyes;
|
||||
} PlayerSprite;
|
||||
|
||||
typedef struct _plrd {
|
||||
//for identification in save data and sync game start
|
||||
u32 id;
|
||||
bool idSet;
|
||||
bool ready;
|
||||
|
||||
//input/multiplayer/synchronization
|
||||
Inputs inputs;
|
||||
Inputs nextInputs[MAX_INPUT_BUFFER];
|
||||
bool nextTurnReady[MAX_INPUT_BUFFER];
|
||||
|
||||
//
|
||||
bool isSpawned;
|
||||
u8 minimapData[128*128];
|
||||
|
||||
//for identification in save data and sync game start
|
||||
u32 id;
|
||||
bool idSet;
|
||||
bool ready;
|
||||
|
||||
//input/multiplayer/synchronization
|
||||
Inputs inputs;
|
||||
Inputs nextInputs[MAX_INPUT_BUFFER];
|
||||
bool nextTurnReady[MAX_INPUT_BUFFER];
|
||||
|
||||
//
|
||||
bool isSpawned;
|
||||
u8 minimapData[128*128];
|
||||
|
||||
int score;
|
||||
QuestlineManager questManager;
|
||||
|
||||
Entity entity;
|
||||
Inventory inventory;
|
||||
Item *activeItem;
|
||||
|
||||
PlayerSprite sprite;
|
||||
|
||||
//menu data
|
||||
u8 ingameMenu;
|
||||
s8 ingameMenuSelection;
|
||||
s16 ingameMenuInvSel;
|
||||
s16 ingameMenuInvSelOther;
|
||||
bool ingameMenuAreYouSure;
|
||||
bool ingameMenuAreYouSureSave;
|
||||
s16 ingameMenuTimer;
|
||||
NPC_MenuData npcMenuData;
|
||||
|
||||
RecipeManager currentRecipes;
|
||||
char *currentCraftTitle;
|
||||
Entity *curChestEntity;
|
||||
s8 curChestEntityR;
|
||||
|
||||
bool mapShouldRender;
|
||||
u8 mapZoomLevel;
|
||||
s16 mapScrollX;
|
||||
s16 mapScrollY;
|
||||
char mapText[32];
|
||||
|
||||
s16 touchLastX;
|
||||
s16 touchLastY;
|
||||
bool touchIsDraggingMap;
|
||||
bool touchIsChangingSize;
|
||||
QuestlineManager questManager;
|
||||
|
||||
Entity entity;
|
||||
Inventory inventory;
|
||||
Item *activeItem;
|
||||
|
||||
PlayerSprite sprite;
|
||||
|
||||
//menu data
|
||||
u8 ingameMenu;
|
||||
s8 ingameMenuSelection;
|
||||
s16 ingameMenuInvSel;
|
||||
s16 ingameMenuInvSelOther;
|
||||
bool ingameMenuAreYouSure;
|
||||
bool ingameMenuAreYouSureSave;
|
||||
s16 ingameMenuTimer;
|
||||
NPC_MenuData npcMenuData;
|
||||
|
||||
RecipeManager currentRecipes;
|
||||
char *currentCraftTitle;
|
||||
Entity *curChestEntity;
|
||||
s8 curChestEntityR;
|
||||
|
||||
bool mapShouldRender;
|
||||
u8 mapZoomLevel;
|
||||
s16 mapScrollX;
|
||||
s16 mapScrollY;
|
||||
char mapText[32];
|
||||
|
||||
s16 touchLastX;
|
||||
s16 touchLastY;
|
||||
bool touchIsDraggingMap;
|
||||
bool touchIsChangingSize;
|
||||
} PlayerData;
|
||||
|
||||
PlayerData players[MAX_PLAYERS];
|
||||
|
|
794
source/Quests.c
794
source/Quests.c
|
@ -4,434 +4,434 @@
|
|||
#include "Render.h"
|
||||
|
||||
void initTrades() {
|
||||
priestTrades.size = 5;
|
||||
priestTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (priestTrades.size));
|
||||
priestTrades.recipes[0] = defineRecipe(ITEM_DUNGEON_KEY,1,1,ITEM_MAGIC_DUST,2);
|
||||
priestTrades.size = 5;
|
||||
priestTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (priestTrades.size));
|
||||
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[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[4] = defineRecipe(ITEM_COIN,1,1,ITEM_FLESH,5);
|
||||
|
||||
farmerTrades.size = 7;
|
||||
farmerTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (farmerTrades.size));
|
||||
farmerTrades.recipes[0] = defineRecipe(ITEM_WHEAT,5,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[3] = defineRecipe(ITEM_ACORN,3,1,ITEM_COIN,1);
|
||||
farmerTrades.recipes[4] = defineRecipe(ITEM_SEEDS,4,1,ITEM_COIN,2);
|
||||
farmerTrades.recipes[5] = defineRecipe(ITEM_COIN,2,1,ITEM_SEEDS,5);
|
||||
farmerTrades.recipes[6] = defineRecipe(ITEM_COIN,1,1,ITEM_ACORN,5);
|
||||
|
||||
dwarfTrades.size = 2;
|
||||
dwarfTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (dwarfTrades.size));
|
||||
dwarfTrades.recipes[0] = defineRecipe(ITEM_IRONINGOT,4,1,ITEM_GOLDINGOT,1);
|
||||
dwarfTrades.recipes[1] = defineRecipe(ITEM_GOLDINGOT,2,1,ITEM_GEM,1);
|
||||
//TODO: Trade Dragon Scales for something really nice
|
||||
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[4] = defineRecipe(ITEM_COIN,1,1,ITEM_FLESH,5);
|
||||
|
||||
farmerTrades.size = 7;
|
||||
farmerTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (farmerTrades.size));
|
||||
farmerTrades.recipes[0] = defineRecipe(ITEM_WHEAT,5,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[3] = defineRecipe(ITEM_ACORN,3,1,ITEM_COIN,1);
|
||||
farmerTrades.recipes[4] = defineRecipe(ITEM_SEEDS,4,1,ITEM_COIN,2);
|
||||
farmerTrades.recipes[5] = defineRecipe(ITEM_COIN,2,1,ITEM_SEEDS,5);
|
||||
farmerTrades.recipes[6] = defineRecipe(ITEM_COIN,1,1,ITEM_ACORN,5);
|
||||
|
||||
dwarfTrades.size = 2;
|
||||
dwarfTrades.recipes = (Recipe*)malloc(sizeof(Recipe) * (dwarfTrades.size));
|
||||
dwarfTrades.recipes[0] = defineRecipe(ITEM_IRONINGOT,4,1,ITEM_GOLDINGOT,1);
|
||||
dwarfTrades.recipes[1] = defineRecipe(ITEM_GOLDINGOT,2,1,ITEM_GEM,1);
|
||||
//TODO: Trade Dragon Scales for something really nice
|
||||
}
|
||||
|
||||
void freeTrades() {
|
||||
free(priestTrades.recipes);
|
||||
free(farmerTrades.recipes);
|
||||
free(dwarfTrades.recipes);
|
||||
free(priestTrades.recipes);
|
||||
free(farmerTrades.recipes);
|
||||
free(dwarfTrades.recipes);
|
||||
}
|
||||
|
||||
void initQuests(QuestlineManager *questManager) {
|
||||
if(questManager->questlines!=NULL) {
|
||||
freeQuests(questManager);
|
||||
}
|
||||
|
||||
questManager->size = 2;
|
||||
questManager->questlines = (Questline*)malloc(sizeof(Questline) * (questManager->size));
|
||||
if(questManager->questlines!=NULL) {
|
||||
freeQuests(questManager);
|
||||
}
|
||||
|
||||
questManager->size = 2;
|
||||
questManager->questlines = (Questline*)malloc(sizeof(Questline) * (questManager->size));
|
||||
}
|
||||
|
||||
void resetQuests(QuestlineManager *questManager) {
|
||||
int i;
|
||||
for(i=0; i<questManager->size; ++i) {
|
||||
questManager->questlines[i].currentQuest = 0;
|
||||
questManager->questlines[i].currentQuestDone = false;
|
||||
}
|
||||
int i;
|
||||
for(i=0; i<questManager->size; ++i) {
|
||||
questManager->questlines[i].currentQuest = 0;
|
||||
questManager->questlines[i].currentQuestDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
void freeQuests(QuestlineManager *questManager) {
|
||||
free(questManager->questlines);
|
||||
questManager->questlines = NULL;
|
||||
free(questManager->questlines);
|
||||
questManager->questlines = NULL;
|
||||
}
|
||||
|
||||
void resetNPCMenuData(NPC_MenuData *data) {
|
||||
data->currentNPC = 0;
|
||||
data->currentNPCMenu = 0;
|
||||
data->currentNPCVal = 0;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 0;
|
||||
|
||||
data->currentTalkOption0 = "";
|
||||
data->currentTalkOption1 = "";
|
||||
data->currentTalkOption2 = "";
|
||||
data->currentTalk0 = "";
|
||||
data->currentTalk1 = "";
|
||||
data->currentTalk2 = "";
|
||||
data->currentTalk3 = "";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "";
|
||||
data->currentNPC = 0;
|
||||
data->currentNPCMenu = 0;
|
||||
data->currentNPCVal = 0;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 0;
|
||||
|
||||
data->currentTalkOption0 = "";
|
||||
data->currentTalkOption1 = "";
|
||||
data->currentTalkOption2 = "";
|
||||
data->currentTalk0 = "";
|
||||
data->currentTalk1 = "";
|
||||
data->currentTalk2 = "";
|
||||
data->currentTalk3 = "";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "";
|
||||
}
|
||||
|
||||
void openNPCMenu(PlayerData *pd, int npc) {
|
||||
pd->ingameMenu = MENU_NPC;
|
||||
|
||||
NPC_MenuData *data = &(pd->npcMenuData);
|
||||
QuestlineManager *questManager = &(pd->questManager);
|
||||
|
||||
data->currentNPC = npc;
|
||||
data->currentNPCVal = 0;
|
||||
data->currentNPCMenu = NPC_MENU_TALK;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "Bye";
|
||||
data->currentTalkOption1 = "";
|
||||
data->currentTalkOption2 = "";
|
||||
data->currentTalk0 = "";
|
||||
data->currentTalk1 = "";
|
||||
data->currentTalk2 = "";
|
||||
data->currentTalk3 = "";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "";
|
||||
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
switch(data->currentNPC) {
|
||||
case NPC_GIRL:
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "Hello?";
|
||||
data->currentTalk1 = "I have a feeling of having";
|
||||
data->currentTalk2 = "forgotten something very";
|
||||
data->currentTalk3 = "important.";
|
||||
data->currentTalk4 = "Hopefully I will remember";
|
||||
data->currentTalk5 = "it soon...";
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
data->currentTalkOptions = 3;
|
||||
data->currentTalkOption1 = "Trade";
|
||||
data->currentTalkOption2 = "Why are you so few?";
|
||||
|
||||
data->currentTalk0 = "Welcome to our small village";
|
||||
data->currentTalk1 = "I am the leader of our group.";
|
||||
data->currentTalk2 = "If you have anything usefull";
|
||||
data->currentTalk3 = "for us I might be able to";
|
||||
data->currentTalk4 = "provide something nice in";
|
||||
data->currentTalk5 = "exchange.";
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Maybe some other time";
|
||||
data->currentTalkOption1 = "Trade";
|
||||
|
||||
data->currentTalk0 = "Hello friend!";
|
||||
data->currentTalk1 = "Nice seeing somebody else";
|
||||
data->currentTalk2 = "visit my little farm.";
|
||||
data->currentTalk3 = "Interested in buying some";
|
||||
data->currentTalk4 = "fresh farm goods?";
|
||||
data->currentTalk5 = "";
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Nothing";
|
||||
data->currentTalkOption1 = "What are you doing here?";
|
||||
if(questManager->questlines[1].currentQuest==1) {
|
||||
data->currentTalkOptions = 3;
|
||||
data->currentTalkOption2 = "Dwarvish language";
|
||||
}
|
||||
|
||||
data->currentTalk0 = "Oh hello?";
|
||||
data->currentTalk1 = "You must be quite brave";
|
||||
data->currentTalk2 = "or stupid to be walking";
|
||||
data->currentTalk3 = "around in this dungeon.";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "How can I help you?";
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(questManager->questlines[1].currentQuest<=1) {
|
||||
questManager->questlines[1].currentQuest = 1;
|
||||
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "?";
|
||||
|
||||
data->currentTalk0 = "Dwo neal bet reck da lo";
|
||||
data->currentTalk1 = "dhum don lir lugn at el";
|
||||
data->currentTalk2 = "nur tor erno ur yo trad";
|
||||
data->currentTalk3 = "thra so tir kho ukk tin";
|
||||
data->currentTalk4 = "hel dro ic";
|
||||
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)
|
||||
} else if(questManager->questlines[1].currentQuest==2) {
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Not really";
|
||||
data->currentTalkOption1 = "Trade";
|
||||
|
||||
data->currentTalk0 = "How are ya?";
|
||||
data->currentTalk1 = "Pretty unusal meeting a";
|
||||
data->currentTalk2 = "human down here.";
|
||||
data->currentTalk3 = "";
|
||||
data->currentTalk4 = "have something valuable";
|
||||
data->currentTalk5 = "to trade?";
|
||||
}
|
||||
break;
|
||||
}
|
||||
pd->ingameMenu = MENU_NPC;
|
||||
|
||||
NPC_MenuData *data = &(pd->npcMenuData);
|
||||
QuestlineManager *questManager = &(pd->questManager);
|
||||
|
||||
data->currentNPC = npc;
|
||||
data->currentNPCVal = 0;
|
||||
data->currentNPCMenu = NPC_MENU_TALK;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "Bye";
|
||||
data->currentTalkOption1 = "";
|
||||
data->currentTalkOption2 = "";
|
||||
data->currentTalk0 = "";
|
||||
data->currentTalk1 = "";
|
||||
data->currentTalk2 = "";
|
||||
data->currentTalk3 = "";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "";
|
||||
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
switch(data->currentNPC) {
|
||||
case NPC_GIRL:
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "Hello?";
|
||||
data->currentTalk1 = "I have a feeling of having";
|
||||
data->currentTalk2 = "forgotten something very";
|
||||
data->currentTalk3 = "important.";
|
||||
data->currentTalk4 = "Hopefully I will remember";
|
||||
data->currentTalk5 = "it soon...";
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
data->currentTalkOptions = 3;
|
||||
data->currentTalkOption1 = "Trade";
|
||||
data->currentTalkOption2 = "Why are you so few?";
|
||||
|
||||
data->currentTalk0 = "Welcome to our small village";
|
||||
data->currentTalk1 = "I am the leader of our group.";
|
||||
data->currentTalk2 = "If you have anything usefull";
|
||||
data->currentTalk3 = "for us I might be able to";
|
||||
data->currentTalk4 = "provide something nice in";
|
||||
data->currentTalk5 = "exchange.";
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Maybe some other time";
|
||||
data->currentTalkOption1 = "Trade";
|
||||
|
||||
data->currentTalk0 = "Hello friend!";
|
||||
data->currentTalk1 = "Nice seeing somebody else";
|
||||
data->currentTalk2 = "visit my little farm.";
|
||||
data->currentTalk3 = "Interested in buying some";
|
||||
data->currentTalk4 = "fresh farm goods?";
|
||||
data->currentTalk5 = "";
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Nothing";
|
||||
data->currentTalkOption1 = "What are you doing here?";
|
||||
if(questManager->questlines[1].currentQuest==1) {
|
||||
data->currentTalkOptions = 3;
|
||||
data->currentTalkOption2 = "Dwarvish language";
|
||||
}
|
||||
|
||||
data->currentTalk0 = "Oh hello?";
|
||||
data->currentTalk1 = "You must be quite brave";
|
||||
data->currentTalk2 = "or stupid to be walking";
|
||||
data->currentTalk3 = "around in this dungeon.";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "How can I help you?";
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(questManager->questlines[1].currentQuest<=1) {
|
||||
questManager->questlines[1].currentQuest = 1;
|
||||
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "?";
|
||||
|
||||
data->currentTalk0 = "Dwo neal bet reck da lo";
|
||||
data->currentTalk1 = "dhum don lir lugn at el";
|
||||
data->currentTalk2 = "nur tor erno ur yo trad";
|
||||
data->currentTalk3 = "thra so tir kho ukk tin";
|
||||
data->currentTalk4 = "hel dro ic";
|
||||
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)
|
||||
} else if(questManager->questlines[1].currentQuest==2) {
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Not really";
|
||||
data->currentTalkOption1 = "Trade";
|
||||
|
||||
data->currentTalk0 = "How are ya?";
|
||||
data->currentTalk1 = "Pretty unusal meeting a";
|
||||
data->currentTalk2 = "human down here.";
|
||||
data->currentTalk3 = "";
|
||||
data->currentTalk4 = "have something valuable";
|
||||
data->currentTalk5 = "to trade?";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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_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_accept.clicked){
|
||||
data->currentTalkDone = true;
|
||||
}
|
||||
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_down.clicked){ --data->currentTalkSel; if(data->currentTalkSel < 0) data->currentTalkSel=data->currentTalkOptions-1;}
|
||||
|
||||
if(pd->inputs.k_accept.clicked){
|
||||
data->currentTalkDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
void tickNPCMenu(PlayerData *pd) {
|
||||
NPC_MenuData *data = &(pd->npcMenuData);
|
||||
QuestlineManager *questManager = &(pd->questManager);
|
||||
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) tickTalkMenu(pd, data);
|
||||
NPC_MenuData *data = &(pd->npcMenuData);
|
||||
QuestlineManager *questManager = &(pd->questManager);
|
||||
|
||||
|
||||
switch(data->currentNPC) {
|
||||
case NPC_GIRL:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
openCraftingMenu(pd, &priestTrades, "Trading");
|
||||
} else if(data->currentTalkSel==2) {
|
||||
data->currentNPCVal = 1;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "For quite some time now this";
|
||||
data->currentTalk1 = "village has been tyrannized";
|
||||
data->currentTalk2 = "by a powerfull Air Wizard.";
|
||||
data->currentTalk3 = "We are the only ones who";
|
||||
data->currentTalk4 = "still have not given up";
|
||||
data->currentTalk5 = "our old homes.";
|
||||
}
|
||||
} else if(data->currentNPCVal==1) {
|
||||
if(data->currentTalkSel==0) {
|
||||
data->currentNPCVal = 2;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "Most of the time the wizard";
|
||||
data->currentTalk1 = "hides somewhere in the";
|
||||
data->currentTalk2 = "cloudes. They can only be";
|
||||
data->currentTalk3 = "reached by a stairwell";
|
||||
data->currentTalk4 = "protected by an almost";
|
||||
data->currentTalk5 = "undestroyable stone barrier.";
|
||||
}
|
||||
} else if(data->currentNPCVal==2) {
|
||||
if(data->currentTalkSel==0) {
|
||||
data->currentNPCVal = 3;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "I am guessing you would ";
|
||||
data->currentTalk1 = "need tools atleast as";
|
||||
data->currentTalk2 = "strong as diamonds to be";
|
||||
data->currentTalk3 = "able to destroy it.";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "";
|
||||
}
|
||||
} else if(data->currentNPCVal==3) {
|
||||
if(data->currentTalkSel==0) {
|
||||
data->currentNPCVal = 4;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Let me do it!";
|
||||
data->currentTalkOption1 = "I am not sure";
|
||||
|
||||
data->currentTalk0 = "I am willing to give an";
|
||||
data->currentTalk1 = "ancient artifact passed";
|
||||
data->currentTalk2 = "down over generations to";
|
||||
data->currentTalk3 = "anybody who manages to";
|
||||
data->currentTalk4 = "chase the wizard away and";
|
||||
data->currentTalk5 = "come back with proof.";
|
||||
}
|
||||
} else if(data->currentNPCVal==4) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
openCraftingMenu(pd, &farmerTrades, "Trading");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
data->currentNPCVal = 2;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "Ok";
|
||||
|
||||
data->currentTalk0 = "The books in this dungeon";
|
||||
data->currentTalk1 = "house secrets that cannot be";
|
||||
data->currentTalk2 = "found anywhere else in the";
|
||||
data->currentTalk3 = "world. So I came to study";
|
||||
data->currentTalk4 = "them. Most are written in";
|
||||
data->currentTalk5 = "an ancient language.";
|
||||
} else if(data->currentTalkSel==2) {
|
||||
data->currentNPCVal = 1;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "I need to think about it";
|
||||
data->currentTalkOption1 = "Here they are";
|
||||
|
||||
data->currentTalk0 = "So you have met a dwarf but";
|
||||
data->currentTalk1 = "had a little communication";
|
||||
data->currentTalk2 = "problem? I do have a dwarvish";
|
||||
data->currentTalk3 = "translation book but I havent";
|
||||
data->currentTalk4 = "read it yet. For 10 Gold bars";
|
||||
data->currentTalk5 = "I will give it to you anyway.";
|
||||
}
|
||||
} else if(data->currentNPCVal==1) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
data->currentNPCVal = 2;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "";
|
||||
|
||||
if(countItemInv(ITEM_GOLDINGOT, 0, &(pd->inventory))>=10) {
|
||||
//remove gold from player inventory
|
||||
//TODO: Maybe I should make a generic substract items method sometime
|
||||
Item* item = getItemFromInventory(ITEM_GOLDINGOT, &(pd->inventory));
|
||||
item->countLevel -= 10;
|
||||
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, &(pd->inventory));
|
||||
|
||||
questManager->questlines[1].currentQuest = 2;
|
||||
|
||||
data->currentTalk0 = "Thank you these will be";
|
||||
data->currentTalk1 = "really helpfull.";
|
||||
data->currentTalk2 = "Here take this book with";
|
||||
data->currentTalk3 = "it you should be able to";
|
||||
data->currentTalk4 = "easily understand anything";
|
||||
data->currentTalk5 = "a dwarf can say.";
|
||||
|
||||
data->currentTalkOption0 = "Thanks";
|
||||
} else {
|
||||
data->currentTalk0 = "You do not seem to have";
|
||||
data->currentTalk1 = "enough Gold Bars with you.";
|
||||
data->currentTalk2 = "";
|
||||
data->currentTalk3 = "Ask again when you have";
|
||||
data->currentTalk4 = "collected the 10 Bars.";
|
||||
data->currentTalk5 = "";
|
||||
|
||||
data->currentTalkOption0 = "Ok";
|
||||
}
|
||||
}
|
||||
} else if(data->currentNPCVal==2) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(questManager->questlines[1].currentQuest<=1) {
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
} else if(questManager->questlines[1].currentQuest==2) {
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
openCraftingMenu(pd, &dwarfTrades, "Trading");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) tickTalkMenu(pd, data);
|
||||
|
||||
|
||||
switch(data->currentNPC) {
|
||||
case NPC_GIRL:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
openCraftingMenu(pd, &priestTrades, "Trading");
|
||||
} else if(data->currentTalkSel==2) {
|
||||
data->currentNPCVal = 1;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "For quite some time now this";
|
||||
data->currentTalk1 = "village has been tyrannized";
|
||||
data->currentTalk2 = "by a powerfull Air Wizard.";
|
||||
data->currentTalk3 = "We are the only ones who";
|
||||
data->currentTalk4 = "still have not given up";
|
||||
data->currentTalk5 = "our old homes.";
|
||||
}
|
||||
} else if(data->currentNPCVal==1) {
|
||||
if(data->currentTalkSel==0) {
|
||||
data->currentNPCVal = 2;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "Most of the time the wizard";
|
||||
data->currentTalk1 = "hides somewhere in the";
|
||||
data->currentTalk2 = "cloudes. They can only be";
|
||||
data->currentTalk3 = "reached by a stairwell";
|
||||
data->currentTalk4 = "protected by an almost";
|
||||
data->currentTalk5 = "undestroyable stone barrier.";
|
||||
}
|
||||
} else if(data->currentNPCVal==2) {
|
||||
if(data->currentTalkSel==0) {
|
||||
data->currentNPCVal = 3;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "...";
|
||||
|
||||
data->currentTalk0 = "I am guessing you would ";
|
||||
data->currentTalk1 = "need tools atleast as";
|
||||
data->currentTalk2 = "strong as diamonds to be";
|
||||
data->currentTalk3 = "able to destroy it.";
|
||||
data->currentTalk4 = "";
|
||||
data->currentTalk5 = "";
|
||||
}
|
||||
} else if(data->currentNPCVal==3) {
|
||||
if(data->currentTalkSel==0) {
|
||||
data->currentNPCVal = 4;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "Let me do it!";
|
||||
data->currentTalkOption1 = "I am not sure";
|
||||
|
||||
data->currentTalk0 = "I am willing to give an";
|
||||
data->currentTalk1 = "ancient artifact passed";
|
||||
data->currentTalk2 = "down over generations to";
|
||||
data->currentTalk3 = "anybody who manages to";
|
||||
data->currentTalk4 = "chase the wizard away and";
|
||||
data->currentTalk5 = "come back with proof.";
|
||||
}
|
||||
} else if(data->currentNPCVal==4) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
openCraftingMenu(pd, &farmerTrades, "Trading");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
data->currentNPCVal = 2;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "Ok";
|
||||
|
||||
data->currentTalk0 = "The books in this dungeon";
|
||||
data->currentTalk1 = "house secrets that cannot be";
|
||||
data->currentTalk2 = "found anywhere else in the";
|
||||
data->currentTalk3 = "world. So I came to study";
|
||||
data->currentTalk4 = "them. Most are written in";
|
||||
data->currentTalk5 = "an ancient language.";
|
||||
} else if(data->currentTalkSel==2) {
|
||||
data->currentNPCVal = 1;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 2;
|
||||
data->currentTalkOption0 = "I need to think about it";
|
||||
data->currentTalkOption1 = "Here they are";
|
||||
|
||||
data->currentTalk0 = "So you have met a dwarf but";
|
||||
data->currentTalk1 = "had a little communication";
|
||||
data->currentTalk2 = "problem? I do have a dwarvish";
|
||||
data->currentTalk3 = "translation book but I havent";
|
||||
data->currentTalk4 = "read it yet. For 10 Gold bars";
|
||||
data->currentTalk5 = "I will give it to you anyway.";
|
||||
}
|
||||
} else if(data->currentNPCVal==1) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
data->currentNPCVal = 2;
|
||||
|
||||
data->currentTalkSel = 0;
|
||||
data->currentTalkDone = false;
|
||||
data->currentTalkOptions = 1;
|
||||
data->currentTalkOption0 = "";
|
||||
|
||||
if(countItemInv(ITEM_GOLDINGOT, 0, &(pd->inventory))>=10) {
|
||||
//remove gold from player inventory
|
||||
//TODO: Maybe I should make a generic substract items method sometime
|
||||
Item* item = getItemFromInventory(ITEM_GOLDINGOT, &(pd->inventory));
|
||||
item->countLevel -= 10;
|
||||
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, &(pd->inventory));
|
||||
|
||||
questManager->questlines[1].currentQuest = 2;
|
||||
|
||||
data->currentTalk0 = "Thank you these will be";
|
||||
data->currentTalk1 = "really helpfull.";
|
||||
data->currentTalk2 = "Here take this book with";
|
||||
data->currentTalk3 = "it you should be able to";
|
||||
data->currentTalk4 = "easily understand anything";
|
||||
data->currentTalk5 = "a dwarf can say.";
|
||||
|
||||
data->currentTalkOption0 = "Thanks";
|
||||
} else {
|
||||
data->currentTalk0 = "You do not seem to have";
|
||||
data->currentTalk1 = "enough Gold Bars with you.";
|
||||
data->currentTalk2 = "";
|
||||
data->currentTalk3 = "Ask again when you have";
|
||||
data->currentTalk4 = "collected the 10 Bars.";
|
||||
data->currentTalk5 = "";
|
||||
|
||||
data->currentTalkOption0 = "Ok";
|
||||
}
|
||||
}
|
||||
} else if(data->currentNPCVal==2) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(questManager->questlines[1].currentQuest<=1) {
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentNPCVal==0) pd->ingameMenu = MENU_NONE;
|
||||
}
|
||||
} else if(questManager->questlines[1].currentQuest==2) {
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK && data->currentTalkDone) {
|
||||
if(data->currentTalkSel==0) {
|
||||
pd->ingameMenu = MENU_NONE;
|
||||
} else if(data->currentTalkSel==1) {
|
||||
openCraftingMenu(pd, &dwarfTrades, "Trading");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void renderTalkMenu(NPC_MenuData *data, char * name) {
|
||||
renderFrame(1,1,24,14,0xFFFF1010);
|
||||
drawTextColor(name,24+1,14+1,0xFF000000);
|
||||
renderFrame(1,1,24,14,0xFFFF1010);
|
||||
drawTextColor(name,24+1,14+1,0xFF000000);
|
||||
drawTextColor(name,24,14,0xFF6FE2E2);
|
||||
|
||||
drawText(data->currentTalk0, 32, 32);
|
||||
drawText(data->currentTalk1, 32, 48);
|
||||
drawText(data->currentTalk2, 32, 64);
|
||||
drawText(data->currentTalk3, 32, 80);
|
||||
drawText(data->currentTalk4, 32, 96);
|
||||
drawText(data->currentTalk5, 32, 112);
|
||||
|
||||
if(data->currentTalkOptions>=3) drawText(data->currentTalkOption2, 64, 147);
|
||||
if(data->currentTalkOptions>=2) drawText(data->currentTalkOption1, 64, 171);
|
||||
if(data->currentTalkOptions>=1) drawText(data->currentTalkOption0, 64, 195);
|
||||
|
||||
if(data->currentTalkOptions>=3 && data->currentTalkSel==2) drawText(">", 48, 147);
|
||||
if(data->currentTalkOptions>=2 && data->currentTalkSel==1) drawText(">", 48, 171);
|
||||
if(data->currentTalkOptions>=1 && data->currentTalkSel==0) drawText(">", 48, 195);
|
||||
|
||||
drawText(data->currentTalk0, 32, 32);
|
||||
drawText(data->currentTalk1, 32, 48);
|
||||
drawText(data->currentTalk2, 32, 64);
|
||||
drawText(data->currentTalk3, 32, 80);
|
||||
drawText(data->currentTalk4, 32, 96);
|
||||
drawText(data->currentTalk5, 32, 112);
|
||||
|
||||
if(data->currentTalkOptions>=3) drawText(data->currentTalkOption2, 64, 147);
|
||||
if(data->currentTalkOptions>=2) drawText(data->currentTalkOption1, 64, 171);
|
||||
if(data->currentTalkOptions>=1) drawText(data->currentTalkOption0, 64, 195);
|
||||
|
||||
if(data->currentTalkOptions>=3 && data->currentTalkSel==2) drawText(">", 48, 147);
|
||||
if(data->currentTalkOptions>=2 && data->currentTalkSel==1) drawText(">", 48, 171);
|
||||
if(data->currentTalkOptions>=1 && data->currentTalkSel==0) drawText(">", 48, 195);
|
||||
}
|
||||
|
||||
void renderNPCMenu(NPC_MenuData *data) {
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
switch(data->currentNPC) {
|
||||
case NPC_GIRL:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Maria");
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Priest Brom");
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Farmer Garrow");
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Librarian Ajihad");
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Dwarf Orik");
|
||||
break;
|
||||
}
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
switch(data->currentNPC) {
|
||||
case NPC_GIRL:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Maria");
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Priest Brom");
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Farmer Garrow");
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Librarian Ajihad");
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(data->currentNPCMenu==NPC_MENU_TALK) renderTalkMenu(data, "Dwarf Orik");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,33 +3,33 @@
|
|||
#include <3ds.h>
|
||||
|
||||
typedef struct _questline {
|
||||
int currentQuest;
|
||||
bool currentQuestDone;
|
||||
int currentQuest;
|
||||
bool currentQuestDone;
|
||||
} Questline;
|
||||
|
||||
typedef struct _questlineManager {
|
||||
int size;
|
||||
Questline * questlines;
|
||||
int size;
|
||||
Questline * questlines;
|
||||
} QuestlineManager;
|
||||
|
||||
typedef struct _npcMenuData {
|
||||
u8 currentNPC;
|
||||
u8 currentNPC;
|
||||
|
||||
int currentNPCMenu;
|
||||
int currentNPCVal;
|
||||
int currentNPCMenu;
|
||||
int currentNPCVal;
|
||||
|
||||
int currentTalkSel;
|
||||
bool currentTalkDone;
|
||||
int currentTalkOptions;
|
||||
char * currentTalkOption0;
|
||||
char * currentTalkOption1;
|
||||
char * currentTalkOption2;
|
||||
char * currentTalk0;
|
||||
char * currentTalk1;
|
||||
char * currentTalk2;
|
||||
char * currentTalk3;
|
||||
char * currentTalk4;
|
||||
char * currentTalk5;
|
||||
int currentTalkSel;
|
||||
bool currentTalkDone;
|
||||
int currentTalkOptions;
|
||||
char * currentTalkOption0;
|
||||
char * currentTalkOption1;
|
||||
char * currentTalkOption2;
|
||||
char * currentTalk0;
|
||||
char * currentTalk1;
|
||||
char * currentTalk2;
|
||||
char * currentTalk3;
|
||||
char * currentTalk4;
|
||||
char * currentTalk5;
|
||||
} NPC_MenuData;
|
||||
|
||||
//TODO: Actually move the data here
|
||||
|
|
535
source/Render.c
535
source/Render.c
|
@ -165,8 +165,8 @@ void renderp(s32 xp, s32 yp, u32 xTile, u32 yTile) {
|
|||
xp -= offsetX;
|
||||
yp -= offsetY;
|
||||
int scaleX = playerScale, scaleY = playerScale;
|
||||
sf2d_draw_texture_part_scale(playerSprites, xp << 1, yp << 1, xTile, yTile, 16, 16,
|
||||
scaleX, scaleY);
|
||||
sf2d_draw_texture_part_scale(playerSprites, xp << 1, yp << 1, xTile, yTile, 16, 16,
|
||||
scaleX, scaleY);
|
||||
}
|
||||
|
||||
void renderTitle(int x, int y) {
|
||||
|
@ -285,13 +285,13 @@ void renderFrame(int x1, int y1, int x2, int y2, u32 bgColor) {
|
|||
void bakeLights() {
|
||||
playerLightBake = sf2d_create_texture(64, 64, TEXFMT_RGBA8, SF2D_PLACE_RAM);
|
||||
lanternLightBake = sf2d_create_texture(128, 128, TEXFMT_RGBA8, SF2D_PLACE_RAM);
|
||||
|
||||
|
||||
glowwormLightBake = sf2d_create_texture(32, 32, TEXFMT_RGBA8, SF2D_PLACE_RAM);
|
||||
glowwormBigLightBake = sf2d_create_texture(64, 64, TEXFMT_RGBA8, SF2D_PLACE_RAM);
|
||||
|
||||
bakeLight(playerLightBake, 32, 32, 32);
|
||||
bakeLight(lanternLightBake, 64, 64, 64);
|
||||
|
||||
|
||||
bakeLight(glowwormLightBake, 8, 8, 8);
|
||||
bakeLight(glowwormBigLightBake, 12, 12, 12);
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ void bakeLights() {
|
|||
void freeLightBakes() {
|
||||
sf2d_free_texture(playerLightBake);
|
||||
sf2d_free_texture(lanternLightBake);
|
||||
|
||||
|
||||
sf2d_free_texture(glowwormLightBake);
|
||||
sf2d_free_texture(glowwormBigLightBake);
|
||||
}
|
||||
|
@ -311,9 +311,9 @@ void renderLightsToStencil(PlayerData *pd, bool force, bool invert, bool rplayer
|
|||
C3D_StencilOp(GPU_STENCIL_REPLACE, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP);
|
||||
C3D_AlphaTest(true, GPU_GREATER, 0);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < eManager.lastSlot[pd->entity.level]; ++i) {
|
||||
Entity e = eManager.entities[pd->entity.level][i];
|
||||
|
@ -326,7 +326,7 @@ void renderLightsToStencil(PlayerData *pd, bool force, bool invert, bool rplayer
|
|||
else renderLight(e.x+8, e.y-8, glowwormLightBake);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int xo = offsetX >> 4;
|
||||
int yo = offsetY >> 4;
|
||||
int x, y;
|
||||
|
@ -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
|
||||
for (x = xo-2; x <= 13 + xo+2; ++x) {
|
||||
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"
|
||||
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;
|
||||
|
@ -343,7 +343,7 @@ void renderLightsToStencil(PlayerData *pd, bool force, bool invert, bool rplayer
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL);
|
||||
if(invert) {
|
||||
|
@ -421,7 +421,7 @@ void renderDots(int x, int y, u8 bits1, u8 bits2, u8 bits3, u8 bits4, u32 xTile,
|
|||
render16(x, y, xTile, yTile, bits1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(tu && tl) render(x, y, xTile, yTile, bits1);
|
||||
if(tu && tr) render(x + 8, y, xTile+8, yTile, bits2);
|
||||
if(td && tl) render(x, y + 8, xTile, yTile+8, bits3);
|
||||
|
@ -478,40 +478,40 @@ void renderTile(int i, int d, u8 level, int x, int y) {
|
|||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_TREE);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_FLOWER);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_SAPLING_TREE);
|
||||
|
||||
if(level==1 && worldData.season==3) renderConnectedTile4(x, y, 256, 112);
|
||||
else if(level==1 && worldData.season==2) renderConnectedTile4(x, y, 256, 128);
|
||||
|
||||
if(level==1 && worldData.season==3) renderConnectedTile4(x, y, 256, 112);
|
||||
else if(level==1 && worldData.season==2) renderConnectedTile4(x, y, 256, 128);
|
||||
else renderConnectedTile4(x, y, 256, 0);
|
||||
break;
|
||||
case TILE_TREE:
|
||||
renderTile(TILE_GRASS, 0, level, x, y);
|
||||
|
||||
|
||||
checkSurrTiles8(level, x >> 4, y >> 4, TILE_TREE);
|
||||
|
||||
if(worldData.season==2) {
|
||||
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, y+8, 352+((td && tl && tdl) ? 16 : 0), 104, 0);
|
||||
render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 104, 0);
|
||||
} else if(worldData.season==3) {
|
||||
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, y+8, 352+((td && tl && tdl) ? 16 : 0), 120, 0);
|
||||
render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 120, 0);
|
||||
} else {
|
||||
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, y+8, 256+((td && tl && tdl) ? 16 : 0), 56, 0);
|
||||
render(x+8, y+8, 264+((td && tr && tdr) ? 16 : 0), 56, 0);
|
||||
}
|
||||
|
||||
|
||||
if(worldData.season==2) {
|
||||
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, y+8, 352+((td && tl && tdl) ? 16 : 0), 104, 0);
|
||||
render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 104, 0);
|
||||
} else if(worldData.season==3) {
|
||||
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, y+8, 352+((td && tl && tdl) ? 16 : 0), 120, 0);
|
||||
render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 120, 0);
|
||||
} else {
|
||||
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, y+8, 256+((td && tl && tdl) ? 16 : 0), 56, 0);
|
||||
render(x+8, y+8, 264+((td && tr && tdr) ? 16 : 0), 56, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
case TILE_ROCK:
|
||||
checkSurrTiles8(level, x >> 4, y >> 4, TILE_ROCK);
|
||||
if(level>1)
|
||||
renderConnectedTile8(x, y, 256, 96);
|
||||
else
|
||||
renderConnectedTile8(x, y, 336, 64);
|
||||
if(level>1)
|
||||
renderConnectedTile8(x, y, 256, 96);
|
||||
else
|
||||
renderConnectedTile8(x, y, 336, 64);
|
||||
break;
|
||||
case TILE_HARDROCK:
|
||||
checkSurrTiles8(level, x >> 4, y >> 4, TILE_HARDROCK);
|
||||
|
@ -527,33 +527,33 @@ void renderTile(int i, int d, u8 level, int x, int y) {
|
|||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_SAND);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_CACTUS);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_SAPLING_CACTUS);
|
||||
|
||||
|
||||
if(level==1 && worldData.season==3) {
|
||||
renderConnectedTile4(x, y, 256, 112);
|
||||
renderConnectedTile4(x, y, 256, 112);
|
||||
} else {
|
||||
renderConnectedTile4(x, y, 320, 0);
|
||||
|
||||
if (d > 0) {
|
||||
render16(x, y, 336, 48, 0);
|
||||
}
|
||||
}
|
||||
renderConnectedTile4(x, y, 320, 0);
|
||||
|
||||
if (d > 0) {
|
||||
render16(x, y, 336, 48, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TILE_WATER:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_WATER);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_HOLE);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_ICE);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 384, 0);
|
||||
|
||||
|
||||
srand((syncTickCount + (x / 2 - y) * 4311) / 10);
|
||||
renderDots(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, 288, 64);
|
||||
break;
|
||||
case TILE_LAVA:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_LAVA);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_HOLE);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 448, 0);
|
||||
|
||||
|
||||
srand((syncTickCount + (x / 2 - y) * 4311) / 10);
|
||||
renderDots(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, 304, 64);
|
||||
break;
|
||||
|
@ -561,7 +561,7 @@ void renderTile(int i, int d, u8 level, int x, int y) {
|
|||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_HOLE);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_WATER);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_LAVA);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 256, 16);
|
||||
break;
|
||||
case TILE_CACTUS:
|
||||
|
@ -571,7 +571,7 @@ void renderTile(int i, int d, u8 level, int x, int y) {
|
|||
case TILE_FLOWER:
|
||||
renderTile(TILE_GRASS, 0, level, x, y);
|
||||
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;
|
||||
case TILE_STAIRS_DOWN:
|
||||
if (level == 0)
|
||||
|
@ -594,7 +594,7 @@ void renderTile(int i, int d, u8 level, int x, int y) {
|
|||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_CLOUD);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_STAIRS_DOWN);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_CLOUDCACTUS);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 320, 16);
|
||||
break;
|
||||
case TILE_CLOUDCACTUS:
|
||||
|
@ -620,32 +620,32 @@ void renderTile(int i, int d, u8 level, int x, int y) {
|
|||
break;
|
||||
case TILE_WOOD_WALL:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_WOOD_WALL);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 384, 16);
|
||||
break;
|
||||
case TILE_STONE_WALL:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_STONE_WALL);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 256, 80);
|
||||
break;
|
||||
case TILE_IRON_WALL:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_IRON_WALL);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 448, 16);
|
||||
break;
|
||||
case TILE_GOLD_WALL:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_GOLD_WALL);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 256, 32);
|
||||
break;
|
||||
case TILE_GEM_WALL:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_GEM_WALL);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 320, 32);
|
||||
break;
|
||||
case TILE_DUNGEON_WALL:
|
||||
checkSurrTiles8(level, x >> 4, y >> 4, TILE_DUNGEON_WALL);
|
||||
|
||||
|
||||
renderConnectedTile8(x, y, 384, 32);
|
||||
break;
|
||||
case TILE_DUNGEON_FLOOR:
|
||||
|
@ -657,61 +657,61 @@ void renderTile(int i, int d, u8 level, int x, int y) {
|
|||
case TILE_MAGIC_BARRIER:
|
||||
renderTile(TILE_DUNGEON_FLOOR, 0, level, x, y);
|
||||
render16(x, y, 320, 64, d);
|
||||
|
||||
|
||||
//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) {
|
||||
x -= offsetX;
|
||||
y -= offsetY;
|
||||
|
||||
|
||||
int data = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < eManager.lastSlot[level]; ++i) {
|
||||
Entity * e = &eManager.entities[level][i];
|
||||
|
||||
|
||||
if(e->type == ENTITY_MAGIC_PILLAR) {
|
||||
++data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char currentCount[3];
|
||||
sprintf(currentCount, "%d", data);
|
||||
|
||||
|
||||
drawSizedTextColor(currentCount, x+4 + 1, y+4 + 1, 2, dungeonColor[1]);
|
||||
drawSizedTextColor(currentCount, x+4, y+4, 2, dungeonColor[0]);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case TILE_BOOKSHELVES:
|
||||
case TILE_BOOKSHELVES:
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_BOOKSHELVES);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 384, 80 + d*16);
|
||||
break;
|
||||
case TILE_WOOD_FLOOR:
|
||||
render16(x, y, 336, 96, 0);
|
||||
break;
|
||||
case TILE_MYCELIUM:
|
||||
case TILE_WOOD_FLOOR:
|
||||
render16(x, y, 336, 96, 0);
|
||||
break;
|
||||
case 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_RED);
|
||||
|
||||
|
||||
if(level==1 && worldData.season==3) renderConnectedTile4(x, y, 256, 112);
|
||||
else renderConnectedTile4(x, y, 448, 80);
|
||||
break;
|
||||
case TILE_MUSHROOM_BROWN:
|
||||
renderTile(TILE_MYCELIUM, 0, level, x, y);
|
||||
case TILE_MUSHROOM_BROWN:
|
||||
renderTile(TILE_MYCELIUM, 0, level, x, y);
|
||||
render16(x, y, 448 + (d&0x1)*16, 96, 0);
|
||||
break;
|
||||
case TILE_MUSHROOM_RED:
|
||||
renderTile(TILE_MYCELIUM, 0, level, x, y);
|
||||
break;
|
||||
case TILE_MUSHROOM_RED:
|
||||
renderTile(TILE_MYCELIUM, 0, level, x, y);
|
||||
render16(x, y, 480 + (d&0x1)*16, 96, 0);
|
||||
break;
|
||||
case TILE_ICE:
|
||||
break;
|
||||
case TILE_ICE:
|
||||
renderTile(TILE_WATER, 0, level, x, y);
|
||||
//checkSurrTiles4(x >> 4, y >> 4, TILE_WATER);
|
||||
//checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE);
|
||||
checkSurrTiles4(level, x >> 4, y >> 4, TILE_ICE);
|
||||
|
||||
|
||||
renderConnectedTile4(x, y, 448, 112);
|
||||
break;
|
||||
}
|
||||
|
@ -725,12 +725,12 @@ void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile) {
|
|||
render16(x, y, xTile+48, yTile, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int l = (tl ? 16 : 0);
|
||||
int r = (tr ? 16 : 0);
|
||||
int u = (tu ? 32 : 0);
|
||||
int d = (td ? 32 : 0);
|
||||
|
||||
|
||||
render(x, y, xTile +l+u, yTile, 0);
|
||||
render(x+8, y, xTile+8+r+u, yTile, 0);
|
||||
render(x, y+8, xTile +l+d, yTile+8, 0);
|
||||
|
@ -743,12 +743,12 @@ void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile) {
|
|||
render16(x, y, xTile+64, yTile, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int l = (tl ? 16 : 0);
|
||||
int r = (tr ? 16 : 0);
|
||||
int u = (tu ? 32 : 0);
|
||||
int d = (td ? 32 : 0);
|
||||
|
||||
|
||||
render(x, y, xTile +l+u+((tl && tu && tul) ? 16 : 0), yTile, 0);
|
||||
render(x+8, y, xTile+8+r+u+((tr && tu && tur) ? 16 : 0), yTile, 0);
|
||||
render(x, y+8, xTile +l+d+((tl && td && tdl) ? 16 : 0), yTile+8, 0);
|
||||
|
@ -757,45 +757,45 @@ void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile) {
|
|||
|
||||
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
|
||||
|
||||
int mx = pd->mapScrollX;
|
||||
int my = pd->mapScrollY;
|
||||
if(pd->mapZoomLevel == 2) mx = 32;
|
||||
|
||||
int mx = pd->mapScrollX;
|
||||
int my = pd->mapScrollY;
|
||||
if(pd->mapZoomLevel == 2) mx = 32;
|
||||
sf2d_draw_texture_scale(minimap[pd->entity.level], mx, my, pd->mapZoomLevel, pd->mapZoomLevel); // zoomed map
|
||||
|
||||
|
||||
// Airwizard on zoomed map
|
||||
if(pd->entity.level == 0){
|
||||
if(awX != 0 && awY != 0){
|
||||
render16c(
|
||||
(mx+((awX/16)*pd->mapZoomLevel)-16)/2,
|
||||
(my+((awY/16)*pd->mapZoomLevel)-16)/2,
|
||||
160, 112,
|
||||
((pd->entity.p.walkDist >> 6) & 1) == 0 ? 0 : 1,
|
||||
(mx+((awX/16)*pd->mapZoomLevel)-16)/2,
|
||||
(my+((awY/16)*pd->mapZoomLevel)-16)/2,
|
||||
160, 112,
|
||||
((pd->entity.p.walkDist >> 6) & 1) == 0 ? 0 : 1,
|
||||
2, 2
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Player on zoomed map
|
||||
//TODO: Maybe also render other players?
|
||||
render16c(
|
||||
(mx+((pd->entity.x/16)*pd->mapZoomLevel)-16)/2,
|
||||
(my+((pd->entity.y/16)*pd->mapZoomLevel)-16)/2,
|
||||
0, 112,
|
||||
((pd->entity.p.walkDist >> 6) & 1) == 0 ? 0 : 1,
|
||||
2, 2
|
||||
);
|
||||
|
||||
drawText(pd->mapText,224, 214); // "x2"/"x4"/"x6"
|
||||
render16(142, 2, 72, 208, 0); // Exit button
|
||||
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
|
||||
else if(pd->mapZoomLevel > 5) sf2d_draw_rectangle(284, 210, 26, 20, 0x7F4F4F4F); // gray out minus button
|
||||
//TODO: Maybe also render other players?
|
||||
render16c(
|
||||
(mx+((pd->entity.x/16)*pd->mapZoomLevel)-16)/2,
|
||||
(my+((pd->entity.y/16)*pd->mapZoomLevel)-16)/2,
|
||||
0, 112,
|
||||
((pd->entity.p.walkDist >> 6) & 1) == 0 ? 0 : 1,
|
||||
2, 2
|
||||
);
|
||||
|
||||
drawText(pd->mapText,224, 214); // "x2"/"x4"/"x6"
|
||||
render16(142, 2, 72, 208, 0); // Exit button
|
||||
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
|
||||
else if(pd->mapZoomLevel > 5) sf2d_draw_rectangle(284, 210, 26, 20, 0x7F4F4F4F); // gray out minus button
|
||||
}
|
||||
|
||||
char scoreT[32];
|
||||
void renderGui(PlayerData *pd) {
|
||||
int i;
|
||||
//health and stamina
|
||||
//health and stamina
|
||||
for (i = 0; i < 10; ++i) {
|
||||
if (i < pd->entity.p.health)
|
||||
render(i * 8 + 6, 5, 168, 152, 0);
|
||||
|
@ -806,11 +806,11 @@ void renderGui(PlayerData *pd) {
|
|||
else
|
||||
render(i * 8 + 6, 14, 191, 152, 0);
|
||||
}
|
||||
|
||||
//minimap
|
||||
|
||||
//minimap
|
||||
sf2d_draw_texture(minimap[pd->entity.level], 10, 102);
|
||||
|
||||
//active item
|
||||
|
||||
//active item
|
||||
renderItemWithTextCentered(pd->activeItem, 320, 66);
|
||||
itoa(pd->score, scoreT, 10); // integer to base10 string
|
||||
drawText("Score:",214,12);
|
||||
|
@ -819,10 +819,10 @@ void renderGui(PlayerData *pd) {
|
|||
if(awX != 0 && awY != 0){
|
||||
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.
|
||||
|
||||
|
||||
//quick select
|
||||
drawText("Quickselect:",164,118);
|
||||
|
||||
|
@ -832,7 +832,7 @@ void renderGui(PlayerData *pd) {
|
|||
if((inv->lastSlot) > i) {
|
||||
int xip = i % 4;
|
||||
int yip = i / 4;
|
||||
|
||||
|
||||
item = &inv->items[i];
|
||||
renderItemIcon(item->id, item->countLevel, 81+xip*21, 77+yip*21);
|
||||
}
|
||||
|
@ -840,86 +840,86 @@ void renderGui(PlayerData *pd) {
|
|||
}
|
||||
|
||||
void renderPlayer(PlayerData *pd) {
|
||||
if (pd->entity.level!=getLocalPlayer()->entity.level) {
|
||||
return;
|
||||
}
|
||||
if (pd->entity.level!=getLocalPlayer()->entity.level) {
|
||||
return;
|
||||
}
|
||||
if (pd->entity.p.isDead) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
int xo = pd->entity.x - 8;
|
||||
int yo = pd->entity.y - 8;
|
||||
|
||||
//attack animation upwards
|
||||
//attack animation upwards
|
||||
if (pd->entity.p.attackTimer > 0 && pd->entity.p.dir == 1) {
|
||||
renderc(xo, yo - 4, 16, 160, 16, 8, 0);
|
||||
renderItemIcon(pd->activeItem->id, pd->activeItem->countLevel, xo + 4, yo - 4);
|
||||
}
|
||||
|
||||
//find basic indices
|
||||
int aIndexBig = 0;
|
||||
int aIndexSmall = 0;
|
||||
switch(pd->entity.p.dir) {
|
||||
case 0: //down
|
||||
aIndexBig = 0;
|
||||
aIndexSmall = 0;
|
||||
break;
|
||||
case 1: //up
|
||||
aIndexBig = 2;
|
||||
aIndexSmall = 1;
|
||||
break;
|
||||
case 2: //left
|
||||
aIndexBig = 7;
|
||||
aIndexSmall = 3;
|
||||
break;
|
||||
case 3: //right
|
||||
aIndexBig = 4;
|
||||
aIndexSmall = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
//find index offset based on walk state
|
||||
u8 walkingOffset = (pd->entity.p.walkDist >> 4) % 2;
|
||||
if(pd->entity.p.dir==2 || pd->entity.p.dir==3) {
|
||||
walkingOffset = (pd->entity.p.walkDist >> 4) % 4;
|
||||
if(walkingOffset==2) walkingOffset = 0;
|
||||
if(walkingOffset==3) walkingOffset = 2;
|
||||
}
|
||||
|
||||
bool swimming = isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4);
|
||||
|
||||
//render water anim when swimming
|
||||
if (swimming) {
|
||||
renderc(xo, yo + 5, 48, 160 + (((pd->entity.p.swimTimer >> 4) & 1) << 3), 16, 8, 0);
|
||||
}
|
||||
|
||||
|
||||
//render the different parts
|
||||
//legs
|
||||
if(!swimming) {
|
||||
renderp(xo, yo, (0+aIndexBig+walkingOffset)*16, pd->sprite.legs*16);
|
||||
}
|
||||
//body
|
||||
renderp(xo, yo, (10+aIndexBig+walkingOffset)*16, pd->sprite.body*16);
|
||||
//arms (normal)
|
||||
if(!(pd->entity.p.isCarrying)) {
|
||||
renderp(xo, yo, (20+aIndexBig+walkingOffset)*16, pd->sprite.arms*16);
|
||||
}
|
||||
//head
|
||||
renderp(xo, yo, (30+aIndexSmall)*16, pd->sprite.head*16);
|
||||
//eyes
|
||||
renderp(xo, yo, (34+aIndexSmall)*16, pd->sprite.eyes*16);
|
||||
//arms (carrying)
|
||||
if(pd->entity.p.isCarrying) {
|
||||
renderp(xo, yo, (38+aIndexSmall)*16, pd->sprite.arms*16);
|
||||
}
|
||||
|
||||
|
||||
//furniture
|
||||
|
||||
//find basic indices
|
||||
int aIndexBig = 0;
|
||||
int aIndexSmall = 0;
|
||||
switch(pd->entity.p.dir) {
|
||||
case 0: //down
|
||||
aIndexBig = 0;
|
||||
aIndexSmall = 0;
|
||||
break;
|
||||
case 1: //up
|
||||
aIndexBig = 2;
|
||||
aIndexSmall = 1;
|
||||
break;
|
||||
case 2: //left
|
||||
aIndexBig = 7;
|
||||
aIndexSmall = 3;
|
||||
break;
|
||||
case 3: //right
|
||||
aIndexBig = 4;
|
||||
aIndexSmall = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
//find index offset based on walk state
|
||||
u8 walkingOffset = (pd->entity.p.walkDist >> 4) % 2;
|
||||
if(pd->entity.p.dir==2 || pd->entity.p.dir==3) {
|
||||
walkingOffset = (pd->entity.p.walkDist >> 4) % 4;
|
||||
if(walkingOffset==2) walkingOffset = 0;
|
||||
if(walkingOffset==3) walkingOffset = 2;
|
||||
}
|
||||
|
||||
bool swimming = isWater(pd->entity.level, pd->entity.x>>4, pd->entity.y>>4);
|
||||
|
||||
//render water anim when swimming
|
||||
if (swimming) {
|
||||
renderc(xo, yo + 5, 48, 160 + (((pd->entity.p.swimTimer >> 4) & 1) << 3), 16, 8, 0);
|
||||
}
|
||||
|
||||
|
||||
//render the different parts
|
||||
//legs
|
||||
if(!swimming) {
|
||||
renderp(xo, yo, (0+aIndexBig+walkingOffset)*16, pd->sprite.legs*16);
|
||||
}
|
||||
//body
|
||||
renderp(xo, yo, (10+aIndexBig+walkingOffset)*16, pd->sprite.body*16);
|
||||
//arms (normal)
|
||||
if(!(pd->entity.p.isCarrying)) {
|
||||
renderp(xo, yo, (20+aIndexBig+walkingOffset)*16, pd->sprite.arms*16);
|
||||
}
|
||||
//head
|
||||
renderp(xo, yo, (30+aIndexSmall)*16, pd->sprite.head*16);
|
||||
//eyes
|
||||
renderp(xo, yo, (34+aIndexSmall)*16, pd->sprite.eyes*16);
|
||||
//arms (carrying)
|
||||
if(pd->entity.p.isCarrying) {
|
||||
renderp(xo, yo, (38+aIndexSmall)*16, pd->sprite.arms*16);
|
||||
}
|
||||
|
||||
|
||||
//furniture
|
||||
if (pd->entity.p.isCarrying) {
|
||||
renderFurniture(pd->activeItem->id, xo, yo - 12);
|
||||
}
|
||||
|
||||
//attack animation (other directios)
|
||||
//attack animation (other directios)
|
||||
if (pd->entity.p.attackTimer > 0) {
|
||||
switch (pd->entity.p.dir) {
|
||||
case 0:
|
||||
|
@ -939,37 +939,37 @@ void renderPlayer(PlayerData *pd) {
|
|||
}
|
||||
|
||||
void renderWeather(u8 level, int xScroll, int yScroll) {
|
||||
if(level==1) {
|
||||
if(worldData.season==3) {
|
||||
int xp = -128 + ((syncTickCount>>2) - xScroll*2)%128;
|
||||
int yp = -128 + ((syncTickCount>>1) - yScroll*2)%128;
|
||||
int xp2 = 0 - ((syncTickCount>>2) + xScroll*2)%128;
|
||||
int yp2 = -128 + ((syncTickCount>>1)+64 - yScroll*2)%128;
|
||||
int xt;
|
||||
int yt;
|
||||
for(xt=0; xt<4; ++xt) {
|
||||
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, xp2 + xt*128, yp2 + yt*128, 192, 0, 64, 64, 2, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(worldData.rain) {
|
||||
int xp = -((xScroll*2)%128);
|
||||
int yp = -128 + ((syncTickCount<<2) - yScroll*2)%128;
|
||||
int xp2 = -((xScroll*2+8)%128);
|
||||
int yp2 = -128 + ((syncTickCount<<1)+64 - yScroll*2)%128;
|
||||
int xt;
|
||||
int yt;
|
||||
for(xt=0; xt<4; ++xt) {
|
||||
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, xp2 + xt*128, yp2 + yt*128, 128, 0, 64, 64, 2, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(level==1) {
|
||||
if(worldData.season==3) {
|
||||
int xp = -128 + ((syncTickCount>>2) - xScroll*2)%128;
|
||||
int yp = -128 + ((syncTickCount>>1) - yScroll*2)%128;
|
||||
int xp2 = 0 - ((syncTickCount>>2) + xScroll*2)%128;
|
||||
int yp2 = -128 + ((syncTickCount>>1)+64 - yScroll*2)%128;
|
||||
int xt;
|
||||
int yt;
|
||||
for(xt=0; xt<4; ++xt) {
|
||||
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, xp2 + xt*128, yp2 + yt*128, 192, 0, 64, 64, 2, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(worldData.rain) {
|
||||
int xp = -((xScroll*2)%128);
|
||||
int yp = -128 + ((syncTickCount<<2) - yScroll*2)%128;
|
||||
int xp2 = -((xScroll*2+8)%128);
|
||||
int yp2 = -128 + ((syncTickCount<<1)+64 - yScroll*2)%128;
|
||||
int xt;
|
||||
int yt;
|
||||
for(xt=0; xt<4; ++xt) {
|
||||
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, xp2 + xt*128, yp2 + yt*128, 128, 0, 64, 64, 2, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renderDayNight(PlayerData *pd) {
|
||||
|
@ -978,7 +978,7 @@ void renderDayNight(PlayerData *pd) {
|
|||
int color2 = 0x00100C0C;
|
||||
int alpha1 = 0x88;
|
||||
int alpha2 = 0xDD;
|
||||
|
||||
|
||||
if(worldData.daytime>5000 && worldData.daytime<6000) {
|
||||
alpha2 = (alpha2 * (1000-(worldData.daytime-5000)))/1000;
|
||||
alpha1 = (alpha1 * (1000-(worldData.daytime-5000)))/1000;
|
||||
|
@ -986,10 +986,10 @@ void renderDayNight(PlayerData *pd) {
|
|||
alpha1 = (alpha1 * (worldData.daytime-18000))/1000;
|
||||
alpha2 = (alpha2 * (worldData.daytime-18000))/1000;
|
||||
}
|
||||
|
||||
|
||||
color1 = color1 | (alpha1 << 24);
|
||||
color2 = color2 | (alpha2 << 24);
|
||||
|
||||
|
||||
sf2d_draw_rectangle(0, 0, 400, 240, color1); //You might think "real" black would be better, but it actually looks better that way
|
||||
renderLightsToStencil(pd, true, true, false);
|
||||
sf2d_draw_rectangle(0, 0, 400, 240, color2); //You might think "real" black would be better, but it actually looks better that way
|
||||
|
@ -998,7 +998,7 @@ void renderDayNight(PlayerData *pd) {
|
|||
}
|
||||
|
||||
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_rectangle(0, 0, 400, 240, 0xAFDFDFDF);
|
||||
} else if(level == 5) {
|
||||
|
@ -1118,7 +1118,7 @@ void renderFurniture(int itemID, int x, int y) {
|
|||
render16(x, y, 240, 128, 0);
|
||||
break;
|
||||
case ITEM_POTION_MAKER:
|
||||
render16(x, y, 240, 96, 0);
|
||||
render16(x, y, 192, 168, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1265,7 +1265,7 @@ void renderEntity(Entity* e, int x, int y) {
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case ENTITY_DRAGONPROJECTILE:
|
||||
case ENTITY_DRAGONPROJECTILE:
|
||||
if(e->dragonFire.type==0) {
|
||||
renderr(x, y, 0, 320, 0, e->dragonFire.age * 0.349);
|
||||
} else {
|
||||
|
@ -1279,7 +1279,7 @@ void renderEntity(Entity* e, int x, int y) {
|
|||
if (e->arrow.age >= 200)
|
||||
if (e->arrow.age / 6 % 2 == 0)
|
||||
return;
|
||||
|
||||
|
||||
int abits = 0;
|
||||
int ayp = 168;
|
||||
if(e->arrow.xa<0) {
|
||||
|
@ -1292,7 +1292,7 @@ void renderEntity(Entity* e, int x, int y) {
|
|||
ayp += 8;
|
||||
abits += 2;
|
||||
}
|
||||
|
||||
|
||||
switch (e->arrow.itemID) {
|
||||
case ITEM_ARROW_WOOD:
|
||||
render(x-2, y-2, 72, ayp, abits);
|
||||
|
@ -1314,7 +1314,7 @@ void renderEntity(Entity* e, int x, int y) {
|
|||
case ENTITY_GLOWWORM:
|
||||
render(x-4, y-4, 224, 112, 0);
|
||||
break;
|
||||
case ENTITY_NPC:
|
||||
case ENTITY_NPC:
|
||||
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
|
||||
col = 0xFF7F7F7F;
|
||||
if(r->recipes[i + io].itemAmountLevel==1) {
|
||||
drawTextColor(getBasicItemName(r->recipes[i + io].itemResult, r->recipes[i + io].itemAmountLevel), x + 18, y + 2, col);
|
||||
} else {
|
||||
drawTextColor(getItemName(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 {
|
||||
drawTextColor(getItemName(r->recipes[i + io].itemResult, r->recipes[i + io].itemAmountLevel), x + 18, y + 2, col);
|
||||
}
|
||||
}
|
||||
|
||||
int yy = selected + 1 - io + yo;
|
||||
|
@ -1463,13 +1463,13 @@ void renderItemStuffWithText(int itemID, int itemCL, bool onlyOne, int x, int y)
|
|||
y + 2, 0xFFD2D2D2, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
/* For bottom screen */
|
||||
/* For bottom screen */
|
||||
void renderItemWithTextCentered(Item* item, int width, int y) {
|
||||
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);
|
||||
|
||||
|
||||
if (item->onlyOne)
|
||||
drawText(getItemName(item->id, item->countLevel), x + 18, y + 2);
|
||||
else
|
||||
|
@ -1478,8 +1478,8 @@ void renderItemWithTextCentered(Item* item, int width, int y) {
|
|||
}
|
||||
|
||||
void renderItemIcon(int itemID, int countLevel, int x, int y) {
|
||||
int xd;
|
||||
int yd;
|
||||
int xd;
|
||||
int yd;
|
||||
switch (itemID) {
|
||||
case ITEM_NULL:
|
||||
return;
|
||||
|
@ -1523,7 +1523,7 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
|
|||
render(x, y, 0, 152, 0);
|
||||
break;
|
||||
case ITEM_WOOD:
|
||||
render(x, y, 8, 152, 0);
|
||||
render(x, y, 160, 168, 0);
|
||||
break;
|
||||
case ITEM_STONE:
|
||||
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);
|
||||
break;
|
||||
case ITEM_GOLD_APPLE:
|
||||
render(x, y, 177, 160, 0);
|
||||
render(x, y, 144, 168, 0);
|
||||
break;
|
||||
case ITEM_STRENGTH_POTION:
|
||||
render(x, y, 184, 160, 0);
|
||||
render(x, y, 176, 160, 0);
|
||||
break;
|
||||
case ITEM_SPEED_POTION:
|
||||
render(x, y, 191, 160, 0);
|
||||
render(x, y, 184, 160, 0);
|
||||
break;
|
||||
case ITEM_REGEN_POTION:
|
||||
render(x, y, 198, 160, 0);
|
||||
render(x, y, 192, 160, 0);
|
||||
break;
|
||||
case ITEM_SWIM_BREATH_POTION:
|
||||
render(x, y, 219, 160, 0);
|
||||
render(x, y, 200, 160, 0);
|
||||
break;
|
||||
case ITEM_SLIME:
|
||||
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);
|
||||
break;
|
||||
case ITEM_POTION_MAKER:
|
||||
render(x, y, 216, 152, 0);
|
||||
render(x, y, 192, 168, 0);
|
||||
break;
|
||||
case ITEM_WALL_WOOD:
|
||||
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:
|
||||
render(x, y, 168, 160, 0);
|
||||
break;
|
||||
case ITEM_BOOKSHELVES:
|
||||
case ITEM_BOOKSHELVES:
|
||||
render(x, y, 232, 144, 0);
|
||||
break;
|
||||
case ITEM_MAGIC_DUST:
|
||||
render(x, y, 200, 152, 0);
|
||||
case ITEM_MAGIC_DUST:
|
||||
render(x, y, 200, 152, 0);
|
||||
break;
|
||||
case ITEM_COIN:
|
||||
render(x, y, 208, 152, 0);
|
||||
case ITEM_COIN:
|
||||
render(x, y, 208, 152, 0);
|
||||
break;
|
||||
case TOOL_BUCKET:
|
||||
render(x, y, 200 + countLevel * 8, 144, 0);
|
||||
|
@ -1687,16 +1687,37 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
|
|||
case TOOL_BOW:
|
||||
render(x, y, 64, 168, 0);
|
||||
break;
|
||||
case TOOL_MAGIC_COMPASS:
|
||||
xd = worldData.compassData[getLocalPlayer()->entity.level][0] - (getLocalPlayer()->entity.x>>4);
|
||||
yd = worldData.compassData[getLocalPlayer()->entity.level][1] - (getLocalPlayer()->entity.y>>4);
|
||||
if(abs(yd)>abs(xd)) {
|
||||
if(yd<0) render(x, y, 112, 168, 0);
|
||||
else render(x, y, 120, 168, 0);
|
||||
} else {
|
||||
if(xd<0) render(x, y, 128, 168, 0);
|
||||
else render(x, y, 136, 168, 0);
|
||||
}
|
||||
case TOOL_MAGIC_COMPASS:
|
||||
xd = worldData.compassData[getLocalPlayer()->entity.level][0] - (getLocalPlayer()->entity.x>>4);
|
||||
yd = worldData.compassData[getLocalPlayer()->entity.level][1] - (getLocalPlayer()->entity.y>>4);
|
||||
if(abs(yd)>abs(xd)) {
|
||||
if(yd<0) render(x, y, 112, 168, 0);
|
||||
else render(x, y, 120, 168, 0);
|
||||
} else {
|
||||
if(xd<0) render(x, y, 128, 168, 0);
|
||||
else render(x, y, 136, 168, 0);
|
||||
}
|
||||
break;
|
||||
case TOOL_CLAYMORE:
|
||||
render(x, y, countLevel * 8, 176, 0);
|
||||
break;
|
||||
case ITEM_TORCH:
|
||||
render(x, y, 168, 168, 0);
|
||||
break;
|
||||
case ITEM_BED:
|
||||
render(x, y, 176, 168, 0);
|
||||
break;
|
||||
case ITEM_SHEARS:
|
||||
render(x, y, 40, 176, 0);
|
||||
break;
|
||||
case ITEM_FISHING_ROD:
|
||||
render(x, y, 48, 176, 0);
|
||||
break;
|
||||
case ITEM_FISH_RAW:
|
||||
render(x, y, 56, 176, 0);
|
||||
break;
|
||||
case ITEM_FISH_COOKED:
|
||||
render(x, y, 64, 176, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include <3ds.h>
|
||||
#include <sf2d.h>
|
||||
#include <string.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include "Globals.h"
|
||||
|
|
1170
source/SaveLoad.c
1170
source/SaveLoad.c
File diff suppressed because it is too large
Load diff
|
@ -5,48 +5,48 @@ int soundListenerX;
|
|||
int soundListenerY;
|
||||
|
||||
void loadSound(Sound * snd, char * filename){
|
||||
FILE *file = fopen(filename, "rb");
|
||||
if(file != NULL){
|
||||
fseek(file, 0, SEEK_END);
|
||||
snd->size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
snd->buffer = linearAlloc(snd->size);
|
||||
fread(snd->buffer, 1, snd->size, file);
|
||||
}
|
||||
fclose(file);
|
||||
FILE *file = fopen(filename, "rb");
|
||||
if(file != NULL){
|
||||
fseek(file, 0, SEEK_END);
|
||||
snd->size = ftell(file)/2;
|
||||
fseek(file, 0, SEEK_SET);
|
||||
snd->buffer = linearAlloc(snd->size*sizeof(u16));
|
||||
fread(snd->buffer, 1, snd->size, file);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
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) {
|
||||
if(level != soundListenerLevel) return;
|
||||
int xd = soundListenerX - x;
|
||||
int yd = soundListenerY - y;
|
||||
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);
|
||||
if(level != soundListenerLevel) return;
|
||||
int xd = soundListenerX - x;
|
||||
int yd = soundListenerY - y;
|
||||
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);
|
||||
}
|
||||
|
||||
void setListenerPosition(s8 level, int x, int y) {
|
||||
soundListenerLevel = level;
|
||||
soundListenerX = x;
|
||||
soundListenerY = y;
|
||||
soundListenerLevel = level;
|
||||
soundListenerX = x;
|
||||
soundListenerY = y;
|
||||
}
|
||||
|
||||
void playMusic(Sound *snd){
|
||||
static Sound *lastSnd;
|
||||
if(lastSnd==snd) return;
|
||||
lastSnd = snd;
|
||||
|
||||
csndPlaySound(10, SOUND_FORMAT_16BIT | SOUND_REPEAT, 44100, 1, 0, snd->buffer, snd->buffer, snd->size);
|
||||
static Sound *lastSnd;
|
||||
if(lastSnd==snd) return;
|
||||
lastSnd = snd;
|
||||
|
||||
csndPlaySound(10, SOUND_FORMAT_16BIT | SOUND_REPEAT, 44100, 1, 0, snd->buffer, snd->buffer, snd->size);
|
||||
}
|
||||
|
||||
void stopMusic() {
|
||||
CSND_SetPlayState(8, 0);
|
||||
CSND_SetPlayState(10, 0);
|
||||
csndExecCmds(true);
|
||||
csndExecCmds(true);
|
||||
}
|
||||
|
||||
void updateMusic(int lvl, int time) {
|
||||
|
@ -77,7 +77,7 @@ void loadSounds() {
|
|||
loadSound(&snd_pickup, "romfs:/resources/pickup.raw");
|
||||
loadSound(&snd_bossdeath, "romfs:/resources/bossdeath.raw");
|
||||
loadSound(&snd_craft, "romfs:/resources/craft.raw");
|
||||
|
||||
|
||||
loadSound(&music_menu, "romfs:/resources/music/menu.raw");
|
||||
loadSound(&music_floor0, "romfs:/resources/music/floor0.raw");
|
||||
loadSound(&music_floor1, "romfs:/resources/music/floor1.raw");
|
||||
|
@ -87,18 +87,18 @@ void loadSounds() {
|
|||
}
|
||||
|
||||
void freeSounds(){
|
||||
linearFree(snd_playerHurt.buffer);
|
||||
linearFree(snd_playerDeath.buffer);
|
||||
linearFree(snd_monsterHurt.buffer);
|
||||
linearFree(snd_test.buffer);
|
||||
linearFree(snd_pickup.buffer);
|
||||
linearFree(snd_bossdeath.buffer);
|
||||
linearFree(snd_craft.buffer);
|
||||
|
||||
linearFree(snd_playerHurt.buffer);
|
||||
linearFree(snd_playerDeath.buffer);
|
||||
linearFree(snd_monsterHurt.buffer);
|
||||
linearFree(snd_test.buffer);
|
||||
linearFree(snd_pickup.buffer);
|
||||
linearFree(snd_bossdeath.buffer);
|
||||
linearFree(snd_craft.buffer);
|
||||
|
||||
linearFree(music_menu.buffer);
|
||||
linearFree(music_floor0.buffer);
|
||||
linearFree(music_floor1.buffer);
|
||||
linearFree(music_floor1_night.buffer);
|
||||
linearFree(music_floor23.buffer);
|
||||
linearFree(music_floor4.buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
|
||||
typedef struct {
|
||||
u32 size;
|
||||
u8 * buffer;
|
||||
u32 size;
|
||||
u8 * buffer;
|
||||
} Sound;
|
||||
|
||||
void loadSound(Sound * snd, char * filename);
|
||||
|
@ -36,4 +36,4 @@ Sound music_floor0;
|
|||
Sound music_floor1;
|
||||
Sound music_floor1_night;
|
||||
Sound music_floor23;
|
||||
Sound music_floor4;
|
||||
Sound music_floor4;
|
||||
|
|
|
@ -21,204 +21,204 @@ void synchronizerSendLocalInputs();
|
|||
int synchronizerGetTurnIndex(u32 turn);
|
||||
|
||||
void synchronizerInit(int seed, int initPlayerCount, int initPlayerLocalID) {
|
||||
synchronizerLocalTurn = 0;
|
||||
synchronizerNextSeed = seed;
|
||||
playerCount = initPlayerCount;
|
||||
playerLocalID = initPlayerLocalID;
|
||||
syncTickCount = 0;
|
||||
|
||||
//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++) {
|
||||
resetKeys(&(players[i].inputs));
|
||||
for(int j=0; j<MAX_INPUT_BUFFER; j++) {
|
||||
resetKeys(&(players[i].nextInputs[j]));
|
||||
}
|
||||
players[i].nextTurnReady[0] = true;
|
||||
players[i].idSet = false;
|
||||
players[i].ready = false;
|
||||
}
|
||||
|
||||
players[playerLocalID].id = localUID;
|
||||
players[playerLocalID].idSet = true;
|
||||
players[playerLocalID].ready = true;
|
||||
|
||||
|
||||
//switch menu
|
||||
currentMenu = MENU_LOADING;
|
||||
|
||||
synchronizerRunning = false;
|
||||
synchronizerLocalTurn = 0;
|
||||
synchronizerNextSeed = seed;
|
||||
playerCount = initPlayerCount;
|
||||
playerLocalID = initPlayerLocalID;
|
||||
syncTickCount = 0;
|
||||
|
||||
//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++) {
|
||||
resetKeys(&(players[i].inputs));
|
||||
for(int j=0; j<MAX_INPUT_BUFFER; j++) {
|
||||
resetKeys(&(players[i].nextInputs[j]));
|
||||
}
|
||||
players[i].nextTurnReady[0] = true;
|
||||
players[i].idSet = false;
|
||||
players[i].ready = false;
|
||||
}
|
||||
|
||||
players[playerLocalID].id = localUID;
|
||||
players[playerLocalID].idSet = true;
|
||||
players[playerLocalID].ready = true;
|
||||
|
||||
|
||||
//switch menu
|
||||
currentMenu = MENU_LOADING;
|
||||
|
||||
synchronizerRunning = false;
|
||||
}
|
||||
|
||||
void synchronizerSendUID() {
|
||||
sendIDPacket(playerLocalID, localUID);
|
||||
sendIDPacket(playerLocalID, localUID);
|
||||
}
|
||||
|
||||
void synchronizerSetPlayerUID(int playerID, u32 uid) {
|
||||
players[playerID].id = uid;
|
||||
players[playerID].idSet = true;
|
||||
players[playerID].id = uid;
|
||||
players[playerID].idSet = true;
|
||||
}
|
||||
|
||||
void synchronizerSendIfReady() {
|
||||
//we are ready when we recieved all uids
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].idSet) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//ready -> send to server
|
||||
sendStartReadyPacket(playerLocalID);
|
||||
//we are ready when we recieved all uids
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].idSet) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//ready -> send to server
|
||||
sendStartReadyPacket(playerLocalID);
|
||||
}
|
||||
|
||||
void synchronizerSetPlayerReady(int playerID) {
|
||||
players[playerID].ready = true;
|
||||
players[playerID].ready = true;
|
||||
}
|
||||
|
||||
bool synchronizerAllReady() {
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].ready) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].ready) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void synchronizerStart() {
|
||||
//check if save file is present
|
||||
bool doLoad = false;
|
||||
char *loadName = NULL;
|
||||
|
||||
//host and single player need to load the actual file
|
||||
if(playerLocalID==0) {
|
||||
FILE *file = fopen(currentFileName, "rb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
doLoad = true;
|
||||
loadName = currentFileName;
|
||||
}
|
||||
//all others the transfered one
|
||||
} else {
|
||||
FILE *file = fopen("tmpTransfer.bin", "rb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
doLoad = true;
|
||||
loadName = "tmpTransfer.bin";
|
||||
}
|
||||
}
|
||||
|
||||
// reset random generators
|
||||
srand(synchronizerNextSeed);
|
||||
gaussrand(true);
|
||||
|
||||
//start the game
|
||||
startGame(doLoad, loadName);
|
||||
|
||||
//remove transfered save file from clients
|
||||
if(playerLocalID!=0) {
|
||||
FILE *file = fopen("tmpTransfer.bin", "rb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
remove("tmpTransfer.bin");
|
||||
}
|
||||
}
|
||||
|
||||
//clear menu
|
||||
currentMenu = MENU_NONE;
|
||||
|
||||
synchronizerRunning = true;
|
||||
synchronizerCurrentTicks = SYNCHRONIZER_TICKS_PER_TURN;
|
||||
//check if save file is present
|
||||
bool doLoad = false;
|
||||
char *loadName = NULL;
|
||||
|
||||
//host and single player need to load the actual file
|
||||
if(playerLocalID==0) {
|
||||
FILE *file = fopen(currentFileName, "rb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
doLoad = true;
|
||||
loadName = currentFileName;
|
||||
}
|
||||
//all others the transfered one
|
||||
} else {
|
||||
FILE *file = fopen("tmpTransfer.bin", "rb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
doLoad = true;
|
||||
loadName = "tmpTransfer.bin";
|
||||
}
|
||||
}
|
||||
|
||||
// reset random generators
|
||||
srand(synchronizerNextSeed);
|
||||
gaussrand(true);
|
||||
|
||||
//start the game
|
||||
startGame(doLoad, loadName);
|
||||
|
||||
//remove transfered save file from clients
|
||||
if(playerLocalID!=0) {
|
||||
FILE *file = fopen("tmpTransfer.bin", "rb");
|
||||
if(file!=NULL) {
|
||||
fclose(file);
|
||||
remove("tmpTransfer.bin");
|
||||
}
|
||||
}
|
||||
|
||||
//clear menu
|
||||
currentMenu = MENU_NONE;
|
||||
|
||||
synchronizerRunning = true;
|
||||
synchronizerCurrentTicks = SYNCHRONIZER_TICKS_PER_TURN;
|
||||
}
|
||||
|
||||
void synchronizerTick(void (*gtick)(void)) {
|
||||
if(synchronizerRunning && synchronizerTurnReady()) {
|
||||
synchronizerNextTurn();
|
||||
|
||||
// reset random generators
|
||||
srand(synchronizerNextSeed);
|
||||
gaussrand(true);
|
||||
|
||||
|
||||
syncTickCount++;
|
||||
|
||||
//call game tick
|
||||
(*gtick)();
|
||||
|
||||
synchronizerNextSeed = rand();
|
||||
}
|
||||
if(synchronizerRunning && synchronizerTurnReady()) {
|
||||
synchronizerNextTurn();
|
||||
|
||||
// reset random generators
|
||||
srand(synchronizerNextSeed);
|
||||
gaussrand(true);
|
||||
|
||||
|
||||
syncTickCount++;
|
||||
|
||||
//call game tick
|
||||
(*gtick)();
|
||||
|
||||
synchronizerNextSeed = rand();
|
||||
}
|
||||
}
|
||||
|
||||
//Test if all players (including single player) input is recieved
|
||||
bool synchronizerTurnReady() {
|
||||
if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) return true;
|
||||
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) return true;
|
||||
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
if(!players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void synchronizerNextTurn() {
|
||||
if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) {
|
||||
synchronizerCurrentTicks++;
|
||||
|
||||
//clicked events are only fired for the first tick per turn
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
resetClicked(&(players[i].inputs));
|
||||
}
|
||||
} else {
|
||||
//move nextInput of every player to currentInput
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
players[i].inputs = players[i].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)];
|
||||
players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = false;
|
||||
}
|
||||
|
||||
//Increase turn number
|
||||
synchronizerLocalTurn++;
|
||||
synchronizerCurrentTicks = 1;
|
||||
|
||||
//send local input
|
||||
synchronizerSendLocalInputs();
|
||||
}
|
||||
if(synchronizerCurrentTicks<SYNCHRONIZER_TICKS_PER_TURN) {
|
||||
synchronizerCurrentTicks++;
|
||||
|
||||
//clicked events are only fired for the first tick per turn
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
resetClicked(&(players[i].inputs));
|
||||
}
|
||||
} else {
|
||||
//move nextInput of every player to currentInput
|
||||
for(int i=0; i<playerCount; i++) {
|
||||
players[i].inputs = players[i].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)];
|
||||
players[i].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = false;
|
||||
}
|
||||
|
||||
//Increase turn number
|
||||
synchronizerLocalTurn++;
|
||||
synchronizerCurrentTicks = 1;
|
||||
|
||||
//send local input
|
||||
synchronizerSendLocalInputs();
|
||||
}
|
||||
}
|
||||
|
||||
void synchronizerSendLocalInputs() {
|
||||
//scan local inputs
|
||||
hidScanInput();
|
||||
tickKeys(&localInputs, hidKeysHeld(), hidKeysDown());
|
||||
|
||||
//store local input in nextInput
|
||||
players[playerLocalID].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)] = localInputs;
|
||||
players[playerLocalID].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = true;
|
||||
|
||||
//send local input
|
||||
if(playerCount>1) {
|
||||
size_t size = writeInputPacket(networkWriteBuffer, &localInputs, playerLocalID, synchronizerLocalTurn);
|
||||
networkSend(networkWriteBuffer, size);
|
||||
}
|
||||
//scan local inputs
|
||||
hidScanInput();
|
||||
tickKeys(&localInputs, hidKeysHeld(), hidKeysDown());
|
||||
|
||||
//store local input in nextInput
|
||||
players[playerLocalID].nextInputs[synchronizerGetTurnIndex(synchronizerLocalTurn)] = localInputs;
|
||||
players[playerLocalID].nextTurnReady[synchronizerGetTurnIndex(synchronizerLocalTurn)] = true;
|
||||
|
||||
//send local input
|
||||
if(playerCount>1) {
|
||||
size_t size = writeInputPacket(networkWriteBuffer, &localInputs, playerLocalID, synchronizerLocalTurn);
|
||||
networkSend(networkWriteBuffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
void synchronizerOnInputPacket(u8 playerID, u32 turnNumber, void *data, size_t dataSize) {
|
||||
if(turnNumber>=synchronizerLocalTurn && turnNumber<synchronizerLocalTurn+MAX_INPUT_BUFFER && playerID<playerCount) {
|
||||
if(readInputPacketData(data, dataSize, &(players[playerID].nextInputs[synchronizerGetTurnIndex(turnNumber)]))) {
|
||||
players[playerID].nextTurnReady[synchronizerGetTurnIndex(turnNumber)] = true;
|
||||
}
|
||||
}
|
||||
if(turnNumber>=synchronizerLocalTurn && turnNumber<synchronizerLocalTurn+MAX_INPUT_BUFFER && playerID<playerCount) {
|
||||
if(readInputPacketData(data, dataSize, &(players[playerID].nextInputs[synchronizerGetTurnIndex(turnNumber)]))) {
|
||||
players[playerID].nextTurnReady[synchronizerGetTurnIndex(turnNumber)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int synchronizerGetTurnIndex(u32 turn) {
|
||||
return turn%MAX_INPUT_BUFFER;
|
||||
return turn%MAX_INPUT_BUFFER;
|
||||
}
|
||||
|
||||
void synchronizerReset() {
|
||||
synchronizerRunning = false;
|
||||
synchronizerCurrentTicks = 0;
|
||||
synchronizerRunning = false;
|
||||
synchronizerCurrentTicks = 0;
|
||||
}
|
||||
|
||||
bool synchronizerIsRunning() {
|
||||
return synchronizerRunning;
|
||||
return synchronizerRunning;
|
||||
}
|
||||
|
||||
// helpers for random numbers
|
||||
|
@ -228,13 +228,13 @@ double gaussrand(bool reset)
|
|||
static double U, V;
|
||||
static int phase = 0;
|
||||
double Z;
|
||||
|
||||
if(reset) {
|
||||
U = 0;
|
||||
V = 0;
|
||||
phase = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(reset) {
|
||||
U = 0;
|
||||
V = 0;
|
||||
phase = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(phase == 0) {
|
||||
U = (rand() + 1.) / (RAND_MAX + 2.);
|
||||
|
@ -242,8 +242,8 @@ double gaussrand(bool reset)
|
|||
Z = sqrt(-2 * log(U)) * sin(2 * PI * V);
|
||||
} else {
|
||||
Z = sqrt(-2 * log(U)) * cos(2 * PI * V);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
phase = 1 - phase;
|
||||
|
||||
return Z;
|
||||
|
|
|
@ -11,203 +11,203 @@
|
|||
#define READ_SIZE 9216
|
||||
|
||||
int unzipAndLoad(char *filename, int (*fileCallback)(char *filename), char *expectedComment, int keepFiles) {
|
||||
// Open the zip file
|
||||
unzFile *zipfile = unzOpen(filename);
|
||||
if (zipfile == NULL) {
|
||||
return 1; // Error: ZipFile could not be opened.
|
||||
}
|
||||
|
||||
// Get info about the zip file
|
||||
unz_global_info global_info;
|
||||
if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK) {
|
||||
unzClose(zipfile);
|
||||
return 2; // Error: Could not read global info
|
||||
}
|
||||
|
||||
if(expectedComment!=NULL) {
|
||||
char *buffer = malloc(global_info.size_comment+1);
|
||||
if(buffer==NULL) {
|
||||
unzClose(zipfile);
|
||||
return 3; // Error: Could not read global comment
|
||||
}
|
||||
|
||||
if (unzGetGlobalComment(zipfile, buffer, global_info.size_comment+1) < 0) {
|
||||
unzClose(zipfile);
|
||||
return 3; // Error: Could not read global comment
|
||||
}
|
||||
|
||||
if (strcmp(expectedComment, buffer)!=0) {
|
||||
unzClose(zipfile);
|
||||
return 4; // Error: Global comment did not have expected value
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
// Buffer to hold data read from the zip file.
|
||||
void *read_buffer = malloc(READ_SIZE);
|
||||
if(read_buffer==NULL) {
|
||||
// Error: Could not allocate read buffer
|
||||
return 5;
|
||||
}
|
||||
// Open the zip file
|
||||
unzFile *zipfile = unzOpen(filename);
|
||||
if (zipfile == NULL) {
|
||||
return 1; // Error: ZipFile could not be opened.
|
||||
}
|
||||
|
||||
// Loop to extract all files
|
||||
uLong i;
|
||||
for (i = 0; i < global_info.number_entry; ++i) {
|
||||
// Get info about current file.
|
||||
unz_file_info file_info;
|
||||
char filename[MAX_FILENAME];
|
||||
if (unzGetCurrentFileInfo(zipfile, &file_info, filename, MAX_FILENAME, NULL, 0, NULL, 0 ) != UNZ_OK) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
return 6; // Error: Could not read file info
|
||||
}
|
||||
// Get info about the zip file
|
||||
unz_global_info global_info;
|
||||
if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK) {
|
||||
unzClose(zipfile);
|
||||
return 2; // Error: Could not read global info
|
||||
}
|
||||
|
||||
// Check if this entry is NOT a directory or file.
|
||||
const size_t filename_length = strlen(filename);
|
||||
if (filename[ filename_length-1 ] != dir_delimter){
|
||||
if (unzOpenCurrentFile( zipfile ) != UNZ_OK) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
return 7;
|
||||
}
|
||||
if(expectedComment!=NULL) {
|
||||
char *buffer = malloc(global_info.size_comment+1);
|
||||
if(buffer==NULL) {
|
||||
unzClose(zipfile);
|
||||
return 3; // Error: Could not read global comment
|
||||
}
|
||||
|
||||
// Open a file to write out the data.
|
||||
FILE * out = fopen(filename, "wb");
|
||||
if (out == NULL) {
|
||||
free(read_buffer);
|
||||
unzCloseCurrentFile(zipfile);
|
||||
unzClose(zipfile);
|
||||
return 8;
|
||||
}
|
||||
if (unzGetGlobalComment(zipfile, buffer, global_info.size_comment+1) < 0) {
|
||||
unzClose(zipfile);
|
||||
return 3; // Error: Could not read global comment
|
||||
}
|
||||
|
||||
int error = UNZ_OK;
|
||||
do {
|
||||
error = unzReadCurrentFile(zipfile, read_buffer, READ_SIZE);
|
||||
if ( error < 0 ) {
|
||||
//printf("error %d\n", error);
|
||||
free(read_buffer);
|
||||
unzCloseCurrentFile(zipfile);
|
||||
unzClose(zipfile);
|
||||
fclose(out);
|
||||
remove(filename);
|
||||
return 9;
|
||||
}
|
||||
if (strcmp(expectedComment, buffer)!=0) {
|
||||
unzClose(zipfile);
|
||||
return 4; // Error: Global comment did not have expected value
|
||||
}
|
||||
|
||||
// Write data to file.
|
||||
if (error > 0) {
|
||||
fwrite(read_buffer, error, 1, out); // You should check return of fwrite...
|
||||
}
|
||||
} while (error > 0);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
|
||||
//run callback
|
||||
if((*fileCallback)(filename) != 0) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
remove(filename);
|
||||
return 10; // Error: Callback error
|
||||
}
|
||||
|
||||
if(keepFiles==ZIPHELPER_CLEANUP_FILES) {
|
||||
remove(filename);
|
||||
}
|
||||
}
|
||||
// Buffer to hold data read from the zip file.
|
||||
void *read_buffer = malloc(READ_SIZE);
|
||||
if(read_buffer==NULL) {
|
||||
// Error: Could not allocate read buffer
|
||||
return 5;
|
||||
}
|
||||
|
||||
unzCloseCurrentFile(zipfile);
|
||||
// Loop to extract all files
|
||||
uLong i;
|
||||
for (i = 0; i < global_info.number_entry; ++i) {
|
||||
// Get info about current file.
|
||||
unz_file_info file_info;
|
||||
char filename[MAX_FILENAME];
|
||||
if (unzGetCurrentFileInfo(zipfile, &file_info, filename, MAX_FILENAME, NULL, 0, NULL, 0 ) != UNZ_OK) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
return 6; // Error: Could not read file info
|
||||
}
|
||||
|
||||
// Go the the next entry listed in the zip file.
|
||||
if (( i+1 ) < global_info.number_entry) {
|
||||
if (unzGoToNextFile( zipfile ) != UNZ_OK) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
return 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
|
||||
return 0;
|
||||
// Check if this entry is NOT a directory or file.
|
||||
const size_t filename_length = strlen(filename);
|
||||
if (filename[ filename_length-1 ] != dir_delimter){
|
||||
if (unzOpenCurrentFile( zipfile ) != UNZ_OK) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
return 7;
|
||||
}
|
||||
|
||||
// Open a file to write out the data.
|
||||
FILE * out = fopen(filename, "wb");
|
||||
if (out == NULL) {
|
||||
free(read_buffer);
|
||||
unzCloseCurrentFile(zipfile);
|
||||
unzClose(zipfile);
|
||||
return 8;
|
||||
}
|
||||
|
||||
int error = UNZ_OK;
|
||||
do {
|
||||
error = unzReadCurrentFile(zipfile, read_buffer, READ_SIZE);
|
||||
if ( error < 0 ) {
|
||||
//printf("error %d\n", error);
|
||||
free(read_buffer);
|
||||
unzCloseCurrentFile(zipfile);
|
||||
unzClose(zipfile);
|
||||
fclose(out);
|
||||
remove(filename);
|
||||
return 9;
|
||||
}
|
||||
|
||||
// Write data to file.
|
||||
if (error > 0) {
|
||||
fwrite(read_buffer, error, 1, out); // You should check return of fwrite...
|
||||
}
|
||||
} while (error > 0);
|
||||
|
||||
fclose(out);
|
||||
|
||||
//run callback
|
||||
if((*fileCallback)(filename) != 0) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
remove(filename);
|
||||
return 10; // Error: Callback error
|
||||
}
|
||||
|
||||
if(keepFiles==ZIPHELPER_CLEANUP_FILES) {
|
||||
remove(filename);
|
||||
}
|
||||
}
|
||||
|
||||
unzCloseCurrentFile(zipfile);
|
||||
|
||||
// Go the the next entry listed in the zip file.
|
||||
if (( i+1 ) < global_info.number_entry) {
|
||||
if (unzGoToNextFile( zipfile ) != UNZ_OK) {
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
return 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(read_buffer);
|
||||
unzClose(zipfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zipFiles(char *filename, char **files, int fileCount, int mode, char *comment) {
|
||||
// Set mode
|
||||
int zipMode = mode==ZIPHELPER_ADD ? APPEND_STATUS_ADDINZIP : APPEND_STATUS_CREATE;
|
||||
FILE *testFile = fopen(filename, "r");
|
||||
if(testFile!=NULL) {
|
||||
fclose(testFile);
|
||||
} else {
|
||||
zipMode = APPEND_STATUS_CREATE;
|
||||
}
|
||||
|
||||
// Open the zip file
|
||||
zipFile *zipfile = zipOpen(filename, zipMode);
|
||||
if (zipfile == NULL) return 1; // Error: ZipFile could not be opened.
|
||||
|
||||
// Buffer to hold data read from the files.
|
||||
void *read_buffer = malloc(READ_SIZE);
|
||||
if(read_buffer==NULL) {
|
||||
// Error: Could not allocate read buffer
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Loop all files to add
|
||||
for(int i = 0; i < fileCount; i++) {
|
||||
// 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) {
|
||||
free(read_buffer);
|
||||
zipClose(zipfile, "");
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Open a file to read the data.
|
||||
FILE *in = fopen(files[i], "rb");
|
||||
if (in == NULL) {
|
||||
free(read_buffer);
|
||||
zipCloseFileInZip(zipfile);
|
||||
zipClose(zipfile, "");
|
||||
return 4;
|
||||
}
|
||||
// Set mode
|
||||
int zipMode = mode==ZIPHELPER_ADD ? APPEND_STATUS_ADDINZIP : APPEND_STATUS_CREATE;
|
||||
FILE *testFile = fopen(filename, "r");
|
||||
if(testFile!=NULL) {
|
||||
fclose(testFile);
|
||||
} else {
|
||||
zipMode = APPEND_STATUS_CREATE;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
do
|
||||
{
|
||||
size = fread(read_buffer, 1, READ_SIZE, in);
|
||||
|
||||
|
||||
if(size<READ_SIZE) {
|
||||
if(!feof(in)) {
|
||||
free(read_buffer);
|
||||
zipCloseFileInZip(zipfile);
|
||||
zipClose(zipfile, "");
|
||||
fclose(in);
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
if(size>0) {
|
||||
//write data to zip
|
||||
if (zipWriteInFileInZip(zipfile, read_buffer, size) != ZIP_OK) {
|
||||
//printf("error %d\n", error);
|
||||
free(read_buffer);
|
||||
zipCloseFileInZip(zipfile);
|
||||
zipClose(zipfile, "");
|
||||
fclose(in);
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
} while (size > 0);
|
||||
// Open the zip file
|
||||
zipFile *zipfile = zipOpen(filename, zipMode);
|
||||
if (zipfile == NULL) return 1; // Error: ZipFile could not be opened.
|
||||
|
||||
fclose(in);
|
||||
// Buffer to hold data read from the files.
|
||||
void *read_buffer = malloc(READ_SIZE);
|
||||
if(read_buffer==NULL) {
|
||||
// Error: Could not allocate read buffer
|
||||
return 2;
|
||||
}
|
||||
|
||||
zipCloseFileInZip(zipfile);
|
||||
}
|
||||
|
||||
free(read_buffer);
|
||||
zipClose(zipfile, comment);
|
||||
|
||||
return 0;
|
||||
// Loop all files to add
|
||||
for(int i = 0; i < fileCount; i++) {
|
||||
// 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) {
|
||||
free(read_buffer);
|
||||
zipClose(zipfile, "");
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Open a file to read the data.
|
||||
FILE *in = fopen(files[i], "rb");
|
||||
if (in == NULL) {
|
||||
free(read_buffer);
|
||||
zipCloseFileInZip(zipfile);
|
||||
zipClose(zipfile, "");
|
||||
return 4;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
do
|
||||
{
|
||||
size = fread(read_buffer, 1, READ_SIZE, in);
|
||||
|
||||
|
||||
if(size<READ_SIZE) {
|
||||
if(!feof(in)) {
|
||||
free(read_buffer);
|
||||
zipCloseFileInZip(zipfile);
|
||||
zipClose(zipfile, "");
|
||||
fclose(in);
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
if(size>0) {
|
||||
//write data to zip
|
||||
if (zipWriteInFileInZip(zipfile, read_buffer, size) != ZIP_OK) {
|
||||
//printf("error %d\n", error);
|
||||
free(read_buffer);
|
||||
zipCloseFileInZip(zipfile);
|
||||
zipClose(zipfile, "");
|
||||
fclose(in);
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
} while (size > 0);
|
||||
|
||||
fclose(in);
|
||||
|
||||
zipCloseFileInZip(zipfile);
|
||||
}
|
||||
|
||||
free(read_buffer);
|
||||
zipClose(zipfile, comment);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <3ds.h>
|
||||
#include <sf2d.h>
|
||||
#include <sfil.h>
|
||||
#include <string.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -25,27 +25,29 @@
|
|||
|
||||
//TODO: Something still causes desyncs very rarely
|
||||
|
||||
static aptHookCookie cookie;
|
||||
|
||||
void setupGame() {
|
||||
synchronizerInit(rand(), 1, 0);
|
||||
synchronizerSetPlayerUID(0, localUID);
|
||||
synchronizerStart();
|
||||
|
||||
|
||||
initGame = 0;
|
||||
}
|
||||
|
||||
void setupGameServer() {
|
||||
size_t size;
|
||||
|
||||
|
||||
networkHostStopConnections();
|
||||
|
||||
|
||||
networkStart();
|
||||
|
||||
|
||||
//send start info (seed)
|
||||
size = writeStartPacket(networkWriteBuffer, rand());
|
||||
networkSend(networkWriteBuffer, size);
|
||||
processPacket(networkWriteBuffer, size);
|
||||
networkSendWaitFlush();
|
||||
|
||||
|
||||
//send save file if loading
|
||||
FILE *file = fopen(currentFileName, "rb");
|
||||
if(file!=NULL) {
|
||||
|
@ -53,12 +55,12 @@ void setupGameServer() {
|
|||
networkSendWaitFlush();
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
||||
//send start command
|
||||
size = writeStartRequestPacket(networkWriteBuffer);
|
||||
networkSend(networkWriteBuffer, size);
|
||||
processPacket(networkWriteBuffer, size);
|
||||
|
||||
|
||||
initMPGame = 0;
|
||||
}
|
||||
|
||||
|
@ -66,17 +68,27 @@ void setupBGMap() {
|
|||
// Reset entity manager.
|
||||
memset(&eManager, 0, sizeof(eManager));
|
||||
sf2d_set_clear_color(0xFF6C6D82);
|
||||
|
||||
|
||||
|
||||
srand(time(NULL));
|
||||
createAndValidateTopMap(128, 128, 1, worldData.map[1], worldData.data[1]);
|
||||
|
||||
|
||||
// Reset entity manager.
|
||||
memset(&eManager, 0, sizeof(eManager));
|
||||
sf2d_set_clear_color(0xFF6C6D82);
|
||||
|
||||
|
||||
initBGMap = 0;
|
||||
}
|
||||
static void task_apt_hook(APT_HookType hook, void* param) {
|
||||
switch(hook) {
|
||||
case APTHOOK_ONSUSPEND:
|
||||
paused = true;
|
||||
stopMusic();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//for rendering -> move to a better place
|
||||
|
@ -99,49 +111,49 @@ int main() {
|
|||
sf2d_init();
|
||||
csndInit();
|
||||
networkInit();
|
||||
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
|
||||
//load or create localUID
|
||||
if ((file = fopen("m3ds_uid.bin", "rb"))) {
|
||||
fread(&localUID, sizeof(u32), 1, file);
|
||||
fclose(file);
|
||||
} else {
|
||||
localUID = (((u32) (rand()%256))<<24) | (((u32) (rand()%256))<<16) | (((u32) (rand()%256))<<8) | (((u32) (rand()%256)));
|
||||
|
||||
|
||||
if ((file = fopen("m3ds_uid.bin", "wb"))) {
|
||||
fwrite(&localUID, sizeof(u32), 1, file);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
noItem = newItem(ITEM_NULL, 0);
|
||||
|
||||
|
||||
initMenus();
|
||||
currentMenu = MENU_TITLE;
|
||||
currentSelection = 0;
|
||||
quitGame = false;
|
||||
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);
|
||||
font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM);
|
||||
bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM);
|
||||
|
||||
loadSounds();
|
||||
playMusic(&music_menu);
|
||||
|
||||
|
||||
bakeLights();
|
||||
|
||||
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 6; ++i) {
|
||||
minimap[i] = sf2d_create_texture(128, 128, TEXFMT_RGBA8, SF2D_PLACE_RAM);
|
||||
sf2d_texture_tile32(minimap[i]);
|
||||
}
|
||||
|
||||
|
||||
reloadColors();
|
||||
|
||||
|
||||
sf2d_set_vblank_wait(true);
|
||||
|
||||
sf2d_set_clear_color(0xFF);
|
||||
|
@ -151,22 +163,26 @@ int main() {
|
|||
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_right.input = KEY_DRIGHT | KEY_CPAD_RIGHT | KEY_CSTICK_RIGHT;
|
||||
localInputs.k_attack.input = KEY_A | KEY_B | KEY_L | KEY_ZR;
|
||||
localInputs.k_menu.input = KEY_X | KEY_Y | KEY_R | KEY_ZL;
|
||||
localInputs.k_attack.input = KEY_A;
|
||||
localInputs.k_pickup.input = KEY_B;
|
||||
localInputs.k_use.input = KEY_X;
|
||||
localInputs.k_menu.input = KEY_Y ;
|
||||
localInputs.k_pause.input = KEY_START;
|
||||
localInputs.k_accept.input = KEY_A;
|
||||
localInputs.k_decline.input = KEY_B;
|
||||
localInputs.k_delete.input = KEY_X;
|
||||
localInputs.k_menuNext.input = KEY_R;
|
||||
localInputs.k_menuPrev.input = KEY_L;
|
||||
localInputs.k_menuNext.input = KEY_R | KEY_ZR;
|
||||
localInputs.k_menuPrev.input = KEY_L | KEY_ZL;
|
||||
|
||||
/* If btnSave exists, then use that. */
|
||||
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_left.input), sizeof(int), 1, file);
|
||||
fread(&(localInputs.k_right.input), sizeof(int), 1, file);
|
||||
fread(&(localInputs.k_attack.input), sizeof(int), 1, file);
|
||||
fread(&(localInputs.k_pickup.input), sizeof(int), 1, file);
|
||||
fread(&(localInputs.k_use.input), sizeof(int), 1, file);
|
||||
fread(&(localInputs.k_menu.input), sizeof(int), 1, file);
|
||||
fread(&(localInputs.k_pause.input), sizeof(int), 1, file);
|
||||
fread(&(localInputs.k_accept.input), sizeof(int), 1, file);
|
||||
|
@ -176,25 +192,27 @@ int main() {
|
|||
fread(&(localInputs.k_menuPrev.input), sizeof(int), 1, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
||||
/* If lastTP exists, then use that. */
|
||||
if ((file = fopen("lastTP.bin", "r"))) {
|
||||
char fnbuf[256];
|
||||
fgets(fnbuf, 256, file); // get directory to texturepack
|
||||
loadTexturePack(fnbuf);
|
||||
loadTexturePack(fnbuf);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
||||
initPlayers();
|
||||
initRecipes();
|
||||
initTrades();
|
||||
aptHook(&cookie, task_apt_hook, NULL);
|
||||
while (aptMainLoop()) {
|
||||
if (paused == true) playMusic(&music_menu);
|
||||
if (quitGame) break;
|
||||
|
||||
if (initGame > 0 && --initGame==0) setupGame();
|
||||
if (initMPGame > 0 && --initMPGame==0) setupGameServer();
|
||||
if (initBGMap > 0 && --initBGMap==0) setupBGMap();
|
||||
|
||||
|
||||
if (currentMenu == MENU_NONE) {
|
||||
tickGame();
|
||||
renderGame();
|
||||
|
@ -202,14 +220,14 @@ int main() {
|
|||
//input scanning ingame is handled by the synchronizer
|
||||
hidScanInput();
|
||||
tickKeys(&localInputs, hidKeysHeld(), hidKeysDown());
|
||||
|
||||
|
||||
tickMenu(currentMenu);
|
||||
renderMenu(currentMenu, xscr, yscr);
|
||||
}
|
||||
|
||||
sf2d_swapbuffers();
|
||||
}
|
||||
|
||||
|
||||
stopMusic();
|
||||
|
||||
freeTrades();
|
||||
|
|
|
@ -10,91 +10,91 @@ bool texturepackUseDefaultFont = true;
|
|||
bool texturepackUseDefaultBottom = true;
|
||||
|
||||
void toLowerString(char * str){
|
||||
int i;
|
||||
for (i = 0; str[i] != '\0'; i++)str[i] = (char)tolower((unsigned char)str[i]);
|
||||
int i;
|
||||
for (i = 0; str[i] != '\0'; i++)str[i] = (char)tolower((unsigned char)str[i]);
|
||||
}
|
||||
|
||||
int getTexturePackComment(char * filename, char * cmmtBuf){
|
||||
|
||||
// Open the zip file
|
||||
unzFile *zipfile = unzOpen(filename);
|
||||
if ( zipfile == NULL ) return 1; // Error: ZipFile could not be opened.
|
||||
|
||||
// Get info about the zip file
|
||||
unz_global_info global_info;
|
||||
if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK )
|
||||
{
|
||||
unzClose( zipfile );
|
||||
return 2; // Error: Could not read global info
|
||||
}
|
||||
|
||||
unzGetGlobalComment(zipfile, cmmtBuf, 58);
|
||||
// Open the zip file
|
||||
unzFile *zipfile = unzOpen(filename);
|
||||
if ( zipfile == NULL ) return 1; // Error: ZipFile could not be opened.
|
||||
|
||||
unzClose( zipfile );
|
||||
// Get info about the zip file
|
||||
unz_global_info global_info;
|
||||
if (unzGetGlobalInfo(zipfile, &global_info ) != UNZ_OK )
|
||||
{
|
||||
unzClose( zipfile );
|
||||
return 2; // Error: Could not read global info
|
||||
}
|
||||
|
||||
return 0;
|
||||
unzGetGlobalComment(zipfile, cmmtBuf, 58);
|
||||
|
||||
unzClose( zipfile );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loadTexture(char * filename) {
|
||||
char lowerFilename[MAX_FILENAME];
|
||||
strcpy(lowerFilename,filename);
|
||||
toLowerString(lowerFilename);
|
||||
|
||||
if(strcmp(lowerFilename, "icons.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
icons = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
reloadColors();
|
||||
|
||||
texturepackUseDefaultIcons = false;
|
||||
} else if(strcmp(lowerFilename, "player.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
playerSprites = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
|
||||
texturepackUseDefaultPlayer = false;
|
||||
} else if(strcmp(lowerFilename, "font.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
font = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
|
||||
texturepackUseDefaultFont = false;
|
||||
} else if(strcmp(lowerFilename, "bottombg.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
bottombg = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
|
||||
texturepackUseDefaultBottom = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
char lowerFilename[MAX_FILENAME];
|
||||
strcpy(lowerFilename,filename);
|
||||
toLowerString(lowerFilename);
|
||||
|
||||
if(strcmp(lowerFilename, "icons.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
icons = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
reloadColors();
|
||||
|
||||
texturepackUseDefaultIcons = false;
|
||||
} else if(strcmp(lowerFilename, "player.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
playerSprites = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
|
||||
texturepackUseDefaultPlayer = false;
|
||||
} else if(strcmp(lowerFilename, "font.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
font = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
|
||||
texturepackUseDefaultFont = false;
|
||||
} else if(strcmp(lowerFilename, "bottombg.png") == 0){
|
||||
if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
bottombg = sfil_load_PNG_file(filename, SF2D_PLACE_RAM);
|
||||
|
||||
texturepackUseDefaultBottom = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loadTexturePack(char * filename) {
|
||||
texturepackUseDefaultIcons = true;
|
||||
texturepackUseDefaultPlayer = true;
|
||||
texturepackUseDefaultFont = true;
|
||||
texturepackUseDefaultBottom = true;
|
||||
texturepackUseDefaultIcons = true;
|
||||
texturepackUseDefaultPlayer = true;
|
||||
texturepackUseDefaultFont = true;
|
||||
texturepackUseDefaultBottom = true;
|
||||
|
||||
if(unzipAndLoad(filename, &loadTexture, NULL, ZIPHELPER_CLEANUP_FILES)!=0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(texturepackUseDefaultIcons){
|
||||
icons = sfil_load_PNG_buffer(icons2_png, SF2D_PLACE_RAM);
|
||||
reloadColors();
|
||||
}
|
||||
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(texturepackUseDefaultBottom) bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM);
|
||||
if(unzipAndLoad(filename, &loadTexture, NULL, ZIPHELPER_CLEANUP_FILES)!=0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if(texturepackUseDefaultIcons){
|
||||
icons = sfil_load_PNG_buffer(icons_png, SF2D_PLACE_RAM);
|
||||
reloadColors();
|
||||
}
|
||||
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(texturepackUseDefaultBottom) bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue