diff --git a/.gitattributes b/.gitattributes old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 index ec8a370..655af00 --- a/.gitignore +++ b/.gitignore @@ -46,15 +46,9 @@ Temporary Items *.3dsx *.elf *.smdh -*.cia -*.3ds -*.icn -*.bnr build # Eclipse .settings .cproject .project - -# Copyrighted Executables diff --git a/Makefile b/Makefile old mode 100755 new mode 100644 index 7b9264e..4f57573 --- a/Makefile +++ b/Makefile @@ -26,18 +26,15 @@ include $(DEVKITARM)/3ds_rules # - icon.png # - /default_icon.png #--------------------------------------------------------------------------------- -TARGET := result/Minicraft3DS -ICON_TARGET := icons-banners/icon -RESULT := result +TARGET := Minicraft3DS BUILD := build SOURCES := source source/minizip DATA := data INCLUDES := include -ROMFS := romfs -APP_TITLE := Minicraft 3DS -APP_DESCRIPTION := Originally created by Notch. -APP_AUTHOR := Davideesk/andre111/ElijahZAwesome/tognee +APP_TITLE := Test +APP_DESCRIPTION := ??? +APP_AUTHOR := Davideesk #--------------------------------------------------------------------------------- # options for code generation @@ -55,7 +52,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lsfil -lpng -ljpeg -lz -lsf2d -lcitro3d -lctru -lm +LIBS := -lsfil -lpng -ljpeg -lz -lsf2d -lctru -lm #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing @@ -109,7 +106,13 @@ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) ifeq ($(strip $(ICON)),) icons := $(wildcard *.png) - export APP_ICON := $(TOPDIR)/$(ICON_TARGET).png + ifneq (,$(findstring $(TARGET).png,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).png + else + ifneq (,$(findstring icon.png,$(icons))) + export APP_ICON := $(TOPDIR)/icon.png + endif + endif else export APP_ICON := $(TOPDIR)/$(ICON) endif @@ -118,17 +121,12 @@ ifeq ($(strip $(NO_SMDH)),) export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh endif -ifneq ($(ROMFS),) - export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) -endif - .PHONY: $(BUILD) clean all #--------------------------------------------------------------------------------- all: $(BUILD) $(BUILD): - @test -d $(RESULT) || mkdir $(RESULT) @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile @@ -141,12 +139,12 @@ $(TARGET)-strip.elf: $(BUILD) @$(STRIP) $(TARGET).elf -o $(TARGET)-strip.elf #--------------------------------------------------------------------------------- cci: $(TARGET)-strip.elf - @makerom -f cci -rsf resources/$(TARGET).rsf -target d -exefslogo -elf $(TARGET)-strip.elf -o $(TARGET).3ds -desc App:0x1B - @echo "built ... Minicraft3DS.3ds" + @makerom -f cci -rsf resources/$(TARGET).rsf -target d -exefslogo -elf $(TARGET)-strip.elf -o $(TARGET).3ds + @echo "built ... sfil_sample.3ds" #--------------------------------------------------------------------------------- cia: $(TARGET)-strip.elf - @makerom -f cia -o $(TARGET).cia -elf $(TARGET)-strip.elf -rsf icons-banners/$(TARGET).rsf -exefslogo -target t - @echo "built ... Minicraft3DS.cia" + @makerom -f cia -o $(TARGET).cia -elf $(TARGET)-strip.elf -rsf resources/$(TARGET).rsf -exefslogo -target t + @echo "built ... sfil_sample.cia" #--------------------------------------------------------------------------------- send: $(BUILD) @3dslink $(TARGET).3dsx diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 8ca113f..afde096 --- a/README.md +++ b/README.md @@ -1,78 +1,21 @@ # Minicraft3DS -3DS Homebrew port of Notch's ludum dare game "Minicraft" -Current Version: Version 1.6.1 +3DS Homebrew port of Notch's ludum dare game "Minicraft" ----------- +Dependencies: -**Download:** +ctrulib by smea: https://github.com/smealum/ctrulib -If you just want to download the game prebuilt check the releases tab in Github: -//TODO -For building the game yourself look below. +sf2dlib by xerpi: https://github.com/xerpi/sf2dlib +sfillib by xerpi: https://github.com/xerpi/sfillib ----------- +zlib: http://www.zlib.net/ +Current Version: Version 1.1 -**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. +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: //TODO +Forum thread: https://gbatemp.net/threads/release-beta-minicraft-3ds-homebrew-edition.399295/ diff --git a/build.bat b/build.bat deleted file mode 100755 index c0d9181..0000000 --- a/build.bat +++ /dev/null @@ -1,17 +0,0 @@ -@echo off -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 "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... -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 -romfs icons-banners/romfs.bin -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 -romfs icons-banners/romfs.bin -echo Cleaning Up... -del /s result\Minicraft3DS.elf -del /s result\Minicraft3DS.smdh -pause diff --git a/build.sh b/build.sh deleted file mode 100755 index 7c7871d..0000000 --- a/build.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/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 diff --git a/data/Font.png b/data/Font.png old mode 100755 new mode 100644 diff --git a/data/bottombg.png b/data/bottombg.png old mode 100755 new mode 100644 diff --git a/data/icons.png b/data/icons.png deleted file mode 100755 index 184fbd2..0000000 Binary files a/data/icons.png and /dev/null differ diff --git a/data/icons2.png b/data/icons2.png new file mode 100644 index 0000000..7059007 Binary files /dev/null and b/data/icons2.png differ diff --git a/data/player.png b/data/player.png deleted file mode 100644 index 53e8a3c..0000000 Binary files a/data/player.png and /dev/null differ diff --git a/icons-banners/Minicraft3DS.rsf b/icons-banners/Minicraft3DS.rsf deleted file mode 100755 index 52914d9..0000000 --- a/icons-banners/Minicraft3DS.rsf +++ /dev/null @@ -1,195 +0,0 @@ -BasicInfo: - Title : "Cia Builder Example" - CompanyCode : "00" - ProductCode : "CTR-P-PWDR" - ContentType : Application - Logo : Homebrew # Nintendo / Licensed / Distributed / iQue / iQueForSystem - -TitleInfo: - UniqueId : 0xFAA5C # Cia Builder Example Unique ID, you need to set your own one - Category : Application - -CardInfo: - MediaSize : 128MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB - MediaType : Card1 # Card1 / Card2 - CardDevice : None # NorFlash(Pick this if you use savedata) / None - - -Option: - UseOnSD : true # true if App is to be installed to SD - FreeProductCode : true # Removes limitations on ProductCode - MediaFootPadding : false # If true CCI files are created with padding - EnableCrypt : false # Enables encryption for NCCH and CIA - EnableCompress : true # Compresses exefs code - -AccessControlInfo: - #UseExtSaveData : true - #ExtSaveDataId: 0xff3ff - #UseExtendedSaveDataAccessControl: true - #AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606] - -SystemControlInfo: - SaveDataSize: 128KB - RemasterVersion: 0 - StackSize: 0x40000 - -# DO NOT EDIT BELOW HERE OR PROGRAMS WILL NOT LAUNCH (most likely) - -AccessControlInfo: - FileSystemAccess: - - Debug - - DirectSdmc - - DirectSdmcWrite - - IdealProcessor : 0 - AffinityMask : 1 - - Priority : 16 - - MaxCpu : 0x9E # Default - DisableDebug : false - EnableForceDebug : false - CanWriteSharedPage : false - CanUsePrivilegedPriority : false - CanUseNonAlphabetAndNumber : false - PermitMainFunctionArgument : false - CanShareDeviceMemory : false - RunnableOnSleep : false - SpecialMemoryArrange : false - CoreVersion : 2 - DescVersion : 2 - - ReleaseKernelMajor : "02" - ReleaseKernelMinor : "33" - MemoryType : Application - HandleTableSize: 512 - - SystemModeExt : Legacy # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode - CpuSpeed : 804MHz # 268MHz(Default)/804MHz - EnableL2Cache : true # false(default)/true - CanAccessCore2 : true - - IORegisterMapping: - - 1ff50000-1ff57fff - - 1ff70000-1ff77fff - MemoryMapping: - - 1f000000-1f5fffff:r - SystemCallAccess: - ArbitrateAddress: 34 - Break: 60 - CancelTimer: 28 - ClearEvent: 25 - ClearTimer: 29 - CloseHandle: 35 - ConnectToPort: 45 - ControlMemory: 1 - CreateAddressArbiter: 33 - CreateEvent: 23 - CreateMemoryBlock: 30 - CreateMutex: 19 - CreateSemaphore: 21 - CreateThread: 8 - CreateTimer: 26 - DuplicateHandle: 39 - ExitProcess: 3 - ExitThread: 9 - GetCurrentProcessorNumber: 17 - GetHandleInfo: 41 - GetProcessId: 53 - GetProcessIdOfThread: 54 - GetProcessIdealProcessor: 6 - GetProcessInfo: 43 - GetResourceLimit: 56 - GetResourceLimitCurrentValues: 58 - GetResourceLimitLimitValues: 57 - GetSystemInfo: 42 - GetSystemTick: 40 - GetThreadContext: 59 - GetThreadId: 55 - GetThreadIdealProcessor: 15 - GetThreadInfo: 44 - GetThreadPriority: 11 - MapMemoryBlock: 31 - OutputDebugString: 61 - QueryMemory: 2 - ReleaseMutex: 20 - ReleaseSemaphore: 22 - SendSyncRequest1: 46 - SendSyncRequest2: 47 - SendSyncRequest3: 48 - SendSyncRequest4: 49 - SendSyncRequest: 50 - SetThreadPriority: 12 - SetTimer: 27 - SignalEvent: 24 - SleepThread: 10 - UnmapMemoryBlock: 32 - WaitSynchronization1: 36 - WaitSynchronizationN: 37 - InterruptNumbers: - ServiceAccessControl: - - APT:U - - $hioFIO - - $hostio0 - - $hostio1 - - ac:u - - boss:U - - cam:u - - ir:rst - - cfg:u - - dlp:FKCL - - dlp:SRVR - - dsp::DSP - - frd:u - - fs:USER - - gsp::Gpu - - hid:USER - - http:C - - mic:u - - ndm:u - - news:s - - nwm::UDS - - ptm:u - - pxi:dev - - soc:U - - gsp::Lcd - - y2r:u - - ldr:ro - - ir:USER - - ir:u - - csnd:SND - - am:u - - ns:s - -SystemControlInfo: - Dependency: - ac: 0x0004013000002402L - am: 0x0004013000001502L - boss: 0x0004013000003402L - camera: 0x0004013000001602L - cecd: 0x0004013000002602L - cfg: 0x0004013000001702L - codec: 0x0004013000001802L - csnd: 0x0004013000002702L - dlp: 0x0004013000002802L - dsp: 0x0004013000001a02L - friends: 0x0004013000003202L - gpio: 0x0004013000001b02L - gsp: 0x0004013000001c02L - hid: 0x0004013000001d02L - http: 0x0004013000002902L - i2c: 0x0004013000001e02L - ir: 0x0004013000003302L - mcu: 0x0004013000001f02L - mic: 0x0004013000002002L - ndm: 0x0004013000002b02L - news: 0x0004013000003502L - nim: 0x0004013000002c02L - nwm: 0x0004013000002d02L - pdn: 0x0004013000002102L - ps: 0x0004013000003102L - ptm: 0x0004013000002202L - ro: 0x0004013000003702L - socket: 0x0004013000002e02L - spi: 0x0004013000002302L - ssl: 0x0004013000002f02L \ No newline at end of file diff --git a/icons-banners/audio.wav b/icons-banners/audio.wav deleted file mode 100755 index 7f3b2f0..0000000 Binary files a/icons-banners/audio.wav and /dev/null differ diff --git a/icons-banners/banner.png b/icons-banners/banner.png deleted file mode 100755 index 45b47c1..0000000 Binary files a/icons-banners/banner.png and /dev/null differ diff --git a/icons-banners/icon.png b/icons-banners/icon.png deleted file mode 100755 index ce37e18..0000000 Binary files a/icons-banners/icon.png and /dev/null differ diff --git a/icons-banners/romfs.bin b/icons-banners/romfs.bin deleted file mode 100644 index 20e6c8f..0000000 Binary files a/icons-banners/romfs.bin and /dev/null differ diff --git a/romfs/resources/bossdeath.raw b/resources/bossdeath.raw similarity index 100% rename from romfs/resources/bossdeath.raw rename to resources/bossdeath.raw diff --git a/romfs/resources/craft.raw b/resources/craft.raw similarity index 100% rename from romfs/resources/craft.raw rename to resources/craft.raw diff --git a/romfs/resources/death.raw b/resources/death.raw similarity index 100% rename from romfs/resources/death.raw rename to resources/death.raw diff --git a/romfs/resources/monsterhurt.raw b/resources/monsterhurt.raw similarity index 100% rename from romfs/resources/monsterhurt.raw rename to resources/monsterhurt.raw diff --git a/romfs/resources/music/floor0.raw b/resources/music/floor0.raw similarity index 100% rename from romfs/resources/music/floor0.raw rename to resources/music/floor0.raw diff --git a/romfs/resources/music/floor1.raw b/resources/music/floor1.raw similarity index 100% rename from romfs/resources/music/floor1.raw rename to resources/music/floor1.raw diff --git a/romfs/resources/music/floor2_3.raw b/resources/music/floor2_3.raw similarity index 100% rename from romfs/resources/music/floor2_3.raw rename to resources/music/floor2_3.raw diff --git a/romfs/resources/music/floor4.raw b/resources/music/floor4.raw similarity index 100% rename from romfs/resources/music/floor4.raw rename to resources/music/floor4.raw diff --git a/romfs/resources/music/menu.raw b/resources/music/menu.raw similarity index 100% rename from romfs/resources/music/menu.raw rename to resources/music/menu.raw diff --git a/romfs/resources/pickup.raw b/resources/pickup.raw similarity index 100% rename from romfs/resources/pickup.raw rename to resources/pickup.raw diff --git a/romfs/resources/playerhurt.raw b/resources/playerhurt.raw similarity index 100% rename from romfs/resources/playerhurt.raw rename to resources/playerhurt.raw diff --git a/romfs/resources/test.raw b/resources/test.raw similarity index 100% rename from romfs/resources/test.raw rename to resources/test.raw diff --git a/romfs/resources/music/floor1_night.raw b/romfs/resources/music/floor1_night.raw deleted file mode 100644 index 1474c1b..0000000 Binary files a/romfs/resources/music/floor1_night.raw and /dev/null differ diff --git a/source/Crafting.c b/source/Crafting.c old mode 100755 new mode 100644 index c6ef4ff..98d1cbb --- a/source/Crafting.c +++ b/source/Crafting.c @@ -1,193 +1,137 @@ #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); -} - 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;inumOfCosts;++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;inumOfCosts;++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 #include "Item.h" -typedef struct _recipecost { - int costItem; - int costAmount; +typedef struct { + 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. +typedef struct { + 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; +typedef struct { + int size; + Recipe * recipes; } RecipeManager; -RecipeManager inHeadRecipes; + RecipeManager workbenchRecipes; RecipeManager furnaceRecipes; RecipeManager ovenRecipes; RecipeManager anvilRecipes; -RecipeManager loomRecipes; -RecipeManager enchanterRecipes; -RecipeManager potionMakerRecipes; -Recipe defineRecipe(int item, int amountOrLevel, int numArgs, ...); - -void cloneRecipeManager(RecipeManager *from, RecipeManager *to); void checkCanCraftRecipes(RecipeManager * rm, Inventory * inv); void sortRecipes(RecipeManager * rm); bool craftItem(RecipeManager * rm, Recipe* r, Inventory* inv); diff --git a/source/Entity.c b/source/Entity.c old mode 100755 new mode 100644 index 37db8c8..57c4503 --- a/source/Entity.c +++ b/source/Entity.c @@ -1,363 +1,204 @@ #include "Entity.h" -#include "Synchronizer.h" +#define PI 3.141592654 +double gaussrand() +{ + static double U, V; + static int phase = 0; + double Z; + + if(phase == 0) { + U = (rand() + 1.) / (RAND_MAX + 2.); + V = rand() / (RAND_MAX + 1.); + Z = sqrt(-2 * log(U)) * sin(2 * PI * V); + } else + Z = sqrt(-2 * log(U)) * cos(2 * PI * V); + + phase = 1 - phase; + + return Z; +} 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.xa = gaussrand() * 0.1; + e.entityItem.ya = gaussrand() * 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.passive.xa = 0; - e.passive.ya = 0; - 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; - 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; -} - -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; - e.hostile.xa = 0; - e.hostile.ya = 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; -} - -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; - 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; + 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.zombie.lvl = lvl; + e.zombie.health = lvl * lvl * 10; + e.zombie.dir = 0; + e.xr = 4; + e.yr = 3; + e.canPass = false; + switch(lvl){ + case 2: e.zombie.color = 0xFF8282CC; break; + case 3: e.zombie.color = 0xFFEFEFEF; break; + case 4: e.zombie.color = 0xFFAA6262; break; + default: e.zombie.color = 0xFF95DB95; 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; - 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; -} - -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.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; - return e; -} - -Entity newDragonFireEntity(Entity* parent, u8 type, int x, int y, float xa, float ya) { - Entity e; - e.type = ENTITY_DRAGONPROJECTILE; - e.level = parent->level; - 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.x = (int) x; - e.y = (int) y; - 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.level = level; - e.x = x; - e.y = y; - e.xr = 3; - e.yr = 3; - e.canPass = false; - return e; + Entity e; + e.type = ENTITY_SPARK; + 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 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.xa = gaussrand() * 0.3; + e.textParticle.ya = gaussrand() * 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; - playSoundPositioned(snd_monsterHurt, e.level, e.x, e.y); //TODO: This is a wierd location for the effect - return e; -} - -Entity newArrowEntity(Entity* parent, int itemID, s8 xa, s8 ya, int level){ - Entity e; - e.type = ENTITY_ARROW; - e.level = level; - 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.canSwim = true; - return e; -} - -Entity newGlowwormEntity(int x, int y, int 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; -} - -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; + Entity e; + e.type = ENTITY_SMASHPARTICLE; + e.level = level; + e.smashParticle.age = 0; + e.x = x; + e.y = y; + e.canPass = true; + playSound(snd_monsterHurt); + 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]; } +Entity nullEntity; 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. } diff --git a/source/Entity.h b/source/Entity.h old mode 100755 new mode 100644 index c21f5e1..c812ea0 --- a/source/Entity.h +++ b/source/Entity.h @@ -13,106 +13,80 @@ #define ENTITY_TEXTPARTICLE 7 #define ENTITY_SMASHPARTICLE 8 #define ENTITY_PLAYER 9 -#define ENTITY_PASSIVE 10 -#define ENTITY_ARROW 11 -#define ENTITY_SKELETON 12 -#define ENTITY_KNIGHT 13 -#define ENTITY_GLOWWORM 14 - -#define ENTITY_DRAGON 15 -#define ENTITY_DRAGONPROJECTILE 16 -#define ENTITY_MAGIC_PILLAR 17 - -#define ENTITY_NPC 18 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; - int regenTimer; - int strengthTimer; - int swimBreathTimer; - int speedTimer; + 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 score; - PlayerData *data; + Inventory* inv; + Item* activeItem; } 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. window select for chests. + Inventory* inv; // Points to chest inventory. + s16 oSel; // other selection inside the chest inv. } EntityFurniture; typedef struct { - u8 mtype; - s8 xa; - s8 ya; - s16 health; - s8 dir; - s8 randWalkTime; - s8 walkDist; -} PassiveMob; + s8 xa; + s8 ya; + s16 health; + s8 dir; + s8 lvl; + s8 randWalkTime; + s8 walkDist; + u32 color; +} Zombie; typedef struct { - s8 xa; - s8 ya; - s16 health; - s8 dir; - s8 lvl; - s8 randWalkTime; - s8 walkDist; - s8 randAttackTime; - 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,129 +94,77 @@ 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 { - Entity* parent; - s16 age; - s16 itemID; - s8 xa; - s8 ya; -} Arrow; - -typedef struct { - s8 xa; - s8 ya; - s16 health; - s8 randWalkTime; - s8 walkDist; - s8 dir; - int attackDelay; - int attackTime; - int attackType; - int animTimer; -} Dragon; - -typedef struct { - Entity* parent; - u8 type; - s16 age; - float xa; - float ya; - float xx; - float yy; -} DragonFire; - -typedef struct { - s8 xa; - s8 ya; - s8 randWalkTime; - s8 waitTime; -} Glowworm; - -typedef struct { - u8 type; -} 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; - PassiveMob passive; - HostileMob hostile; - Slime slime; - AirWizard wizard; - Spark spark; - Arrow arrow; - Glowworm glowworm; - Dragon dragon; - DragonFire dragonFire; - NPC npc; - TextParticleEntity textParticle; - SmashParticleEntity smashParticle; - }; + 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; + Zombie zombie; + Slime slime; + AirWizard wizard; + Spark spark; + TextParticleEntity textParticle; + SmashParticleEntity smashParticle; + }; }; typedef struct { - Entity entities[6][1000]; - s16 lastSlot[6]; - Inventory invs[300]; - s16 nextInv; + Entity entities[5][1000]; + Entity wizardSparks[120]; + s16 lastSlot[5]; + Inventory invs[301];//1 for the player, 300 for chests. + s16 nextInv; } EntityManager; EntityManager eManager; -Entity nullEntity; +s8 currentLevel; +double gaussrand(); Entity newItemEntity(Item item, int x, int y, int level); -Entity newFurnitureEntity(int itemID, Inventory * invPtr, int x, int y, int level); -Entity newPassiveEntity(int type, int x, int y, int level); +Entity newFurnitureEntity(int itemID,Inventory * invPtr, int x, int y, int level); Entity newZombieEntity(int lvl, int x, int y, int level); -Entity newSkeletonEntity(int lvl, int x, int y, int level); -Entity newKnightEntity(int lvl, int x, int y, int level); Entity newSlimeEntity(int lvl, int x, int y, int level); Entity newAirWizardEntity(int x, int y, int level); Entity newSparkEntity(Entity* parent, float xa, float ya); -Entity newDragonEntity(int x, int y, int level); -Entity newDragonFireEntity(Entity* parent, u8 type, int x, int y, float xa, float ya); -Entity newMagicPillarEntity(int x, int y, int level); Entity newTextParticleEntity(char * str, u32 color, int xa, int ya, int level); Entity newSmashParticleEntity(int xa, int ya, int level); -Entity newArrowEntity(Entity* parent, int itemID, s8 xa, s8 ya, int level); -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); + + + diff --git a/source/Globals.c b/source/Globals.c old mode 100755 new mode 100644 index 9e278fe..a1aaf28 --- a/source/Globals.c +++ b/source/Globals.c @@ -1,42 +1,40 @@ #include "Globals.h" -#include "Menu.h" -#include "Synchronizer.h" -char versionText[34] = "Version 1.6.2"; +char versionText[34] = "Version 1.1"; char fpsstr[34]; u8 currentMenu = 0; -void addItemsToWorld(Item item, s8 level, int x, int y, int count){ - int i; - for(i = 0; i < count; ++i) addEntityToList(newItemEntity(item, x, y, level), &eManager); +void addItemsToWorld(Item item,int x, int y, int count){ + int i; + for(i = 0;i x1 || e.y - e.yr > y1); } -int getEntities(Entity **result, s8 level, int x0, int y0, int x1, int y1) { - int i, last = 0; - for (i = 0; i < eManager.lastSlot[level]; ++i) { - Entity* e = &eManager.entities[level][i]; - if (intersects(*e, x0, y0, x1, y1)){ - result[last] = e; - ++last; - } +int getEntities(Entity** result,int x0, int y0, int x1, int y1) { + int i, last = 0; + for (i = 0; i < eManager.lastSlot[currentLevel]; ++i) { + Entity* e = &eManager.entities[currentLevel][i]; + if (intersects(*e,x0, y0, x1, y1)){ + result[last] = e; + ++last; + } } return last; } -void removeSimilarElements(Entity **arr1, int arr1Size, Entity **arr2, int arr2Size){ - int i,j; - for(i=0;ix) - e->xr) >> 4; int yto0 = ((e->y) - e->yr) >> 4; @@ -52,41 +50,39 @@ bool move2(Entity* e, int xa, int ya) { for (yt = yt0; yt <= yt1; ++yt) for (xt = xt0; xt <= xt1; ++xt) { if (xt >= xto0 && xt <= xto1 && yt >= yto0 && yt <= yto1) continue; - entityTileInteract(e, getTile(e->level, xt, yt), e->level, xt, yt); - if (!e->canPass && tileIsSolid(getTile(e->level, xt, yt), e)) { + entityTileInteract(e, getTile(xt,yt), xt, yt); + if (!e->canPass && tileIsSolid(getTile(xt,yt),e)) { blocked = true; return false; } } if (blocked) return false; - Entity * wasInside[eManager.lastSlot[e->level]]; - Entity * isInside[eManager.lastSlot[e->level]]; - int wasSize = getEntities(wasInside, e->level, e->x - e->xr, e->y - e->yr, e->x + e->xr, e->y + e->yr); - int isSize = getEntities(isInside, e->level, e->x + xa - e->xr, e->y + ya - e->yr, e->x + xa + e->xr, e->y + ya + e->yr); + Entity * wasInside[eManager.lastSlot[currentLevel]]; + Entity * isInside[eManager.lastSlot[currentLevel]]; + getEntities(wasInside, e->x - e->xr, e->y - e->yr, e->x + e->xr, e->y + e->yr); + int isSize = getEntities(isInside, e->x + xa - e->xr, e->y + ya - e->yr, e->x + xa + e->xr, e->y + ya + e->yr); int i; - + for (i = 0; i < isSize; ++i) { Entity * ent = isInside[i]; if (ent == e || ent == NULL) continue; EntityVsEntity(e, ent); } if(e->type != ENTITY_PLAYER){ - for(int i=0; ilevel && intersects(players[i].entity, e->x + xa - e->xr, e->y + ya - e->yr, e->x + xa + e->xr, e->y + ya + e->yr)){ - EntityVsEntity(e, &(players[i].entity)); - } - } - } - removeSimilarElements(wasInside, wasSize, isInside, isSize); - + if(intersects(player, e->x + xa - e->xr, e->y + ya - e->yr, e->x + xa + e->xr, e->y + ya + e->yr)){ + EntityVsEntity(e, &player); + } + } + removeSimilarElements(wasInside, isInside); + for (i = 0; i < isSize; ++i) { Entity * ent = isInside[i]; if (ent == e || ent == NULL) continue; - if (EntityBlocksEntity(e, ent)) return false; + if (EntityBlocksEntity(e,ent)) return false; } - if(e->x + xa > 0 && e->x + xa < 2048) e->x += xa; + if(e->x + xa > 0 && e->x + xa < 2048) e->x += xa; if(e->y + ya > 0 && e->y + ya < 2048) e->y += ya; return true; } @@ -102,1694 +98,1418 @@ bool move(Entity* e, int xa, int ya) { } bool moveMob(Entity* e, int xa, int ya){ - if (e->xKnockback < 0) { - move2(e, -1, 0); - e->xKnockback++; - } - if (e->xKnockback > 0) { - move2(e, 1, 0); - e->xKnockback--; - } - if (e->yKnockback < 0) { - move2(e, 0, -1); - e->yKnockback++; - } - if (e->yKnockback > 0) { - move2(e, 0, 1); - e->yKnockback--; - } - if (e->hurtTime > 0) return true; - return move(e, xa, ya); + if (e->xKnockback < 0) { + move2(e,-1, 0); + e->xKnockback++; + } + if (e->xKnockback > 0) { + move2(e,1, 0); + e->xKnockback--; + } + if (e->yKnockback < 0) { + move2(e,0, -1); + e->yKnockback++; + } + if (e->yKnockback > 0) { + move2(e,0, 1); + e->yKnockback--; + } + if (e->hurtTime > 0) return true; + return move(e, xa, ya); } -void hurtEntity(Entity *e, int damage, int dir, u32 hurtColor, Entity *damager){ - if (shouldRenderDebug && e->type==ENTITY_PLAYER) return; - if (e->hurtTime > 0) return; - playSoundPositioned(snd_monsterHurt, e->level, e->x, e->y); +s16 lastTouchX = -1; +s16 lastTouchY = -1; +bool isDraggingMap = false; +bool isChangingSize = false; +void tickTouchMap(){ + if(shouldRenderMap){ + if(k_touch.px > 0 || k_touch.py > 0){ + // Plus/Minus zoom button + if(k_touch.py > 204 && k_touch.py < 232){ + if(k_touch.px > 284 && k_touch.px < 312){ + if(zoomLevel > 4) return; + if(!isChangingSize && !isDraggingMap){ + zoomLevel += 2; + mScrollX -= (50 * (zoomLevel/2)); + mScrollY -= (40 * (zoomLevel/2)); + isChangingSize = true; + sprintf(mapText,"x%d",zoomLevel); + } + if(mScrollX < 320-(128*zoomLevel)) mScrollX = 320-(128*zoomLevel); + else if(mScrollX > 0) mScrollX = 0; + if(mScrollY < 240-(128*zoomLevel)) mScrollY = 240-(128*zoomLevel); + else if(mScrollY > 0) mScrollY = 0; + return; + } else if(k_touch.px > 256 && k_touch.px < 284){ + if(zoomLevel < 4) return; + if(!isChangingSize && !isDraggingMap){ + mScrollX += (50 * (zoomLevel/2)); + mScrollY += (40 * (zoomLevel/2)); + zoomLevel -= 2; + isChangingSize = true; + sprintf(mapText,"x%d",zoomLevel); + } + if(mScrollX < 320-(128*zoomLevel)) mScrollX = 320-(128*zoomLevel); + else if(mScrollX > 0) mScrollX = 0; + if(mScrollY < 240-(128*zoomLevel)) mScrollY = 240-(128*zoomLevel); + else if(mScrollY > 0) mScrollY = 0; + return; + } + } else if(k_touch.py > 8 && k_touch.py < 40 && k_touch.px > 284 && k_touch.px < 312){ + // Exit Button + if(!isChangingSize && !isDraggingMap){ + shouldRenderMap = false; + return; + } + } + + if(!isDraggingMap){ + lastTouchX = k_touch.px; + lastTouchY = k_touch.py; + } + if(zoomLevel > 2){ + int dx = lastTouchX - k_touch.px; + if(dx > 1 || dx < -1){ + mScrollX -= dx; + if(mScrollX < 320-(128*zoomLevel)) mScrollX = 320-(128*zoomLevel); + else if(mScrollX > 0) mScrollX = 0; + } + lastTouchX = k_touch.px; + } + + int dy = lastTouchY - k_touch.py; + if(dy > 1 || dy < -1){ + mScrollY -= dy; + if(mScrollY < 240-(128*zoomLevel)) mScrollY = 240-(128*zoomLevel); + else if(mScrollY > 0) mScrollY = 0; + } + lastTouchY = k_touch.py; + isDraggingMap = true; + } else { + isDraggingMap = false; + isChangingSize = false; + } + } else { + // touch minimap to bring up zoomed map. + if(k_touch.py > 100 && k_touch.py < 228 && k_touch.px > 10 && k_touch.px < 142){ + shouldRenderMap = true; + } + } +} - char hurtText[11]; - sprintf(hurtText, "%d", damage); - addEntityToList(newTextParticleEntity(hurtText, hurtColor, e->x, e->y, e->level), &eManager); - - int i; - - // In hindsight I should've made a generic Mob struct, but whatever. �\_(-.-)_/� - switch(e->type){ - case ENTITY_PLAYER: - e->p.health -= damage; - if(e->p.health < 1){ - playSoundPositioned(snd_bossdeath, e->level, e->x, e->y); - e->p.endTimer = 60; - e->p.isDead = true; - e->hurtTime = 10; - return; - } - break; - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - e->hostile.health -= damage; - if(e->hostile.health < 1){ - if(e->type == ENTITY_ZOMBIE) { - addItemsToWorld(newItem(ITEM_FLESH,1), e->level, e->x+8, e->y+8, (rand()%2) + 1); - } else if(e->type == ENTITY_SKELETON) { - addItemsToWorld(newItem(ITEM_BONE,1), e->level, e->x+8, e->y+8, (rand()%2) + 1); - if(rand()%2==0) addItemsToWorld(newItem(ITEM_ARROW_STONE,1), e->level, e->x+8, e->y+8, 1); - } else if(e->type == ENTITY_KNIGHT) { - addItemsToWorld(newItem(ITEM_IRONINGOT,1), e->level, e->x+8, e->y+8, (rand()%2) + 1); +void tickTouchQuickSelect() { + if (currentMenu == 0) { + int i = 0; + Inventory * inv = player.p.inv; + + for (i = 0; i < 8; ++i) { + if((inv->lastSlot) > i) { + int xip = i % 4; + int yip = i / 4; + + if(k_touch.py > 72*2+yip*21*2 && k_touch.py < 72*2+yip*21*2+21*2 && k_touch.px > 76*2+xip*21*2 && k_touch.px < 76*2+xip*21*2+21*2) { + playerSetActiveItem(&inv->items[i]); } - if(damager!=NULL && damager->type==ENTITY_PLAYER) damager->p.data->score += 50 * (e->hostile.lvl + 1); - removeEntityFromList(e, e->level, &eManager); - if(e->level != 5) trySpawn(3, e->level); - return; } - break; - case ENTITY_SLIME: - e->slime.health -= damage; - if(e->slime.health < 1){ - addItemsToWorld(newItem(ITEM_SLIME,1), e->level, e->x+8, e->y+8, (rand()%2) + 1); - if(damager!=NULL && damager->type==ENTITY_PLAYER) damager->p.data->score += 25 * (e->slime.lvl + 1); - removeEntityFromList(e, e->level, &eManager); - if(e->level != 5) trySpawn(3, e->level); - return; - } - break; - case ENTITY_AIRWIZARD: - e->wizard.health -= damage; - airWizardHealthDisplay = e->wizard.health; - if(e->wizard.health < 1){ - addItemsToWorld(newItem(ITEM_MAGIC_DUST,1), e->level, e->x+8, e->y+8, (rand()%2) + 2); - removeEntityFromList(e,e->level,&eManager); - playSound(snd_bossdeath); - - for(i=0; ipassive.health -= damage; - if(e->passive.health < 1){ - if(e->passive.mtype==0) { - addItemsToWorld(newItem(ITEM_WOOL,1), e->level, e->x+8, e->y+8, (rand()%3) + 1); - } else if(e->passive.mtype==1) { - addItemsToWorld(newItem(ITEM_PORK_RAW,1), e->level, e->x+8, e->y+8, (rand()%2) + 1); - } else if(e->passive.mtype==2) { - addItemsToWorld(newItem(ITEM_BEEF_RAW,1), e->level, e->x+8, e->y+8, (rand()%2) + 1); - if((rand()%2)==0) { - addItemsToWorld(newItem(ITEM_LEATHER,1), e->level, e->x+8, e->y+8, 1); - } - } - if(damager!=NULL && damager->type==ENTITY_PLAYER) damager->p.data->score += 10; - removeEntityFromList(e, e->level, &eManager); - if(e->level != 5) trySpawn(3, e->level); - return; - } - break; - case ENTITY_DRAGON: - e->dragon.health -= damage; - if(e->dragon.health < 1){ - addItemsToWorld(newItem(ITEM_DRAGON_EGG,1), e->level, e->x+8, e->y+8, 1); - addItemsToWorld(newItem(ITEM_DRAGON_SCALE,1), e->level, e->x+8, e->y+8, (rand()%11) + 10); - removeEntityFromList(e, e->level, &eManager); - playSound(snd_bossdeath); - for(i=0; ihurtTime > 0) return; + int xd = player.x - e->x; + int yd = player.y - e->y; + if (xd * xd + yd * yd < 80 * 80) playSound(snd_monsterHurt); + + char hurtText[11]; + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,hurtColor,e->x,e->y,currentLevel), &eManager); + + // In hindsight I should've made a generic Mob struct, but whatever. ¯\_(-.-)_/¯ + switch(e->type){ + case ENTITY_PLAYER: + e->p.health -= damage; + if(e->p.health < 1){ + playSound(snd_bossdeath); + e->p.endTimer = 60; + e->p.isDead = true; + return; + } + break; + case ENTITY_ZOMBIE: + e->zombie.health -= damage; + if(e->zombie.health < 1){ + addItemsToWorld(newItem(ITEM_FLESH,1),e->x+8, e->y+8, (rand()%2) + 1); + player.p.score += 50 * (e->zombie.lvl + 1); + removeEntityFromList(e,e->level,&eManager); + trySpawn(3, currentLevel); + return; + } + break; + case ENTITY_SLIME: + e->slime.health -= damage; + if(e->slime.health < 1){ + addItemsToWorld(newItem(ITEM_SLIME,1),e->x+8, e->y+8, (rand()%2) + 1); + player.p.score += 25 * (e->slime.lvl + 1); + removeEntityFromList(e,e->level,&eManager); + trySpawn(3, currentLevel); + return; + } + break; + case ENTITY_AIRWIZARD: + e->wizard.health -= damage; + airWizardHealthDisplay = e->wizard.health; + if(e->wizard.health < 1){ + removeEntityFromList(e,e->level,&eManager); + playSound(snd_bossdeath); + player.p.score += 1000; + player.p.endTimer = 60; + player.p.hasWon = true; + player.p.hasWonSaved = true; + return; + } + break; + } + switch(dir){ - case -1: - switch(e->type){ - case ENTITY_PLAYER: - switch(e->p.dir){ - case 0: e->yKnockback = -10; break; - case 1: e->yKnockback = +10; break; - case 2: e->xKnockback = +10; break; - case 3: e->xKnockback = -10; break; - } - break; - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - switch(e->hostile.dir){ - case 0: e->yKnockback = -10; break; - case 1: e->yKnockback = +10; break; - case 2: e->xKnockback = +10; break; - case 3: e->xKnockback = -10; break; - } - break; - case ENTITY_SLIME: - switch(e->slime.dir){ - case 0: e->yKnockback = -10; break; - case 1: e->yKnockback = +10; break; - case 2: e->xKnockback = +10; break; - case 3: e->xKnockback = -10; break; - } - break; - case ENTITY_PASSIVE: - switch(e->passive.dir){ - case 0: e->yKnockback = -10; break; - case 1: e->yKnockback = +10; break; - case 2: e->xKnockback = +10; break; - case 3: e->xKnockback = -10; break; - } - break; - } - break; - case 0: e->yKnockback = +10; break; - case 1: e->yKnockback = -10; break; - case 2: e->xKnockback = -10; break; - case 3: e->xKnockback = +10; break; - } + case -1: + switch(e->type){ + case ENTITY_PLAYER: + switch(e->p.dir){ + case 0: e->yKnockback = -10; break; + case 1: e->yKnockback = +10; break; + case 2: e->xKnockback = +10; break; + case 3: e->xKnockback = -10; break; + } + break; + case ENTITY_ZOMBIE: + switch(e->zombie.dir){ + case 0: e->yKnockback = -10; break; + case 1: e->yKnockback = +10; break; + case 2: e->xKnockback = +10; break; + case 3: e->xKnockback = -10; break; + } + break; + case ENTITY_SLIME: + switch(e->slime.dir){ + case 0: e->yKnockback = -10; break; + case 1: e->yKnockback = +10; break; + case 2: e->xKnockback = +10; break; + case 3: e->xKnockback = -10; break; + } + break; + } + break; + case 0: e->yKnockback = +10; break; + case 1: e->yKnockback = -10; break; + case 2: e->xKnockback = -10; break; + case 3: e->xKnockback = +10; break; + } e->hurtTime = 10; } -bool ItemVsEntity(PlayerData *pd, Item *item, Entity *e, int dir) { - //TODO: Too much duplicated code - switch(item->id){ - case ITEM_POWGLOVE: - if(e->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; iid){ + case ITEM_POWGLOVE: + if(e->type == ENTITY_FURNITURE){ + Item nItem = newItem(e->entityFurniture.itemID,0); + if(e->entityFurniture.itemID == ITEM_CHEST) nItem.chestPtr = e->entityFurniture.inv; + pushItemToInventoryFront(nItem, player.p.inv); + removeEntityFromList(e,currentLevel,&eManager); + player.p.activeItem = &player.p.inv->items[0]; + player.p.isCarrying = true; + return true; + } break; + case TOOL_AXE: + switch(e->type){ + case ENTITY_ZOMBIE: + case ENTITY_SLIME: + case ENTITY_AIRWIZARD: + if(playerUseEnergy(4-item->countLevel)) hurtEntity(e,(item->countLevel + 1) * 2 + (rand()%4),dir,0xFF0000FF); + else hurtEntity(e,1+rand()%3,dir,0xFF0000FF); + return true; + } break; + case TOOL_SWORD: + switch(e->type){ + case ENTITY_ZOMBIE: + case ENTITY_SLIME: + case ENTITY_AIRWIZARD: + if(playerUseEnergy(4-item->countLevel)) hurtEntity(e,(item->countLevel+1)*3+(rand()%(2+item->countLevel*item->countLevel*2)),dir,0xFF0000FF); + else hurtEntity(e,1+rand()%3,dir,0xFF0000FF); + return true; + } break; + case ITEM_NULL: + switch(e->type){ + case ENTITY_ZOMBIE: + case ENTITY_SLIME: + case ENTITY_AIRWIZARD: + hurtEntity(e,1+rand()%3,dir,0xFF0000FF); + return true; + } break; + } + return false; +} - Item nItem = newItem(e->entityFurniture.itemID,0); - if(e->entityFurniture.itemID == ITEM_CHEST) nItem.chestPtr = e->entityFurniture.inv; - pushItemToInventoryFront(nItem, &(pd->inventory)); - - removeEntityFromList(e, e->level, &eManager); - pd->activeItem = &(pd->inventory.items[0]); - pd->entity.p.isCarrying = true; - return true; - } break; - case TOOL_AXE: - switch(e->type){ - case ENTITY_PASSIVE: - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - case ENTITY_SLIME: - case ENTITY_AIRWIZARD: - case ENTITY_DRAGON: - if(playerUseEnergy(pd, 4-item->countLevel)) hurtEntity(e, (item->countLevel + 1) * 2 + (rand()%4), dir, 0xFF0000FF, &(pd->entity)); - else hurtEntity(e, 1+rand()%3, dir, 0xFF0000FF, &(pd->entity)); - return true; - - case ENTITY_MAGIC_PILLAR: - playSoundPositioned(snd_monsterHurt, e->level, e->x, e->y); - - removeEntityFromList(e, e->level, &eManager); - return true; - } break; - case TOOL_SWORD: - switch(e->type){ - case ENTITY_PASSIVE: - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - case ENTITY_SLIME: - case ENTITY_AIRWIZARD: - case ENTITY_DRAGON: - if(playerUseEnergy(pd, 4-item->countLevel)) hurtEntity(e, (item->countLevel+1)*3+(rand()%(2+item->countLevel*item->countLevel*2)), dir, 0xFF0000FF, &(pd->entity)); - else hurtEntity(e, 1+rand()%3, dir, 0xFF0000FF, &(pd->entity)); - return true; - - case ENTITY_MAGIC_PILLAR: - playSoundPositioned(snd_monsterHurt, e->level, e->x, e->y); - - removeEntityFromList(e, e->level, &eManager); - return true; - } break; - case ITEM_NULL: - switch(e->type){ - case ENTITY_PASSIVE: - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - case ENTITY_SLIME: - case ENTITY_AIRWIZARD: - case ENTITY_DRAGON: - hurtEntity(e, 1+rand()%3, dir, 0xFF0000FF, &(pd->entity)); - return true; - - case ENTITY_MAGIC_PILLAR: - playSoundPositioned(snd_monsterHurt, e->level, e->x, e->y); - - removeEntityFromList(e, e->level, &eManager); - return true; - } break; +bool interact(int x0, int y0, int x1, int y1) { + Entity * es[eManager.lastSlot[currentLevel]]; + int eSize = getEntities(es, x0, y0, x1, y1); + int i; + for (i = 0; i < eSize; ++i) { + Entity * ent = es[i]; + if (ent != &player){ + if (ItemVsEntity(player.p.activeItem, ent, player.p.dir)) return true; + } } return false; } void EntityVsEntity(Entity* e1, Entity* e2){ - int damage = 1; - switch(e1->type){ - case ENTITY_PLAYER: playerEntityInteract(e1->p.data, e2); break; - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - if(e2->type == ENTITY_PLAYER){ - if(e1->type == ENTITY_ZOMBIE) hurtEntity(e2, 2, e1->hostile.dir, 0xFFAF00FF, e1); - else if(e1->type == ENTITY_SKELETON) hurtEntity(e2, 1, e1->hostile.dir, 0xFFAF00FF, e1); - else if(e1->type == ENTITY_KNIGHT) hurtEntity(e2, 3, e1->hostile.dir, 0xFFAF00FF, e1); - switch(e1->hostile.dir){ - case 0: e1->yKnockback = -4; break; - case 1: e1->yKnockback = +4; break; - case 2: e1->xKnockback = +4; break; - case 3: e1->xKnockback = -4; break; - } - } - break; - case ENTITY_SLIME: - if(e2->type == ENTITY_PLAYER){ - hurtEntity(e2, 1, e1->slime.dir, 0xFFAF00FF, e1); - switch(e1->slime.dir){ - case 0: e1->yKnockback = -4; break; - case 1: e1->yKnockback = +4; break; - case 2: e1->xKnockback = +4; break; - case 3: e1->xKnockback = -4; break; - } - } - break; - case ENTITY_AIRWIZARD: - if(e2->type == ENTITY_PLAYER) hurtEntity(e2, 3, e1->wizard.dir, 0xFFAF00FF, e1); - break; - case ENTITY_SPARK: - if(e2 != e1->spark.parent) hurtEntity(e2, 1, -1, 0xFFAF00FF, e1); - break; - case ENTITY_DRAGON: - if(e2->type == ENTITY_PLAYER) hurtEntity(e2, 3, e1->dragon.dir, 0xFFAF00FF, e1); - break; - case ENTITY_DRAGONPROJECTILE: - if(e2 != e1->dragonFire.parent) hurtEntity(e2, 1, -1, 0xFFAF00FF, e1); - break; - case ENTITY_ARROW: - switch(e1->arrow.itemID) { - case ITEM_ARROW_WOOD: - damage = 1 + (rand()%3); - break; - case ITEM_ARROW_STONE: - damage = 2 + (rand()%4); - break; - case ITEM_ARROW_IRON: - damage = 8 + (rand()%9); - break; - case ITEM_ARROW_GOLD: - damage = 16 + (rand()%9); - break; - case ITEM_ARROW_GEM: - damage = 24 + (rand()%9); - break; - } - - if(e1->arrow.parent->type == ENTITY_PLAYER) { - if(e2->type != ENTITY_PLAYER) { - hurtEntity(e2, damage, -1, 0xFF0000FF, e1); - removeEntityFromList(e1, e1->level, &eManager); - } - } else { - if(e2->type == ENTITY_PLAYER) { - hurtEntity(e2, damage, -1, 0xFFAF00FF, e1); - removeEntityFromList(e1, e1->level, &eManager); - } - } - break; - } + switch(e1->type){ + case ENTITY_PLAYER: playerEntityInteract(e2); break; + case ENTITY_ZOMBIE: + if(e2->type == ENTITY_PLAYER){ + hurtEntity(e2, 2, e1->zombie.dir, 0xFFAF00FF); + switch(e1->zombie.dir){ + case 0: e1->yKnockback = -4; break; + case 1: e1->yKnockback = +4; break; + case 2: e1->xKnockback = +4; break; + case 3: e1->xKnockback = -4; break; + } + } + break; + case ENTITY_SLIME: + if(e2->type == ENTITY_PLAYER){ + hurtEntity(e2, 1, e1->slime.dir, 0xFFAF00FF); + switch(e1->slime.dir){ + case 0: e1->yKnockback = -4; break; + case 1: e1->yKnockback = +4; break; + case 2: e1->xKnockback = +4; break; + case 3: e1->xKnockback = -4; break; + } + } + break; + case ENTITY_AIRWIZARD: + if(e2->type == ENTITY_PLAYER) hurtEntity(e2, 3, e1->wizard.dir, 0xFFAF00FF); + break; + case ENTITY_SPARK: + if(e2 != e1->spark.parent) hurtEntity(e2, 1, -1, 0xFFAF00FF); + break; + } } bool EntityBlocksEntity(Entity* e1, Entity* e2){ - switch(e1->type){ - case ENTITY_PLAYER: - case ENTITY_FURNITURE: - switch(e2->type){ - case ENTITY_FURNITURE: - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - case ENTITY_SLIME: - case ENTITY_AIRWIZARD: - case ENTITY_DRAGON: - case ENTITY_PLAYER: - case ENTITY_PASSIVE: - case ENTITY_MAGIC_PILLAR: - case ENTITY_NPC: - return true; - break; - } - break; - } - return false; + switch(e1->type){ + case ENTITY_PLAYER: + case ENTITY_FURNITURE: + switch(e2->type){ + case ENTITY_FURNITURE: + case ENTITY_ZOMBIE: + case ENTITY_SLIME: + case ENTITY_AIRWIZARD: + case ENTITY_PLAYER: + return true; + break; + } + break; + } + return false; } bool tileIsSolid(int tile, Entity * e){ - switch(tile){ - case TILE_ROCK: - case TILE_HARDROCK: - case TILE_MAGIC_BARRIER: - case TILE_DUNGEON_WALL: - return true; - case TILE_TREE: - case TILE_CACTUS: - case TILE_IRONORE: - case TILE_GOLDORE: - case TILE_GEMORE: - case TILE_CLOUDCACTUS: - case TILE_WOOD_WALL: - case TILE_STONE_WALL: - case TILE_IRON_WALL: - case TILE_GOLD_WALL: - case TILE_GEM_WALL: - case TILE_BOOKSHELVES: - case TILE_MUSHROOM_BROWN: - case TILE_MUSHROOM_RED: - if(e->type != ENTITY_DRAGON) return true; - case TILE_LAVA: - case 255: - if(e->type != ENTITY_ARROW) return true; - case TILE_WATER: - if(e != NULL && !e->canSwim && e->type != ENTITY_ARROW) return true; - case TILE_HOLE: - if(e != NULL && e->type != ENTITY_PLAYER && e->type != ENTITY_ARROW) return true; - } - return false; + switch(tile){ + case TILE_TREE: + case TILE_ROCK: + case TILE_HARDROCK: + case TILE_CACTUS: + case TILE_IRONORE: + case TILE_GOLDORE: + case TILE_GEMORE: + case TILE_CLOUDCACTUS: + case TILE_LAVA: + case TILE_WOOD_WALL: + case 255: + return true; + case TILE_WATER: + if(e != NULL && !e->canSwim) return true; + case TILE_HOLE: + if(e != NULL && e->type != ENTITY_PLAYER) return true; + } + return false; } /* For minimap */ u32 getTileColor(int tile){ - switch(tile){ - case TILE_WATER: return SWAP_UINT32(waterColor[0]); - case TILE_LAVA: return SWAP_UINT32(lavaColor[0]); - case TILE_DIRT: return 0x826D6CFF; - case TILE_ROCK: return SWAP_UINT32(rockColor[1]); - case TILE_HARDROCK: return SWAP_UINT32(rockColor[3]); - case TILE_GRASS: return SWAP_UINT32(grassColor); - case TILE_TREE: return 0x007F00FF; - case TILE_SAND: return SWAP_UINT32(sandColor); - case TILE_CACTUS: return 0x009F00FF; - case TILE_FLOWER: return SWAP_UINT32(grassColor); - case TILE_IRONORE: return SWAP_UINT32(ironColor); - case TILE_GOLDORE: return SWAP_UINT32(goldColor); - case TILE_GEMORE: return SWAP_UINT32(gemColor); - case TILE_CLOUD: return 0xFFFFFFFF; - case TILE_CLOUDCACTUS: return 0xAFAFAFFF; - case TILE_STAIRS_DOWN: return 0x9F9F9FFF; - case TILE_STAIRS_UP: return 0x9F9F9FFF; - case TILE_HOLE: return 0x383838FF; - case TILE_WOOD_WALL: return SWAP_UINT32(woodColor); - case TILE_STONE_WALL: return SWAP_UINT32(rockColor[1]); - case TILE_IRON_WALL: return SWAP_UINT32(ironColor); - case TILE_GOLD_WALL: return SWAP_UINT32(goldColor); - case TILE_GEM_WALL: return SWAP_UINT32(gemColor); - case TILE_DUNGEON_WALL: return SWAP_UINT32(dungeonColor[0]); - case TILE_DUNGEON_FLOOR: return SWAP_UINT32(dungeonColor[1]); - case TILE_MAGIC_BARRIER: return SWAP_UINT32(dungeonColor[0]); - case TILE_BOOKSHELVES: return SWAP_UINT32(woodColor); - case TILE_WOOD_FLOOR: return SWAP_UINT32(woodColor); - case TILE_MYCELIUM: return SWAP_UINT32(myceliumColor); - case TILE_MUSHROOM_BROWN: return SWAP_UINT32(mushroomColor); - case TILE_MUSHROOM_RED: return SWAP_UINT32(mushroomColor); - case TILE_ICE: return SWAP_UINT32(iceColor); - - default: return 0x111111FF; - } + switch(tile){ + case TILE_WATER: return 0x0000FFFF; + case TILE_LAVA: return 0xFF0000FF; + case TILE_DIRT: return 0x826D6CFF; + case TILE_ROCK: return 0x7F7F7FFF; + case TILE_HARDROCK: return 0x5F5F7FFF; + case TILE_GRASS: return 0x00FF00FF; + case TILE_TREE: return 0x007F00FF; + case TILE_SAND: return 0xFFFF00FF; + case TILE_CACTUS: return 0x009F00FF; + case TILE_FLOWER: return 0x3FFF00FF; + case TILE_IRONORE: return 0xDC9696FF; + case TILE_GOLDORE: return 0xE5E89AFF; + case TILE_GEMORE: return 0xDF98DEFF; + case TILE_CLOUD: return 0xFFFFFFFF; + case TILE_CLOUDCACTUS: return 0xAFAFAFFF; + case TILE_STAIRS_DOWN: return 0x9F9F9FFF; + case TILE_STAIRS_UP: return 0x9F9F9FFF; + case TILE_HOLE: return 0x383838FF; + case TILE_WOOD_WALL: return 0xC1A55EFF; + default: return 0x111111FF; + } } +void healPlayer(int amount){ + player.p.health += amount; + if(player.p.health > 10) player.p.health = 10; + char healText[11]; + sprintf(healText, "%d", amount); + addEntityToList(newTextParticleEntity(healText,0xFF00FF00,player.x,player.y,currentLevel), &eManager); +} - -s8 itemTileInteract(int tile, PlayerData *pd, Item *item, s8 level, int x, int y, int px, int py, int dir){ - - // Furniture items - if(item->id > 27 && item->id < 51){ - if(!tileIsSolid(getTile(level, x, y), NULL)){ - addEntityToList(newFurnitureEntity(item->id, item->chestPtr, (x<<4)+8, (y<<4)+8, level), &eManager); - removeItemFromCurrentInv(item); - pd->activeItem = &noItem; - return 2; - } - return 0; - } - - switch(tile){ - case TILE_TREE: - if(item->id == TOOL_AXE && playerUseEnergy(pd, 4-item->countLevel)){ - playerHurtTile(pd, tile, level, x, y, (rand()%10) + (item->countLevel) * 5 + 10, pd->entity.p.dir); - return 1; - } break; - case TILE_ROCK: - case TILE_HARDROCK: - if(item->id == TOOL_PICKAXE && playerUseEnergy(pd, 4-item->countLevel)){ - playerHurtTile(pd, tile, level, x, y, (rand()%10) + (item->countLevel) * 5 + 10, pd->entity.p.dir); - return 1; - } break; - case TILE_IRONORE: - case TILE_GOLDORE: - case TILE_GEMORE: - case TILE_CLOUDCACTUS: - if(item->id == TOOL_PICKAXE && playerUseEnergy(pd, 4-item->countLevel)){ - playerHurtTile(pd, tile, level, x, y, 1, pd->entity.p.dir); - return 1; - } break; - case TILE_GRASS: - if(item->id == TOOL_HOE && playerUseEnergy(pd, 4-item->countLevel)){ - setTile(TILE_FARM, level, x, y); - return 1; - } - else if(item->id == ITEM_ACORN){ - setTile(TILE_SAPLING_TREE, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_FLOWER){ - setTile(TILE_FLOWER, level, x, y); --item->countLevel; - setData(rand()%4, level, x, y); // determines mirroring. - return 1; - } - else if(item->id == ITEM_WALL_WOOD){ - setTile(TILE_WOOD_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_STONE){ - setTile(TILE_STONE_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_IRON){ - setTile(TILE_IRON_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_GOLD){ - setTile(TILE_GOLD_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_GEM){ - setTile(TILE_GEM_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_BOOKSHELVES){ - setTile(TILE_BOOKSHELVES, level, x, y); --item->countLevel; - setData(rand()%3, level, x, y); //determines sprite - return 1; - } - else if(item->id == TOOL_SHOVEL && playerUseEnergy(pd, 4-item->countLevel)){ - if(rand()%5==0) addItemsToWorld(newItem(ITEM_SEEDS,1), level, (x<<4)+8, (y<<4)+8, 1); - setTile(TILE_DIRT, level, x, y); - return 1; - } break; - case TILE_SAND: - if(item->id == ITEM_CACTUS){ - setTile(TILE_SAPLING_CACTUS, level, x, y); - --item->countLevel; - return 1; - } - else if(item->id == TOOL_SHOVEL && playerUseEnergy(pd, 4-item->countLevel)){ - addItemsToWorld(newItem(ITEM_SAND,1), level, (x<<4)+8, (y<<4)+8, 1); - setTile(TILE_DIRT, level, x, y); - return 1; - } break; - case TILE_DIRT: - if(item->id == TOOL_HOE && pd->entity.level==1 && playerUseEnergy(pd, 4-item->countLevel)){ - setTile(TILE_FARM, level, x, y); - return 1; - } - else if(item->id == ITEM_WALL_WOOD){ - setTile(TILE_WOOD_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_STONE){ - setTile(TILE_STONE_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_IRON){ - setTile(TILE_IRON_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_GOLD){ - setTile(TILE_GOLD_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_WALL_GEM){ - setTile(TILE_GEM_WALL, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_BOOKSHELVES){ - setTile(TILE_BOOKSHELVES, level, x, y); --item->countLevel; - setData(rand()%3, level, x, y); //determines sprite - return 1; - } - else if(item->id == ITEM_WOOD) { - setTile(TILE_WOOD_FLOOR, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == ITEM_SAND){ - setTile(TILE_SAND, level, x, y); --item->countLevel; - return 1; - } - else if(item->id == TOOL_SHOVEL && playerUseEnergy(pd, 4-item->countLevel)){ - addItemsToWorld(newItem(ITEM_DIRT,1), level, (x<<4)+8, (y<<4)+8, 1); - setTile(TILE_HOLE, level, x, y); - return 1; - } break; - case TILE_HOLE: +s8 itemTileInteract(int tile, Item* item, int x, int y, int px, int py, int dir){ + + // Furniture items + if(item->id > 27 && item->id < 34){ + if(!tileIsSolid(getTile(x,y), NULL)){ + addEntityToList(newFurnitureEntity(item->id,item->chestPtr, (x<<4)+8, (y<<4)+8, currentLevel), &eManager); + removeItemFromCurrentInv(item); + player.p.activeItem = &noItem; + return 2; + } + return 0; + } + + // Health items + switch(item->id){ + case ITEM_APPLE: + if(player.p.health < 10 && playerUseEnergy(2)){ + healPlayer(1); + --item->countLevel; + if(item->countLevel < 1){ + removeItemFromCurrentInv(item); + player.p.activeItem = &noItem; + } + } + return 0; + case ITEM_FLESH: + if(player.p.health < 10 && playerUseEnergy(4+(rand()%4))){ + healPlayer(1); + --item->countLevel; + if(item->countLevel < 1){ + removeItemFromCurrentInv(item); + player.p.activeItem = &noItem; + } + } + return 0; + case ITEM_BREAD: + if(player.p.health < 10 && playerUseEnergy(3)){ + healPlayer(2); + --item->countLevel; + if(item->countLevel < 1){ + removeItemFromCurrentInv(item); + player.p.activeItem = &noItem; + } + } + return 0; + } + + switch(tile){ + case TILE_TREE: + if(item->id == TOOL_AXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, (rand()%10) + (item->countLevel) * 5 + 10, player.p.dir); + return 1; + } break; + case TILE_ROCK: + if(item->id == TOOL_PICKAXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, (rand()%10) + (item->countLevel) * 5 + 10, player.p.dir); + return 1; + } break; + case TILE_HARDROCK: + if(item->id == TOOL_PICKAXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, (rand()%10) + (item->countLevel) * 5 + 10, player.p.dir); + return 1; + } break; + case TILE_IRONORE: + if(item->id == TOOL_PICKAXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, 1, player.p.dir); + return 1; + } break; + case TILE_GOLDORE: + if(item->id == TOOL_PICKAXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, 1, player.p.dir); + return 1; + } break; + case TILE_GEMORE: + if(item->id == TOOL_PICKAXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, 1, player.p.dir); + return 1; + } break; + case TILE_CLOUDCACTUS: + if(item->id == TOOL_PICKAXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, 1, player.p.dir); + return 1; + } break; + case TILE_GRASS: + if(item->id == TOOL_HOE && playerUseEnergy(4-item->countLevel)){ + setTile(TILE_FARM,x,y); + return 1; + } + else if(item->id == ITEM_ACORN){ + setTile(TILE_SAPLING_TREE,x,y); --item->countLevel; + return 1; + } + else if(item->id == ITEM_FLOWER){ + setTile(TILE_FLOWER,x,y); --item->countLevel; + setData(rand()%4,x,y); // determines mirroring. + return 1; + } + else if(item->id == ITEM_WOOD){ + setTile(TILE_WOOD_WALL,x,y); --item->countLevel; + return 1; + } + else if(item->id == TOOL_SHOVEL && playerUseEnergy(4-item->countLevel)){ + if(rand()%5==0)addEntityToList(newItemEntity(newItem(ITEM_SEEDS,1),(x<<4)+8, (y<<4)+8,currentLevel),&eManager); + setTile(TILE_DIRT,x,y); + return 1; + } break; + case TILE_SAND: + if(item->id == ITEM_CACTUS){ + setTile(TILE_SAPLING_CACTUS,x,y); + --item->countLevel; + return 1; + } + else if(item->id == TOOL_SHOVEL && playerUseEnergy(4-item->countLevel)){ + addEntityToList(newItemEntity(newItem(ITEM_SAND,1), (x<<4)+8, (y<<4)+8, currentLevel), &eManager); + setTile(TILE_DIRT,x,y); + return 1; + } break; + case TILE_DIRT: + if(item->id == TOOL_HOE && playerUseEnergy(4-item->countLevel)){ + setTile(TILE_FARM,x,y); + return 1; + } + else if(item->id == ITEM_WOOD){ + setTile(TILE_WOOD_WALL,x,y); --item->countLevel; + return 1; + } + else if(item->id == ITEM_SAND){ + setTile(TILE_SAND,x,y); --item->countLevel; + return 1; + } + else if(item->id == TOOL_SHOVEL && playerUseEnergy(4-item->countLevel)){ + addEntityToList(newItemEntity(newItem(ITEM_DIRT,1), (x<<4)+8, (y<<4)+8, currentLevel), &eManager); + setTile(TILE_HOLE,x,y); + return 1; + } break; + case TILE_HOLE: if(item->id == ITEM_DIRT){ - setTile(TILE_DIRT, level, x, y); - --item->countLevel; - return 1; + setTile(TILE_DIRT,x,y); + --item->countLevel; + return 1; } - else if(item->id == TOOL_BUCKET && item->countLevel == 1 && playerUseEnergy(pd, 4)) { - setTile(TILE_WATER, level, x, y); + else if(item->id == TOOL_BUCKET && item->countLevel == 1 && playerUseEnergy(4)) { + setTile(TILE_WATER,x,y); item->countLevel = 0; - } - else if(item->id == TOOL_BUCKET && item->countLevel == 2 && playerUseEnergy(pd, 4)) { - setTile(TILE_LAVA, level, x, y); + } + else if(item->id == TOOL_BUCKET && item->countLevel == 2 && playerUseEnergy(4)) { + setTile(TILE_LAVA,x,y); item->countLevel = 0; - } break; - case TILE_WATER: + } break; + case TILE_WATER: if(item->id == ITEM_DIRT){ - setTile(TILE_DIRT, level, x, y); - --item->countLevel; - return 1; + setTile(TILE_DIRT,x,y); + --item->countLevel; + return 1; } - else if(item->id == TOOL_BUCKET && item->countLevel == 0 && playerUseEnergy(pd, 4)) { - setTile(TILE_HOLE, level, x, y); + else if(item->id == TOOL_BUCKET && item->countLevel == 0 && playerUseEnergy(4)) { + setTile(TILE_HOLE,x,y); item->countLevel = 1; - } break; - case TILE_LAVA: - if(item->id == ITEM_DIRT){ - setTile(TILE_DIRT, level, x, y); - --item->countLevel; - return 1; - } - else if(item->id == TOOL_BUCKET && item->countLevel == 0 && playerUseEnergy(pd, 4)) { - setTile(TILE_HOLE, level, x, y); + } break; + case TILE_LAVA: + if(item->id == ITEM_DIRT){ + setTile(TILE_DIRT,x,y); + --item->countLevel; + return 1; + } + else if(item->id == TOOL_BUCKET && item->countLevel == 0 && playerUseEnergy(4)) { + setTile(TILE_HOLE,x,y); item->countLevel = 2; - } break; - case TILE_NULL: - if(item->id == ITEM_CLOUD){ - setTile(TILE_CLOUD, level, x, y); - --item->countLevel; - return 1; - } break; - case TILE_FARM: - if(item->id == ITEM_SEEDS){ - setTile(TILE_WHEAT, level, x, y); - setData(0, level, x, y); - --item->countLevel; - return 1; - } break; - case TILE_WHEAT: - if(item->id == TOOL_HOE){ - if(getData(level, x, y) > -1){ - int age = getData(level, x, y); - int count = (rand() % 2); - if(age >= 80) count = (rand()%2) + 1; - addItemsToWorld(newItem(ITEM_SEEDS,1), level, (x<<4)+8, (y<<4)+8, count); - count = 0; - if(age == 100) count = (rand()%3) + 2; - else if(age >= 80) count = (rand()%2) + 1; - addItemsToWorld(newItem(ITEM_WHEAT,1), level, (x<<4)+8, (y<<4)+8, count); - setTile(TILE_DIRT, level, x, y); - } - } break; + } break; + case TILE_NULL: + if(item->id == ITEM_CLOUD){ + setTile(TILE_CLOUD,x,y); + --item->countLevel; + return 1; + } break; + case TILE_FARM: + if(item->id == ITEM_SEEDS){ + setTile(TILE_WHEAT,x,y); + setData(0,x,y); + --item->countLevel; + return 1; + } break; + case TILE_WHEAT: + if(item->id == TOOL_HOE){ + if(getData(x,y) > -1){ + int age = getData(x,y); + int count = (rand() % 2); + if(age >= 80) count = (rand()%2) + 1; + addItemsToWorld(newItem(ITEM_SEEDS,1),(x<<4)+8,(y<<4)+8,count); + count = 0; + if(age == 100)count = (rand()%3) + 2; + else if(age >= 80)count = (rand()%2) + 1; + addItemsToWorld(newItem(ITEM_WHEAT,1),(x<<4)+8,(y<<4)+8,count); + setTile(TILE_DIRT,x,y); + } + } break; case TILE_WOOD_WALL: - case TILE_BOOKSHELVES: - if(item->id == TOOL_AXE && playerUseEnergy(pd, 4-item->countLevel)){ - playerHurtTile(pd, tile, level, x, y, (rand()%10) + (item->countLevel) * 5 + 10, pd->entity.p.dir); - return 1; - } break; - case TILE_STONE_WALL: - case TILE_IRON_WALL: - case TILE_GOLD_WALL: - case TILE_GEM_WALL: - if(item->id == TOOL_PICKAXE && playerUseEnergy(pd, 4-item->countLevel)){ - playerHurtTile(pd, tile, level, x, y, (rand()%10) + (item->countLevel) * 5 + 10, pd->entity.p.dir); - return 1; - } break; - case TILE_WOOD_FLOOR: - if(item->id == TOOL_AXE && playerUseEnergy(pd, 4-item->countLevel)){ - addItemsToWorld(newItem(ITEM_WOOD,1), level, (x<<4)+8, (y<<4)+8, 1); - setTile(TILE_DIRT, level, x, y); - } break; - } - return 0; + if(item->id == TOOL_AXE && playerUseEnergy(4-item->countLevel)){ + playerHurtTile(tile, x, y, (rand()%10) + (item->countLevel) * 5 + 10, player.p.dir); + return 1; + } break; + } + return 0; } -void tickTile(s8 level, int x, int y){ - int tile = getTile(level, x, y); - int data = getData(level, x, y); - - switch(tile){ - case TILE_SAPLING_TREE: - if(worldData.season!=3) { - setData(++data, level, x, y); - if(data>100){setData(0, level, x, y); setTile(TILE_TREE, level, x, y);} +void tickTile(int x, int y){ + int tile = getTile(x,y); + int data = getData(x,y); + + switch(tile){ + case TILE_SAPLING_TREE: + setData(++data,x,y); if(data>100){setData(0,x,y); setTile(TILE_TREE,x,y);} + break; + case TILE_SAPLING_CACTUS: + setData(++data,x,y); if(data>100){setData(0,x,y); setTile(TILE_CACTUS,x,y);} + break; + case TILE_WHEAT: + if(data<100)setData(++data,x,y); + break; + case TILE_WATER: + if(getTile(x+1,y)==TILE_HOLE) setTile(TILE_WATER,x+1,y); + if(getTile(x-1,y)==TILE_HOLE) setTile(TILE_WATER,x-1,y); + if(getTile(x,y+1)==TILE_HOLE) setTile(TILE_WATER,x,y+1); + if(getTile(x,y-1)==TILE_HOLE) setTile(TILE_WATER,x,y-1); + break; + case TILE_LAVA: + if(getTile(x+1,y)==TILE_HOLE) setTile(TILE_LAVA,x+1,y); + if(getTile(x-1,y)==TILE_HOLE) setTile(TILE_LAVA,x-1,y); + if(getTile(x,y+1)==TILE_HOLE) setTile(TILE_LAVA,x,y+1); + if(getTile(x,y-1)==TILE_HOLE) setTile(TILE_LAVA,x,y-1); + + if(getTile(x+1,y)==TILE_WATER || getTile(x-1,y)==TILE_WATER || getTile(x,y+1)==TILE_WATER || getTile(x,y-1)==TILE_WATER) { + setTile(TILE_ROCK,x,y); + setData(0,x,y); } - break; - case TILE_TREE: - if(eManager.lastSlot[level]<800 && (worldData.daytime>18000 || worldData.daytime<5000) && rand()%800==0) { - //check for nearby glowworms - //TODO: This should really use getEntities - int i = 0; - for (i = 0; i < eManager.lastSlot[level]; ++i) { - Entity * e = &eManager.entities[level][i]; - if(e->type==ENTITY_GLOWWORM && ((e->x)-(x<<4))*((e->x)-(x<<4))+((e->y)-(y<<4))*((e->y)-(y<<4)) < (2<<4)*(2<<4)) return; - } - addEntityToList(newGlowwormEntity((x<<4)+8, (y<<4)+8, level), &eManager); - } - break; - case TILE_SAPLING_CACTUS: - if(worldData.season!=3) { - setData(++data, level, x, y); - if(data>100){setData(0, level, x, y); setTile(TILE_CACTUS, level, x, y);} - } - break; - case TILE_WHEAT: - if(data<100 && worldData.season!=3) setData(++data, level, x, y); - break; - case TILE_WATER: - if(getTile(level, x+1, y)==TILE_HOLE) setTile(TILE_WATER, level, x+1, y); - if(getTile(level, x-1, y)==TILE_HOLE) setTile(TILE_WATER, level, x-1, y); - if(getTile(level, x, y+1)==TILE_HOLE) setTile(TILE_WATER, level, x, y+1); - if(getTile(level, x, y-1)==TILE_HOLE) setTile(TILE_WATER, level, x, y-1); - if(level==1 && worldData.season==3 && rand()%12==0) { - if(getTile(level, x+1, y)!=TILE_WATER) setTile(TILE_ICE, level, x, y); - if(getTile(level, x-1, y)!=TILE_WATER) setTile(TILE_ICE, level, x, y); - if(getTile(level, x, y+1)!=TILE_WATER) setTile(TILE_ICE, level, x, y); - if(getTile(level, x, y-1)!=TILE_WATER) setTile(TILE_ICE, level, x, y); - } - break; - case TILE_LAVA: - if(getTile(level, x+1, y)==TILE_HOLE) setTile(TILE_LAVA, level, x+1, y); - if(getTile(level, x-1, y)==TILE_HOLE) setTile(TILE_LAVA, level, x-1, y); - if(getTile(level, x, y+1)==TILE_HOLE) setTile(TILE_LAVA, level, x, y+1); - if(getTile(level, x, y-1)==TILE_HOLE) setTile(TILE_LAVA, level, x, y-1); - - if(getTile(level, x+1, y)==TILE_WATER || getTile(level, x-1, y)==TILE_WATER || getTile(level, x, y+1)==TILE_WATER || getTile(level, x, y-1)==TILE_WATER) { - setTile(TILE_ROCK, level, x, y); - } - break; - case TILE_HOLE: // This makes water flow slightly faster than lava - if(getTile(level, x+1, y)==TILE_WATER) setTile(TILE_WATER, level, x, y); - if(getTile(level, x-1, y)==TILE_WATER) setTile(TILE_WATER, level, x, y); - if(getTile(level, x, y+1)==TILE_WATER) setTile(TILE_WATER, level, x, y); - if(getTile(level, x, y-1)==TILE_WATER) setTile(TILE_WATER, level, x, y); - break; - case TILE_GRASS: - if(getTile(level, x+1, y)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS, level, x+1, y); - if(getTile(level, x-1, y)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS, level, x-1, y); - if(getTile(level, x, y+1)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS, level, x, y+1); - if(getTile(level, x, y-1)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS, level, x, y-1); - break; - case TILE_SAND: - if(data > 0) setData(--data, level, x, y); - break; - case TILE_CLOUD: - if((rand()%24000)==0) setTile(TILE_CLOUDCACTUS, level, x, y); - break; - case TILE_MAGIC_BARRIER: - 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; - } - } - if(data==0) setTile(TILE_DUNGEON_FLOOR, level, x, y); - setData(rand()%2, level, x, y); - break; - case TILE_ICE: - if(worldData.season!=3) { - setTile(TILE_WATER, level, x, y); - } - break; - } - + break; + case TILE_HOLE: // This makes water flow slightly faster than lava + if(getTile(x+1,y)==TILE_WATER) setTile(TILE_WATER,x,y); + if(getTile(x-1,y)==TILE_WATER) setTile(TILE_WATER,x,y); + if(getTile(x,y+1)==TILE_WATER) setTile(TILE_WATER,x,y); + if(getTile(x,y-1)==TILE_WATER) setTile(TILE_WATER,x,y); + break; + case TILE_GRASS: + if(getTile(x+1,y)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS,x+1,y); + if(getTile(x-1,y)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS,x-1,y); + if(getTile(x,y+1)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS,x,y+1); + if(getTile(x,y-1)==TILE_DIRT) if((rand()%25) == 0) setTile(TILE_GRASS,x,y-1); + break; + } + } void tickEntityItem(Entity* e){ - ++e->entityItem.age; - if(e->entityItem.age == 630){ - removeEntityFromList(e, e->level, &eManager); - /* - Programming pro tip: - Remember to put a return statement after you remove the entity, - or else your going to have a very bad time like I did. - */ - return; - } - e->entityItem.xx += e->entityItem.xa; - e->entityItem.yy += e->entityItem.ya; - e->entityItem.zz += e->entityItem.za; - if (e->entityItem.zz < 0) { - e->entityItem.zz = 0; - e->entityItem.za *= -0.5; - e->entityItem.xa *= 0.6; - e->entityItem.ya *= 0.6; - } - e->entityItem.za -= 0.15; - int ox = e->x; - int oy = e->y; - int nx = (int) e->entityItem.xx; - int ny = (int) e->entityItem.yy; - int expectedx = nx - e->x; - int expectedy = ny - e->y; - move(e, nx - e->x, ny - e->y); - int gotx = e->x - ox; - int goty = e->y - oy; - e->entityItem.xx += gotx - expectedx; - e->entityItem.yy += goty - expectedy; + ++e->entityItem.age; + if(e->entityItem.age == 630){ + removeEntityFromList(e,e->level,&eManager); + /* + Programming pro tip: + Remember to put a return statement after you remove the entity, + or else your going to have a very bad time like I did. + */ + return; + } + e->entityItem.xx += e->entityItem.xa; + e->entityItem.yy += e->entityItem.ya; + e->entityItem.zz += e->entityItem.za; + if (e->entityItem.zz < 0) { + e->entityItem.zz = 0; + e->entityItem.za *= -0.5; + e->entityItem.xa *= 0.6; + e->entityItem.ya *= 0.6; + } + e->entityItem.za -= 0.15; + int ox = e->x; + int oy = e->y; + int nx = (int) e->entityItem.xx; + int ny = (int) e->entityItem.yy; + int expectedx = nx - e->x; + int expectedy = ny - e->y; + move(e, nx - e->x, ny - e->y); + int gotx = e->x - ox; + int goty = e->y - oy; + e->entityItem.xx += gotx - expectedx; + e->entityItem.yy += goty - expectedy; } void tickEntityTextParticle(Entity* e){ - ++e->textParticle.age; - if(e->textParticle.age == 60){ - removeEntityFromList(e, e->level, &eManager); - return; - } - e->textParticle.xx += e->textParticle.xa; - e->textParticle.yy += e->textParticle.ya; - e->textParticle.zz += e->textParticle.za; - if (e->textParticle.zz < 0) { - e->textParticle.zz = 0; - e->textParticle.za *= -0.5; - e->textParticle.xa *= 0.6; - e->textParticle.ya *= 0.6; - } - e->textParticle.za -= 0.15; - e->x = (int) e->textParticle.xx; - e->y = (int) e->textParticle.yy; + ++e->textParticle.age; + if(e->textParticle.age == 60){ + removeEntityFromList(e,e->level,&eManager); + return; + } + e->textParticle.xx += e->textParticle.xa; + e->textParticle.yy += e->textParticle.ya; + e->textParticle.zz += e->textParticle.za; + if (e->textParticle.zz < 0) { + e->textParticle.zz = 0; + e->textParticle.za *= -0.5; + e->textParticle.xa *= 0.6; + e->textParticle.ya *= 0.6; + } + e->textParticle.za -= 0.15; + e->x = (int) e->textParticle.xx; + e->y = (int) e->textParticle.yy; } void tickEntity(Entity* e){ - PlayerData *nearestPlayer = getNearestPlayer(e->level, e->x, e->y); - switch(e->type){ - case ENTITY_ITEM: tickEntityItem(e); return; - case ENTITY_FURNITURE: return; - case ENTITY_MAGIC_PILLAR: return; - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - if (e->hurtTime > 0) e->hurtTime--; - if (e->hostile.randWalkTime == 0 && e->type != ENTITY_SKELETON && nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - int dist = 50 * 50; - if(e->type == ENTITY_KNIGHT) dist = 80 * 80; + switch(e->type){ + case ENTITY_ITEM: tickEntityItem(e); return; + case ENTITY_FURNITURE: return; + case ENTITY_ZOMBIE: + if (e->hurtTime > 0) e->hurtTime--; + if (e->zombie.randWalkTime == 0) { + int xd = player.x - e->x; + int yd = player.y - e->y; + if (xd * xd + yd * yd < 50 * 50) { + e->zombie.xa = 0; + e->zombie.ya = 0; + if (xd < 0) e->zombie.xa = -1; + if (xd > 0) e->zombie.xa = +1; + if (yd < 0) e->zombie.ya = -1; + if (yd > 0) e->zombie.ya = +1; + } + } + + if(e->zombie.xa < 0) e->zombie.dir = 2; + else if(e->zombie.xa > 0) e->zombie.dir = 3; + if(e->zombie.ya < 0) e->zombie.dir = 1; + else if(e->zombie.ya > 0) e->zombie.dir = 0; + + if(e->zombie.xa != 0 || e->zombie.ya != 0) e->zombie.walkDist++; - //charge player - if (xd * xd + yd * yd < dist) { - e->hostile.xa = 0; - e->hostile.ya = 0; - if (xd < 0) e->hostile.xa = -1; - if (xd > 0) e->hostile.xa = +1; - if (yd < 0) e->hostile.ya = -1; - if (yd > 0) e->hostile.ya = +1; - } - } - - if(e->hostile.xa < 0) e->hostile.dir = 2; - else if(e->hostile.xa > 0) e->hostile.dir = 3; - if(e->hostile.ya < 0) e->hostile.dir = 1; - else if(e->hostile.ya > 0) e->hostile.dir = 0; - - if(e->type == ENTITY_SKELETON) { - --(e->hostile.randAttackTime); - if(e->hostile.randAttackTime <= 0) { - e->hostile.randAttackTime = 80 - (e->hostile.lvl * 5); - - int aitemID = ITEM_ARROW_WOOD; - if(e->hostile.lvl >= 2) aitemID = ITEM_ARROW_STONE; - - //turn to player when attacking - if(nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - if(xd*xd > yd*yd) { - if (xd < 0) e->hostile.dir = 2; - if (xd > 0) e->hostile.dir = 3; - } else { - if (yd < 0) e->hostile.dir = 1; - if (yd > 0) e->hostile.dir = 0; - } - } - - switch(e->hostile.dir) { - case 0: - addEntityToList(newArrowEntity(e, aitemID, 0, 2, e->level), &eManager); - break; - case 1: - addEntityToList(newArrowEntity(e, aitemID, 0, -2, e->level), &eManager); - break; - case 2: - addEntityToList(newArrowEntity(e, aitemID, -2, 0, e->level), &eManager); - break; - case 3: - addEntityToList(newArrowEntity(e, aitemID, 2, 0, e->level), &eManager); - break; - } - } - } - - if(e->hostile.xa != 0 || e->hostile.ya != 0) e->hostile.walkDist++; - - int speed = syncTickCount & 1; - if (!moveMob(e, e->hostile.xa * speed, e->hostile.ya * speed) || (rand()%100) == 0) { - e->hostile.randWalkTime = 60; - e->hostile.xa = ((rand()%3) - 1) * (rand()%2); - e->hostile.ya = ((rand()%3) - 1) * (rand()%2); - } - if (e->hostile.randWalkTime > 0) e->hostile.randWalkTime--; - return; - case ENTITY_SLIME: - if (e->hurtTime > 0) e->hurtTime--; - - if (!moveMob(e, e->slime.xa, e->slime.ya) || (rand()%10) == 0) { - if (e->slime.jumpTime <= -10) { - e->slime.xa = ((rand()%3) - 1); - e->slime.ya = ((rand()%3) - 1); - - if(nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - if (xd * xd + yd * yd < 50 * 50) { - if (xd < 0) e->slime.xa = -1; - if (xd > 0) e->slime.xa = +1; - if (yd < 0) e->slime.ya = -1; - if (yd > 0) e->slime.ya = +1; - } - } - - if (e->slime.xa != 0 || e->slime.ya != 0) e->slime.jumpTime = 10; - } - } - - if(e->slime.xa < 0) e->slime.dir = 2; - else if(e->slime.xa > 0) e->slime.dir = 3; - if(e->slime.ya < 0) e->slime.dir = 1; - else if(e->slime.ya > 0) e->slime.dir = 0; - - if (e->slime.jumpTime > -10) e->slime.jumpTime--; - if(e->slime.jumpTime == 0){ - e->slime.xa = 0; - e->slime.ya = 0; - } - return; - case ENTITY_AIRWIZARD: - if (e->hurtTime > 0) e->hurtTime--; - - if (e->wizard.attackDelay > 0) { - e->wizard.dir = (e->wizard.attackDelay - 45) / 4 % 4; - e->wizard.dir = (e->wizard.dir * 2 % 4) + (e->wizard.dir / 2); - if (e->wizard.attackDelay < 45) e->wizard.dir = 0; - e->wizard.attackDelay--; - if (e->wizard.attackDelay <= 0) { - e->wizard.attackType = 0; - if (e->wizard.health < 1000) e->wizard.attackType = 1; - if (e->wizard.health < 200) e->wizard.attackType = 2; - e->wizard.attackTime = 120; - } - return; - } - - if (e->wizard.attackTime > 0) { - e->wizard.attackTime--; - float dir = e->wizard.attackTime * 0.25 * (e->wizard.attackTime % 2 * 2 - 1); - float speed = (0.7) + (e->wizard.attackType+1) * 0.2; - addEntityToList(newSparkEntity(e, cos(dir) * speed, sin(dir) * speed), &eManager); - return; - } - - if (e->wizard.randWalkTime == 0 && nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - int dist = xd * xd + yd * yd; - if (dist > 80 * 80) { - e->wizard.xa = 0; - e->wizard.ya = 0; - if (xd < 0) e->wizard.xa = -1; - if (xd > 0) e->wizard.xa = +1; - if (yd < 0) e->wizard.ya = -1; - if (yd > 0) e->wizard.ya = +1; - } else if (dist < 24 * 24) { - e->wizard.xa = 0; - e->wizard.ya = 0; - if (xd < 0) e->wizard.xa = +1; - if (xd > 0) e->wizard.xa = -1; - if (yd < 0) e->wizard.ya = +1; - if (yd > 0) e->wizard.ya = -1; - } - } - - int wSpeed = (syncTickCount % 4) == 0 ? 0 : 1; - if (!moveMob(e, e->wizard.xa * wSpeed, e->wizard.ya * wSpeed) || (rand()%100) == 0) { - e->wizard.randWalkTime = 30; - e->wizard.xa = ((rand()%3) - 1) * (rand()%2); - e->wizard.ya = ((rand()%3) - 1) * (rand()%2); - } - - if(e->wizard.xa != 0 || e->wizard.ya != 0){ - e->wizard.walkDist++; - awX = e->x; - awY = e->y; - } - - if(e->wizard.xa < 0) e->wizard.dir = 2; - else if(e->wizard.xa > 0) e->wizard.dir = 3; - if(e->wizard.ya < 0) e->wizard.dir = 1; - else if(e->wizard.ya > 0) e->wizard.dir = 0; - - if (e->wizard.randWalkTime > 0) { - e->wizard.randWalkTime--; - if (e->wizard.randWalkTime == 0 && nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - if (rand()%4 == 0 && xd * xd + yd * yd < 50 * 50) { - if (e->wizard.attackDelay == 0 && e->wizard.attackTime == 0) e->wizard.attackDelay = 120; - } - } - } - - return; - case ENTITY_SPARK: - e->spark.age++; - if (e->spark.age >= 260) { - removeEntityFromList(e, e->level, &eManager); - return; - } - e->spark.xx += e->spark.xa; - e->spark.yy += e->spark.ya; - e->x = (int) e->spark.xx; - e->y = (int) e->spark.yy; - - if(nearestPlayer!=NULL && intersects(nearestPlayer->entity, e->x + e->spark.xa - e->xr, e->y + e->spark.ya - e->yr, e->x + e->spark.xa + e->xr, e->y + e->spark.ya + e->yr)){ - EntityVsEntity(e, &(nearestPlayer->entity)); - removeEntityFromList(e, e->level, &eManager); - } - return; - case ENTITY_DRAGON: - if (e->hurtTime > 0) e->hurtTime--; - - e->dragon.animTimer++; - if(e->dragon.animTimer>=4*4) { - e->dragon.animTimer = 0; - } - - //choose random attack - if (e->dragon.attackDelay > 0) { - e->dragon.attackDelay--; - if (e->dragon.attackDelay <= 0) { - e->dragon.attackType = rand()%2; - e->dragon.attackTime = 121; - } - return; - } - - if (e->dragon.attackTime > 0) { - e->dragon.attackTime--; - - //turn to player when attacking - if(nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - if(xd*xd > yd*yd) { - if (xd < 0) e->dragon.dir = 2; - if (xd > 0) e->dragon.dir = 3; - } else { - if (yd < 0) e->dragon.dir = 1; - if (yd > 0) e->dragon.dir = 0; - } - } - - switch(e->dragon.attackType) { - case 0: //Firebreathing - if(e->dragon.attackTime%2 == 0) { - float dfdir = 0; - - if(e->dragon.dir==0) dfdir = 1 * 3.141592 / 2; - else if(e->dragon.dir==1) dfdir = 3 * 3.141592 / 2; - else if(e->dragon.dir==2) dfdir = 2 * 3.141592 / 2; - else if(e->dragon.dir==3) dfdir = 0 * 3.141592 / 2; - - dfdir += 0.03141592 * ((rand()%33) - 16); - - addEntityToList(newDragonFireEntity(e, e->dragon.attackType, e->x + cos(dfdir)*14, e->y + sin(dfdir)*14, cos(dfdir), sin(dfdir)), &eManager); - } - break; - case 1: //Firering - if(e->dragon.attackTime%20 == 0) { - int ai = 0; - for(ai = 0; ai < 16; ai++) { - float ddir = (3.141592 * 2 / 16.0) * ai; - float ddist = (140 - e->dragon.attackTime) / 2; - - addEntityToList(newDragonFireEntity(e, e->dragon.attackType, (e->x) + cos(ddir)*ddist, (e->y) + sin(ddir)*ddist, 0, 0), &eManager); - } - } - break; - } - - return; - } - - //TODO - movement copied from airwizard, adjust to better fit dragon - if (e->dragon.randWalkTime == 0 && nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - int dist = xd * xd + yd * yd; - if (dist > 64 * 64) { - e->dragon.xa = 0; - e->dragon.ya = 0; - if (xd < 0) e->dragon.xa = -1; - if (xd > 0) e->dragon.xa = +1; - if (yd < 0) e->dragon.ya = -1; - if (yd > 0) e->dragon.ya = +1; - } else if (dist < 16 * 16) { - e->dragon.xa = 0; - e->dragon.ya = 0; - if (xd < 0) e->dragon.xa = +1; - if (xd > 0) e->dragon.xa = -1; - if (yd < 0) e->dragon.ya = +1; - if (yd > 0) e->dragon.ya = -1; - } - } - - int dSpeed = (syncTickCount % 4) == 0 ? 0 : 1; - if (!moveMob(e, e->dragon.xa * dSpeed, e->dragon.ya * dSpeed) || (rand()%120) == 0) { - e->dragon.randWalkTime = 30; - e->dragon.xa = ((rand()%3) - 1) * (rand()%2); - e->dragon.ya = ((rand()%3) - 1) * (rand()%2); - } - - if(e->dragon.xa != 0 || e->dragon.ya != 0){ - e->dragon.walkDist++; - } - - if(e->dragon.xa < 0) e->dragon.dir = 2; - else if(e->dragon.xa > 0) e->dragon.dir = 3; - if(e->dragon.ya < 0) e->dragon.dir = 1; - else if(e->dragon.ya > 0) e->dragon.dir = 0; - - //if (e->dragon.randWalkTime > 0) { - // e->dragon.randWalkTime--; - // if (e->dragon.randWalkTime == 0) { - if(nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - if (rand()%12 == 0 && xd * xd + yd * yd < 50 * 50) { - if (e->dragon.attackDelay == 0 && e->dragon.attackTime == 0) e->dragon.attackDelay = 40; - } - } - // } - //} - - return; - case ENTITY_DRAGONPROJECTILE: - e->dragonFire.age++; - if (e->dragonFire.age >= 30) { - removeEntityFromList(e, e->level, &eManager); - return; - } - e->dragonFire.xx += e->dragonFire.xa; - e->dragonFire.yy += e->dragonFire.ya; - e->x = (int) e->dragonFire.xx; - e->y = (int) e->dragonFire.yy; - - if(nearestPlayer!=NULL && intersects(nearestPlayer->entity, e->x + e->dragonFire.xa - e->xr, e->y + e->dragonFire.ya - e->yr, e->x + e->dragonFire.xa + e->xr, e->y + e->dragonFire.ya + e->yr)){ - EntityVsEntity(e, &(nearestPlayer->entity)); - removeEntityFromList(e, e->level, &eManager); - } - return; - case ENTITY_ARROW: - e->arrow.age++; - if (e->arrow.age >= 260 || !move(e, e->arrow.xa, e->arrow.ya)) { - //only drop arrows shot by player - if(e->arrow.parent->type == ENTITY_PLAYER) addItemsToWorld(newItem(e->arrow.itemID,1), e->level, e->x+4, e->y+4, 1); - removeEntityFromList(e, e->level, &eManager); - return; - } - return; - case ENTITY_PASSIVE: - if (e->hurtTime > 0) e->hurtTime--; - if (e->passive.randWalkTime == 0 && nearestPlayer!=NULL) { - int xd = nearestPlayer->entity.x - e->x; - int yd = nearestPlayer->entity.y - e->y; - //flee from player - if (xd * xd + yd * yd < 40 * 40) { - e->passive.xa = 0; - e->passive.ya = 0; - if (xd < 0) e->passive.xa = +1; - if (xd > 0) e->passive.xa = -1; - if (yd < 0) e->passive.ya = +1; - if (yd > 0) e->passive.ya = -1; - } - } - - if(e->passive.xa < 0) e->passive.dir = 2; - else if(e->passive.xa > 0) e->passive.dir = 3; - if(e->passive.ya < 0) e->passive.dir = 1; - else if(e->passive.ya > 0) e->passive.dir = 0; - - if(e->passive.xa != 0 || e->passive.ya != 0) e->passive.walkDist++; - - int pspeed = syncTickCount & 1; - if (!moveMob(e, e->passive.xa * pspeed, e->passive.ya * pspeed) || (rand()%100) == 0) { - e->passive.randWalkTime = 60; - e->passive.xa = ((rand()%3) - 1) * (rand()%2); - e->passive.ya = ((rand()%3) - 1) * (rand()%2); - } - if (e->passive.randWalkTime > 0) e->passive.randWalkTime--; - return; - case ENTITY_GLOWWORM: - if(worldData.daytime>5000 && worldData.daytime<6000) { - if(rand()%200==0) { - removeEntityFromList(e, e->level, &eManager); - return; - } - } else if(worldData.daytime>6000 && worldData.daytime<18000) { - removeEntityFromList(e, e->level, &eManager); - return; - } - - int gspeed = (((syncTickCount & 0x3) == 3) ? 1 : 0); - if (!moveMob(e, e->glowworm.xa * gspeed, e->glowworm.ya * gspeed) || (e->glowworm.randWalkTime==0) || (rand()%20) == 0) { - if(e->glowworm.randWalkTime != 0) { - e->glowworm.waitTime = 20 + (rand()%60); - } - if(e->glowworm.waitTime == 0 || getTile(e->level, (e->x)>>4, (e->y)>>4)!=TILE_TREE) { - e->glowworm.randWalkTime = 20; - e->glowworm.xa = ((rand()%3) - 1) * (rand()%2); - e->glowworm.ya = ((rand()%3) - 1) * (rand()%2); - } else { - e->glowworm.xa = 0; - e->glowworm.ya = 0; - } - } - if (e->glowworm.randWalkTime > 0) { - e->glowworm.randWalkTime--; - if(e->glowworm.randWalkTime==0 && (e->glowworm.xa != 0 || e->glowworm.xa != 0)) { - e->glowworm.waitTime = 120 + (rand()%60); - } - } else if (e->glowworm.waitTime > 0) { - e->glowworm.waitTime--; - } - return; - case ENTITY_TEXTPARTICLE: tickEntityTextParticle(e); return; - case ENTITY_SMASHPARTICLE: - ++e->smashParticle.age; - if(e->smashParticle.age > 10) removeEntityFromList(e, e->level, &eManager); - return; - } + int speed = tickCount & 1; + if (!moveMob(e, e->zombie.xa * speed, e->zombie.ya * speed) || (rand()%100) == 0) { + e->zombie.randWalkTime = 60; + e->zombie.xa = ((rand()%3) - 1) * (rand()%2); + e->zombie.ya = ((rand()%3) - 1) * (rand()%2); + } + if (e->zombie.randWalkTime > 0) e->zombie.randWalkTime--; + return; + case ENTITY_SLIME: + if (e->hurtTime > 0) e->hurtTime--; + + if (!moveMob(e, e->slime.xa, e->slime.ya) || (rand()%10) == 0) { + if (e->slime.jumpTime <= -10) { + e->slime.xa = ((rand()%3) - 1); + e->slime.ya = ((rand()%3) - 1); + + int xd = player.x - e->x; + int yd = player.y - e->y; + if (xd * xd + yd * yd < 50 * 50) { + if (xd < 0) e->slime.xa = -1; + if (xd > 0) e->slime.xa = +1; + if (yd < 0) e->slime.ya = -1; + if (yd > 0) e->slime.ya = +1; + } + + if (e->slime.xa != 0 || e->slime.ya != 0) e->slime.jumpTime = 10; + } + } + + if(e->slime.xa < 0) e->slime.dir = 2; + else if(e->slime.xa > 0) e->slime.dir = 3; + if(e->slime.ya < 0) e->slime.dir = 1; + else if(e->slime.ya > 0) e->slime.dir = 0; + + if (e->slime.jumpTime > -10) e->slime.jumpTime--; + if(e->slime.jumpTime == 0){ + e->slime.xa = 0; + e->slime.ya = 0; + } + return; + case ENTITY_AIRWIZARD: + if (e->hurtTime > 0) e->hurtTime--; + + if (e->wizard.attackDelay > 0) { + e->wizard.dir = (e->wizard.attackDelay - 45) / 4 % 4; + e->wizard.dir = (e->wizard.dir * 2 % 4) + (e->wizard.dir / 2); + if (e->wizard.attackDelay < 45) e->wizard.dir = 0; + e->wizard.attackDelay--; + if (e->wizard.attackDelay <= 0) { + e->wizard.attackType = 0; + if (e->wizard.health < 1000) e->wizard.attackType = 1; + if (e->wizard.health < 200) e->wizard.attackType = 2; + e->wizard.attackTime = 120; + } + return; + } + + if (e->wizard.attackTime > 0) { + e->wizard.attackTime--; + float dir = e->wizard.attackTime * 0.25 * (e->wizard.attackTime % 2 * 2 - 1); + float speed = (0.7) + (e->wizard.attackType+1) * 0.2; + addEntityToList(newSparkEntity(e, cos(dir) * speed, sin(dir) * speed), &eManager); + return; + } + + if (e->wizard.randWalkTime == 0) { + int xd = player.x - e->x; + int yd = player.y - e->y; + int dist = xd * xd + yd * yd; + if (dist > 80 * 80) { + e->wizard.xa = 0; + e->wizard.ya = 0; + if (xd < 0) e->wizard.xa = -1; + if (xd > 0) e->wizard.xa = +1; + if (yd < 0) e->wizard.ya = -1; + if (yd > 0) e->wizard.ya = +1; + } else if (dist < 24 * 24) { + e->wizard.xa = 0; + e->wizard.ya = 0; + if (xd < 0) e->wizard.xa = +1; + if (xd > 0) e->wizard.xa = -1; + if (yd < 0) e->wizard.ya = +1; + if (yd > 0) e->wizard.ya = -1; + } + } + + int wSpeed = (tickCount % 4) == 0 ? 0 : 1; + if (!moveMob(e, e->wizard.xa * wSpeed, e->wizard.ya * wSpeed) || (rand()%100) == 0) { + e->wizard.randWalkTime = 30; + e->wizard.xa = ((rand()%3) - 1) * (rand()%2); + e->wizard.ya = ((rand()%3) - 1) * (rand()%2); + } + + if(e->wizard.xa != 0 || e->wizard.ya != 0){ + e->wizard.walkDist++; + awX = e->x; + awY = e->y; + } + + if(e->wizard.xa < 0) e->wizard.dir = 2; + else if(e->wizard.xa > 0) e->wizard.dir = 3; + if(e->wizard.ya < 0) e->wizard.dir = 1; + else if(e->wizard.ya > 0) e->wizard.dir = 0; + + if (e->wizard.randWalkTime > 0) { + e->wizard.randWalkTime--; + if (e->wizard.randWalkTime == 0) { + int xd = player.x - e->x; + int yd = player.y - e->y; + if (rand()%4 == 0 && xd * xd + yd * yd < 50 * 50) { + if (e->wizard.attackDelay == 0 && e->wizard.attackTime == 0) e->wizard.attackDelay = 120; + } + } + } + + return; + case ENTITY_SPARK: + e->spark.age++; + if (e->spark.age >= 260) { + removeEntityFromList(e,e->level,&eManager); + return; + } + e->spark.xx += e->spark.xa; + e->spark.yy += e->spark.ya; + e->x = (int) e->spark.xx; + e->y = (int) e->spark.yy; + + if(intersects(player, e->x + e->spark.xa - e->xr, e->y + e->spark.ya - e->yr, e->x + e->spark.xa + e->xr, e->y + e->spark.ya + e->yr)){ + EntityVsEntity(e, &player); + removeEntityFromList(e,e->level,&eManager); + } + return; + case ENTITY_TEXTPARTICLE: tickEntityTextParticle(e); return; + case ENTITY_SMASHPARTICLE: + ++e->smashParticle.age; + if(e->smashParticle.age > 10) removeEntityFromList(e,e->level,&eManager); + return; + } } void trySpawn(int count, int level) { - int i, j; + int i; for (i = 0; i < count; i++) { - if(eManager.lastSlot[level] > 900) continue; + if(eManager.lastSlot[level] > 900) continue; Entity e; - + int minLevel = 1; int maxLevel = 1; if (level > 0) maxLevel = level; else if (level == 0) { minLevel = maxLevel = 4; } - if(level > 4) { - minLevel = maxLevel = 4; - } - - int rx = rand()%128; - int ry = rand()%128; - int ex = (rx<<4)+8; - int ey = (ry<<4)+8; - - //do not spawn near players - for(j = 0; j players[j].entity.x-160 && ey > players[j].entity.y-125 && ex < players[j].entity.x+160 && ey < players[j].entity.y+125)) continue; - } - - //spawn if tile is free - if (!tileIsSolid(worldData.map[level][rx+ry*128],&e)) { - if(level==1 && (rand()%2)==0) { //passive entities on overworld - e = newPassiveEntity(rand()%3, ex, ey, level); - } else { - int lvl = (rand()%(maxLevel - minLevel + 1)) + minLevel; - int randMax = 1; - - if(level>1 || level==0) randMax = 2; - if(level>3) randMax = 3; - - switch (rand()%(randMax+1)) { - case 0: - e = newSlimeEntity(lvl, ex, ey, level); - break; - case 1: - e = newZombieEntity(lvl, ex, ey, level); - break; - case 2: - e = newSkeletonEntity(lvl, ex, ey, level); - break; - case 3: - e = newKnightEntity(lvl, ex, ey, level); - break; - } - } + + int rx = rand()%128; + int ry = rand()%128; + int ex = (rx<<4)+8; + int ey = (ry<<4)+8; + + if(level == currentLevel && (ex > player.x-160 && ey > player.y-125 && ex < player.x+160 && ey < player.y+125)) continue; + + if (!tileIsSolid(map[level][rx+ry*128],&e)) { + int lvl = (rand()%(maxLevel - minLevel + 1)) + minLevel; + if ((rand()%2) == 0) e = newSlimeEntity(lvl, ex, ey, level); + else e = newZombieEntity(lvl, ex, ey, level); addEntityToList(e, &eManager); } } } -int getTile(s8 level, int x, int y){ - if(x < 0 || y < 0 || x > 128 || y > 128) return -1; - return worldData.map[level][x+y*128]; +int getTile(int x, int y){ + if(x < 0 || y < 0 || x > 128 || y > 128) return -1; + return map[currentLevel][x+y*128]; } -void setTile(int id, s8 level, int x, int y){ - if(x < 0 || y < 0 || x > 128 || y > 128) return; - worldData.map[level][x+y*128] = id; - worldData.data[level][x+y*128] = 0; //reset data(set again if needed, hopefully this breaks nothing) - - sf2d_set_pixel(minimap[level], x, y, getMinimapColor(getLocalPlayer(), level, x, y)); +void setTile(int id, int x, int y){ + if(x < 0 || y < 0 || x > 128 || y > 128) return; + map[currentLevel][x+y*128] = id; + sf2d_set_pixel(minimap[currentLevel], x, y, getTileColor(id)); +} +int getData(int x, int y){ + if(x < 0 || y < 0 || x > 128 || y > 128) return -1; + return data[currentLevel][x+y*128]; } -int getData(s8 level, int x, int y){ - if(x < 0 || y < 0 || x > 128 || y > 128) return -1; - return worldData.data[level][x+y*128]; +void setData(int id, int x, int y){ + if(x < 0 || y < 0 || x > 128 || y > 128) return; + data[currentLevel][x+y*128] = id; } -void setData(int id, s8 level, int x, int y){ - if(x < 0 || y < 0 || x > 128 || y > 128) return; - worldData.data[level][x+y*128] = id; +void spawnPlayer(){ + while(true){ + int rx = rand()%128; + int ry = rand()%128; + if(getTile(rx,ry) == TILE_GRASS){ + player.x = (rx << 4) + 8; + player.y = (ry << 4) + 8; + break; + } + } + } -void addSmashParticles(s8 level, int x, int y, int damage) { - char hurtText[11]; - sprintf(hurtText, "%d", damage); - addEntityToList(newTextParticleEntity(hurtText, 0xFF0000FF, x, y, level), &eManager); - addEntityToList(newSmashParticleEntity(x, y, level), &eManager); +void initPlayer(){ + player.type = ENTITY_PLAYER; + spawnPlayer(); + player.xr = 4; + player.yr = 3; + player.canSwim = true; + player.p.ax = 0; + player.p.ay = 0; + player.p.health = 10; + player.p.stamina = 10; + player.p.score = 0; + player.p.walkDist = 0; + player.p.attackTimer = 0; + player.p.dir = 0; + player.p.inv = &eManager.invs[0]; + eManager.nextInv++; + player.p.inv->lastSlot = 0; + player.p.activeItem = &noItem; + player.p.isDead = false; + player.p.hasWon = false; + + addItemToInventory(newItem(ITEM_WORKBENCH,0), player.p.inv); + addItemToInventory(newItem(ITEM_POWGLOVE,0), player.p.inv); + + /* + addItemToInventory(newItem(TOOL_SHOVEL,4), player.p.inv); + addItemToInventory(newItem(TOOL_HOE,4), player.p.inv); + addItemToInventory(newItem(TOOL_SWORD,4), player.p.inv); + addItemToInventory(newItem(TOOL_PICKAXE,4), player.p.inv); + addItemToInventory(newItem(TOOL_AXE,4), player.p.inv); + + addItemToInventory(newItem(ITEM_ANVIL,0), player.p.inv); + addItemToInventory(newItem(ITEM_CHEST,0), player.p.inv); + addItemToInventory(newItem(ITEM_OVEN,0), player.p.inv); + addItemToInventory(newItem(ITEM_FURNACE,0), player.p.inv); + addItemToInventory(newItem(ITEM_LANTERN,0), player.p.inv); + + int i; + for (i = 7;i < 28;++i) addItemToInventory(newItem(i,50), player.p.inv); + //*/ } -void damageAndBreakTile(s8 level, int xt, int yt, int damage, int maxDamage, int replaceTile, int numItems, ...) { - int i; - - //damage indicator - addSmashParticles(level, xt<<4, yt<<4, damage); - - //do damage - setData(getData(level, xt, yt)+damage, level, xt, yt); - - //tile has been destroyed - if(getData(level, xt, yt)>maxDamage) { - setTile(replaceTile, level, xt, yt); - - //drop items - va_list al; - numItems<<=1; //each item is the item+count, moved up here to get rid of warning - va_start(al, numItems); - numItems>>=1; - for(i=0; iactiveItem->id != TOOL_PICKAXE || pd->activeItem->countLevel < 4) && !shouldRenderDebug) damage = 0; - damageAndBreakTile(level, xt, yt, damage, 200, TILE_DIRT, 2, newItem(ITEM_STONE,1), rand()%4+1, newItem(ITEM_COAL,1), rand()%2); - break; - case TILE_IRONORE: - case TILE_GOLDORE: - case TILE_GEMORE: - if(pd->activeItem->id != TOOL_PICKAXE) damage = 0; - addSmashParticles(level, xt<<4, yt<<4, damage); - setData(getData(level, xt, yt)+damage, level, xt, yt); - if(getData(level, xt, yt) > 0){ - int count = rand() & 1; - if (getData(level, xt, yt) >= (rand()%10) + 3) { - if(level!=5) setTile(TILE_DIRT, level, xt, yt); - else setTile(TILE_DUNGEON_FLOOR, level, xt, yt); - count += 2; - } - if(tile==TILE_IRONORE) addItemsToWorld(newItem(ITEM_IRONORE,1), level, (xt<<4)+8, (yt<<4)+8, count); - if(tile==TILE_GOLDORE) addItemsToWorld(newItem(ITEM_GOLDORE,1), level, (xt<<4)+8, (yt<<4)+8, count); - if(tile==TILE_GEMORE) addItemsToWorld(newItem(ITEM_GEM,1), level, (xt<<4)+8, (yt<<4)+8, count); - } break; - case TILE_CLOUDCACTUS: - if(pd->activeItem->id != TOOL_PICKAXE) damage = 0; - addSmashParticles(level, xt<<4, yt<<4, damage); - setData(getData(level, xt, yt)+damage, level, xt, yt); - if(getData(level, xt, yt) > 0){ - int count = rand() % 3; - if (getData(level, xt, yt) >= (rand()%10) + 3) { - setTile(TILE_CLOUD, level, xt, yt); - count += 3; - } - addItemsToWorld(newItem(ITEM_CLOUD,1), level, (xt<<4)+8, (yt<<4)+8, count); - } break; - case TILE_FARM: - setTile(TILE_DIRT, level, xt, yt); - break; - case TILE_SAPLING_TREE: - setTile(TILE_GRASS, level, xt, yt); - break; - case TILE_SAPLING_CACTUS: - setTile(TILE_SAND, level, xt, yt); - break; - case TILE_WHEAT: - if(getData(level, xt, yt) > -1){ - int age = getData(level, xt, yt); - int count = (rand() % 2); - if(age >= 80) count = (rand()%2) + 1; - addItemsToWorld(newItem(ITEM_SEEDS,1), level, (xt<<4)+8, (yt<<4)+8, count); - count = 0; - if(age == 100) count = (rand()%3) + 2; - else if(age >= 80) count = (rand()%2) + 1; - addItemsToWorld(newItem(ITEM_WHEAT,1), level, (xt<<4)+8, (yt<<4)+8, count); - setTile(TILE_DIRT, level, xt, yt); - } break; - case TILE_FLOWER: - setTile(TILE_GRASS, level, xt,yt); - addItemsToWorld(newItem(ITEM_FLOWER,1), level, (xt<<4)+8, (yt<<4)+8, 1); - break; +void playerHurtTile(int tile, int xt, int yt, int damage, int dir){ + char hurtText[11]; + switch(tile){ + case TILE_TREE: + if(rand()%120==0)addEntityToList(newItemEntity(newItem(ITEM_APPLE,1), (xt<<4)+8,(yt<<4)+8, currentLevel), &eManager); + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 20){ + setTile(TILE_GRASS,xt,yt); + addItemsToWorld(newItem(ITEM_WOOD,1),(xt<<4)+8,(yt<<4)+8,rand()%2+1); + addItemsToWorld(newItem(ITEM_ACORN,1),(xt<<4)+8,(yt<<4)+8,rand()%2); + } + break; + case TILE_CACTUS: + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 10){ + setTile(TILE_SAND,xt,yt); + addItemsToWorld(newItem(ITEM_CACTUS,1),(xt<<4)+8,(yt<<4)+8,rand()%2+1); + } + break; + case TILE_ROCK: + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 50){ + setTile(TILE_DIRT,xt,yt); + addItemsToWorld(newItem(ITEM_STONE,1),(xt<<4)+8,(yt<<4)+8,rand()%4+1); + addItemsToWorld(newItem(ITEM_COAL,1),(xt<<4)+8,(yt<<4)+8,rand()%2); + } + break; + case TILE_HARDROCK: + if(player.p.activeItem->id != TOOL_PICKAXE || player.p.activeItem->countLevel < 4) damage = 0; + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 200){ + setTile(TILE_DIRT,xt,yt); + addItemsToWorld(newItem(ITEM_STONE,1),(xt<<4)+8,(yt<<4)+8,rand()%4+1); + addItemsToWorld(newItem(ITEM_COAL,1),(xt<<4)+8,(yt<<4)+8,rand()%2); + } + break; + case TILE_IRONORE: + if(player.p.activeItem->id != TOOL_PICKAXE) damage = 0; + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 0){ + int count = rand() & 1; + if (getData(xt,yt) >= (rand()%10) + 3) { + setTile(TILE_DIRT,xt,yt); + count += 2; + } + addItemsToWorld(newItem(ITEM_IRONORE,1),(xt<<4)+8,(yt<<4)+8,count); + } break; + case TILE_GOLDORE: + if(player.p.activeItem->id != TOOL_PICKAXE) damage = 0; + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 0){ + int count = rand() & 1; + if (getData(xt,yt) >= (rand()%10) + 3) { + setTile(TILE_DIRT,xt,yt); + count += 2; + } + addItemsToWorld(newItem(ITEM_GOLDORE,1),(xt<<4)+8,(yt<<4)+8,count); + } break; + case TILE_GEMORE: + if(player.p.activeItem->id != TOOL_PICKAXE) damage = 0; + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 0){ + int count = rand() & 1; + if (getData(xt,yt) >= (rand()%10) + 3) { + setTile(TILE_DIRT,xt,yt); + count += 2; + } + addItemsToWorld(newItem(ITEM_GEM,1),(xt<<4)+8,(yt<<4)+8,count); + } break; + case TILE_CLOUDCACTUS: + if(player.p.activeItem->id != TOOL_PICKAXE) damage = 0; + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 0){ + int count = rand() % 3; + if (getData(xt,yt) >= (rand()%10) + 3) { + setTile(TILE_CLOUD,xt,yt); + count += 3; + } + addItemsToWorld(newItem(ITEM_CLOUD,1),(xt<<4)+8,(yt<<4)+8,count); + } break; + case TILE_FARM: + setTile(TILE_DIRT,xt,yt); + break; + case TILE_SAPLING_TREE: + setTile(TILE_GRASS,xt,yt); + break; + case TILE_SAPLING_CACTUS: + setTile(TILE_SAND,xt,yt); + break; + case TILE_WHEAT: + if(getData(xt,yt) > -1){ + int age = getData(xt,yt); + int count = (rand() % 2); + if(age >= 80) count = (rand()%2) + 1; + addItemsToWorld(newItem(ITEM_SEEDS,1),(xt<<4)+8,(yt<<4)+8,count); + count = 0; + if(age == 100)count = (rand()%3) + 2; + else if(age >= 80)count = (rand()%2) + 1; + addItemsToWorld(newItem(ITEM_WHEAT,1),(xt<<4)+8,(yt<<4)+8,count); + setTile(TILE_DIRT,xt,yt); + } break; + case TILE_FLOWER: + setTile(TILE_GRASS,xt,yt); + addEntityToList(newItemEntity(newItem(ITEM_FLOWER,1), (xt<<4)+8,(yt<<4)+8, currentLevel), &eManager); + break; case TILE_WOOD_WALL: - damageAndBreakTile(level, xt, yt, damage, 20, TILE_DIRT, 1, newItem(ITEM_WALL_WOOD,1), 1); - break; - case TILE_STONE_WALL: - damageAndBreakTile(level, xt, yt, damage, 30, TILE_DIRT, 1, newItem(ITEM_WALL_STONE,1), 1); - break; - case TILE_IRON_WALL: - damageAndBreakTile(level, xt, yt, damage, 40, TILE_DIRT, 1, newItem(ITEM_WALL_IRON,1), 1); - break; - case TILE_GOLD_WALL: - damageAndBreakTile(level, xt, yt, damage, 50, TILE_DIRT, 1, newItem(ITEM_WALL_GOLD,1), 1); - break; - case TILE_GEM_WALL: - damageAndBreakTile(level, xt, yt, damage, 60, TILE_DIRT, 1, newItem(ITEM_WALL_GEM,1), 1); - break; - case TILE_BOOKSHELVES: - addSmashParticles(level, xt<<4, yt<<4, damage); - if(level!=5) setTile(TILE_DIRT, level, xt, yt); - else setTile(TILE_DUNGEON_FLOOR, level, xt, yt); - addItemsToWorld(newItem(ITEM_BOOKSHELVES,1), level, (xt<<4)+8, (yt<<4)+8, 1); - break; - } + sprintf(hurtText, "%d", damage); + addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager); + addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager); + setData(getData(xt,yt)+damage,xt,yt); + if(getData(xt,yt) > 20){ + setTile(TILE_DIRT,xt,yt); + addItemsToWorld(newItem(ITEM_WOOD,1),(xt<<4)+8,(yt<<4)+8,1); + } + break; + } + +} +bool playerUseEnergy(int amount){ + if(amount > player.p.stamina) return false; + player.p.stamina -= amount; + return true; +} + +void playerAttack(){ + bool done = false; + player.p.attackTimer = 5; + int yo = -2; + int range = 12; + + switch(player.p.dir){ + case 0: if(interact(player.x - 8, player.y + 4 + yo, player.x + 8, player.y + range + yo)) return; break; + case 1: if(interact(player.x - 8, player.y - range + yo, player.x + 8, player.y - 4 + yo)) return; break; + case 2: if(interact(player.x - range, player.y - 8 + yo, player.x - 4, player.y + 8 + yo)) return; break; + case 3: if(interact(player.x + 4, player.y - 8 + yo, player.x + range, player.y + 8 + yo)) return; break; + } + + int xt = player.x >> 4; + int yt = (player.y + yo) >> 4; + int r = 12; + if (player.p.dir == 0) yt = (player.y + r + yo) >> 4; + if (player.p.dir == 1) yt = (player.y - r + yo) >> 4; + if (player.p.dir == 2) xt = (player.x - r) >> 4; + if (player.p.dir == 3) xt = (player.x + r) >> 4; + + if (xt >= 0 && yt >= 0 && xt < 128 && yt < 128) { + s8 itract = itemTileInteract(getTile(xt,yt),player.p.activeItem,xt,yt,player.x,player.y,player.p.dir); + if(itract > 0){ + if(itract==2)player.p.isCarrying = false; + done = true; + } + + if (isItemEmpty(player.p.activeItem)) { + removeItemFromInventory(player.p.activeItem->slotNum, player.p.inv); + player.p.activeItem = &noItem; + } + } + + if(done) return; + + if (player.p.activeItem == &noItem || player.p.activeItem->id == TOOL_SWORD || player.p.activeItem->id == TOOL_AXE) { + xt = player.x >> 4; + yt = (player.y + yo) >> 4; + r = 12; + if (player.p.dir == 0) yt = (player.y + r + yo) >> 4; + if (player.p.dir == 1) yt = (player.y - r + yo) >> 4; + if (player.p.dir == 2) xt = (player.x - r) >> 4; + if (player.p.dir == 3) xt = (player.x + r) >> 4; + + if (xt >= 0 && yt >= 0 && xt < 128 && 128) { + playerHurtTile(getTile(xt,yt), xt, yt, (rand()%3) + 1, player.p.dir); + } + } } -void switchLevel(PlayerData *pd, s8 change){ - pd->entity.level+=change; - if(pd->entity.level > 4) pd->entity.level = 0; else if(pd->entity.level < 0) pd->entity.level = 4; - - if(pd==getLocalPlayer()) { - if(pd->entity.level == 1) sf2d_set_clear_color(0xFF6C6D82); - else if(pd->entity.level > 1) sf2d_set_clear_color(0xFF666666); - else sf2d_set_clear_color(0xFF007F00); - } - - //for level 0 background - updateLevel1Map(); +void switchLevel(s8 change){ + currentLevel+=change; + if(currentLevel > 4) currentLevel = 0; else if(currentLevel < 0) currentLevel = 4; + if(currentLevel == 1) sf2d_set_clear_color(0xFF6C6D82); //sf2d_set_clear_color(RGBA8(0x82, 0x6D, 0x6C, 0xFF)); + else if(currentLevel > 1) sf2d_set_clear_color(0xFF666666); //sf2d_set_clear_color(RGBA8(0x66, 0x66, 0x66, 0xFF)); + else sf2d_set_clear_color(0xFF007F00); //sf2d_set_clear_color(RGBA8(0x00, 0x7F, 0x00, 0xFF)); + + updateMusic(currentLevel); } -void playerEntityInteract(PlayerData *pd, Entity* e){ - switch(e->type){ - case ENTITY_ITEM: - if(e->entityItem.age > 30){ - addItemToInventory(e->entityItem.item, &(pd->inventory)); - removeEntityFromList(e, e->level, &eManager); - playSoundPositioned(snd_pickup, pd->entity.level, pd->entity.x, pd->entity.y); - pd->score++; - } - break; - case ENTITY_FURNITURE: - switch(pd->entity.p.dir){ - case 0: if(pd->entity.y < e->y) move(e, 0, 2); break; - case 1: if(pd->entity.y > e->y) move(e, 0, -2); break; - case 2: if(pd->entity.x > e->x) move(e, -2, 0); break; - case 3: if(pd->entity.x < e->x) move(e, 2, 0); break; - } - break; - } +bool playerIntersectsEntity(Entity* e){ + return (player.x < e->x + e->xr && player.x + 4 > e->x && player.y < e->y + e->yr && player.y + 4 > e->y); } -void entityTileInteract(Entity*e, int tile, s8 level, int x, int y){ - switch(tile){ - case TILE_STAIRS_DOWN: - if(e->type == ENTITY_PLAYER){ - switchLevel(e->p.data, 1); - e->x = (x << 4) + 8; - e->y = (y << 4) + 8; - } - return; - case TILE_STAIRS_UP: - if(e->type == ENTITY_PLAYER){ - switchLevel(e->p.data, -1); - e->x = (x << 4) + 8; - e->y = (y << 4) + 8; - } - return; - case TILE_CACTUS: if(e->type == ENTITY_PLAYER) hurtEntity(e ,1, -1, 0xFFAF00FF, NULL); return; - case TILE_LAVA: if(e->type == ENTITY_PLAYER) hurtEntity(e, 1, -1, 0xFFAF00FF, NULL); return; - case TILE_WHEAT: - if(e->type == ENTITY_PLAYER || e->type == ENTITY_ZOMBIE){ - if(getData(level, x, y) > -1 && rand()%20 == 0){ - int age = getData(level, x, y); - int count = (rand() % 2); - if(age >= 80) count = (rand()%2) + 1; - addItemsToWorld(newItem(ITEM_SEEDS,1), level, (x<<4)+8, (y<<4)+8, count); - count = 0; - if(age == 100) count = (rand()%3) + 2; - else if(age >= 80) count = (rand()%2) + 1; - addItemsToWorld(newItem(ITEM_WHEAT,1), level, (x<<4)+8, (y<<4)+8, count); - setTile(TILE_DIRT, level, x, y); - } - } - return; - case TILE_FARM: - if(e->type == ENTITY_PLAYER || e->type == ENTITY_ZOMBIE){ - if(rand()%20 == 0) setTile(TILE_DIRT, level, x, y); - } - return; - case TILE_SAND: - if(e->type != ENTITY_ARROW && e->type != ENTITY_ITEM) { - setData(10, level, x, y); - } - return; - case TILE_DUNGEON_ENTRANCE: - if(e->type == ENTITY_PLAYER) { - e->p.data->ingameMenu = MENU_DUNGEON; - } - return; - } +void playerEntityInteract(Entity* e){ + switch(e->type){ + case ENTITY_ITEM: + if(e->entityItem.age > 30){//30 + addItemToInventory(e->entityItem.item, player.p.inv); + removeEntityFromList(e,currentLevel,&eManager); + playSound(snd_pickup); + player.p.score++; + } + break; + case ENTITY_FURNITURE: + switch(player.p.dir){ + case 0: if(player.y < e->y) move(e,0,2); break; + case 1: if(player.y > e->y) move(e,0,-2); break; + case 2: if(player.x > e->x) move(e,-2,0); break; + case 3: if(player.x < e->x) move(e,2,0); break; + } + break; + + } + +} + +void entityTileInteract(Entity*e, int tile, int x, int y){ + switch(tile){ + case TILE_STAIRS_DOWN: + if(e->type == ENTITY_PLAYER){ + switchLevel(1); + player.x = (x << 4) + 8; + player.y = (y << 4) + 8; + } + return; + case TILE_STAIRS_UP: + if(e->type == ENTITY_PLAYER){ + switchLevel(-1); + player.x = (x << 4) + 8; + player.y = (y << 4) + 8; + } + return; + case TILE_CACTUS: if(e->type == ENTITY_PLAYER)hurtEntity(e,1,-1,0xFFAF00FF); return; + case TILE_LAVA: if(e->type == ENTITY_PLAYER)hurtEntity(e,1,-1,0xFFAF00FF); return; + case TILE_WHEAT: + if(e->type == ENTITY_PLAYER || e->type == ENTITY_ZOMBIE){ + if(getData(x,y) > -1 && rand()%20 == 0){ + int age = getData(x,y); + int count = (rand() % 2); + if(age >= 80) count = (rand()%2) + 1; + addItemsToWorld(newItem(ITEM_SEEDS,1),(x<<4)+8,(y<<4)+8,count); + count = 0; + if(age == 100)count = (rand()%3) + 2; + else if(age >= 80)count = (rand()%2) + 1; + addItemsToWorld(newItem(ITEM_WHEAT,1),(x<<4)+8,(y<<4)+8,count); + setTile(TILE_DIRT,x,y); + } + } + return; + case TILE_FARM: + if(e->type == ENTITY_PLAYER || e->type == ENTITY_ZOMBIE){ + if(rand()%20 == 0)setTile(TILE_DIRT,x,y); + } + return; + } } bool intersectsEntity(int x, int y, int r, Entity* e){ - return (x < e->x + e->xr && x + r > e->x && y < e->y + e->yr && y + r > e->y); + return (x < e->x + e->xr && x + r > e->x && y < e->y + e->yr && y + r > e->y); } -void openCraftingMenu(PlayerData *pd, RecipeManager *rm, char *title) { - pd->currentCraftTitle = title; - pd->ingameMenu = MENU_CRAFTING; - - cloneRecipeManager(rm, &(pd->currentRecipes)); - checkCanCraftRecipes(&(pd->currentRecipes), &(pd->inventory)); - sortRecipes(&(pd->currentRecipes)); +bool isPlayerInsideEntity(int x, int y){ + int i; + for(i = 0; i < eManager.lastSlot[currentLevel];++i){ + Entity e = eManager.entities[currentLevel][i]; + if(!e.canPass && intersectsEntity(x-16,y-16,16,&e)){ + playerEntityInteract(&eManager.entities[currentLevel][i]); + return true; + } + } + return false; } -bool useEntity(PlayerData *pd, Entity* e) { - if(e->type == ENTITY_FURNITURE){ - switch(e->entityFurniture.itemID){ - case ITEM_WORKBENCH: - openCraftingMenu(pd, &workbenchRecipes, "Crafting"); - return true; - case ITEM_FURNACE: - openCraftingMenu(pd, &furnaceRecipes, "Smelting"); - return true; - case ITEM_OVEN: - openCraftingMenu(pd, &ovenRecipes, "Cooking"); - return true; - case ITEM_ANVIL: - openCraftingMenu(pd, &anvilRecipes, "Smithing"); - return true; - case ITEM_LOOM: - openCraftingMenu(pd, &loomRecipes, "Crafting"); - return true; - case ITEM_ENCHANTER: - openCraftingMenu(pd, &enchanterRecipes, "Enchanting"); - return true; - case ITEM_POTION_MAKER: - openCraftingMenu(pd, &potionMakerRecipes, "Brewing"); - return true; - case ITEM_CHEST: - pd->curChestEntity = e; - pd->ingameMenuInvSel = 0; - pd->ingameMenuInvSelOther = 0; - pd->curChestEntityR = 0; - pd->ingameMenu = MENU_CONTAINER; - return true; - } - } else if(e->type == ENTITY_NPC) { - openNPCMenu(pd, e->npc.type); - return true; - } - return false; +bool useEntity(Entity* e) { + if(e->type == ENTITY_FURNITURE){ + switch(e->entityFurniture.itemID){ + case ITEM_WORKBENCH: + currentRecipes = &workbenchRecipes; + currentMenu = MENU_CRAFTING; + checkCanCraftRecipes(currentRecipes, player.p.inv); + sortRecipes(currentRecipes); + return true; + case ITEM_FURNACE: + currentRecipes = &furnaceRecipes; + currentMenu = MENU_CRAFTING; + checkCanCraftRecipes(currentRecipes, player.p.inv); + sortRecipes(currentRecipes); + return true; + case ITEM_OVEN: + currentRecipes = &ovenRecipes; + currentMenu = MENU_CRAFTING; + checkCanCraftRecipes(currentRecipes, player.p.inv); + sortRecipes(currentRecipes); + return true; + case ITEM_ANVIL: + currentRecipes = &anvilRecipes; + currentMenu = MENU_CRAFTING; + checkCanCraftRecipes(currentRecipes, player.p.inv); + sortRecipes(currentRecipes); + return true; + case ITEM_CHEST: + curChestEntity = e; + curInvSel = 0; + curChestEntity->entityFurniture.r = 0; + curChestEntity->entityFurniture.oSel = 0; + currentMenu = MENU_CONTAINER; + return true; + } + } + return false; } -bool isWater(s8 level, int xt, int yt){ - return getTile(level, xt, yt)==TILE_WATER; -} - -bool dungeonActive() { - //check if dungeon already exists (ie someone is in there) +bool use(int x0, int y0, int x1, int y1) { + Entity * entities[eManager.lastSlot[currentLevel]]; int i; - for(i = 0; i < playerCount; i++) { - if(players[i].entity.level==5) { - return true; - } - } + int ae = getEntities(entities, x0, y0, x1, y1); + for(i = 0; i < ae; ++i){ + if(useEntity(entities[i])) return true; + } + return false; +} + +bool playerUse() { + int yo = -2; + if (player.p.dir == 0 && use(player.x - 8, player.y + 4 + yo, player.x + 8, player.y + 12 + yo)) return true; + if (player.p.dir == 1 && use(player.x - 8, player.y - 12 + yo, player.x + 8, player.y - 4 + yo)) return true; + if (player.p.dir == 3 && use(player.x + 4, player.y - 8 + yo, player.x + 12, player.y + 8 + yo)) return true; + if (player.p.dir == 2 && use(player.x - 12, player.y - 8 + yo, player.x - 4, player.y + 8 + yo)) return true; return false; } -void enterDungeon(PlayerData *pd) { - //create new one if needed - if(!dungeonActive()) { - //reset Entities - (&eManager)->lastSlot[5] = 0; - (&eManager)->entities[5][0] = nullEntity; - - //create map - createAndValidateDungeonMap(128, 128, 5, worldData.map[5], worldData.data[5]); - - //reset minimap clear state - int xd,yd; - for(xd = 0; xd < 128; ++xd) { - for(yd = 0; yd < 128; ++yd) { - setMinimapVisible(pd, 5, xd, yd, false); - } - } - initMinimapLevel(pd, 5); - - //spawn new entities - trySpawn(500, 5); +void tickPlayer(){ + if (player.hurtTime > 0) player.hurtTime--; + bool swimming = isSwimming(); + if (player.p.stamina <= 0 && player.p.staminaRechargeDelay == 0 && player.p.staminaRecharge == 0) { + player.p.staminaRechargeDelay = 40; } - - pd->entity.level = 5; - pd->entity.x = ((128/2) << 4) + 8; - pd->entity.y = ((128/2) << 4) + 8; -} - -void leaveDungeon(PlayerData *pd) { - pd->entity.level = 4; - pd->entity.x = ((128/2) << 4) + 8; - pd->entity.y = ((128/2) << 4) + 8; - - //clear dungeon if empty - if(!dungeonActive()) { - //reset Entities - (&eManager)->lastSlot[5] = 0; - (&eManager)->entities[5][0] = nullEntity; - } -} - -void setMinimapVisible(PlayerData *pd, int level, int x, int y, bool visible) { - if(visible) { - pd->minimapData[x + y * 128] = pd->minimapData[x + y * 128] | (1 << level); - } else { - pd->minimapData[x + y * 128] = pd->minimapData[x + y * 128] & (0xFF - (1 << level)); + if (player.p.staminaRechargeDelay > 0) { + --player.p.staminaRechargeDelay; } - if(pd==getLocalPlayer()) sf2d_set_pixel(minimap[level], x, y, getMinimapColor(pd, level, x, y)); -} - -bool getMinimapVisible(PlayerData *pd, int level, int x, int y) { - return (pd->minimapData[x + y * 128] & (1 << level)) > 0; -} - -u32 getMinimapColor(PlayerData *pd, int level, int x, int y) { - if(getMinimapVisible(pd, level, x, y) || (pd->entity.level==0 && level==1)) return getTileColor(worldData.map[level][x + y * 128]); - else return getTileColor(worldData.map[level][x + y * 128]) & 0xFFFFFF00; -} - -void initMinimapLevel(PlayerData *pd, int level) { - int x; - int y; - - if(pd!=getLocalPlayer()) return; - - for (x = 0; x < 128; ++x) { - for (y = 0; y < 128; ++y) { - /* Minimaps */ - sf2d_set_pixel(minimap[level], x, y, getMinimapColor(pd, level, x, y)); + if (player.p.staminaRechargeDelay == 0) { + ++player.p.staminaRecharge; + if (swimming) player.p.staminaRecharge = 0; + + while (player.p.staminaRecharge > 10) { + player.p.staminaRecharge -= 10; + if (player.p.stamina < 10) ++player.p.stamina; } } + + player.p.ax = 0; + player.p.ay = 0; + + if (k_left.down){ + player.p.ax -= 1; + player.p.dir = 2; + ++player.p.walkDist; + } + if (k_right.down){ + player.p.ax += 1; + player.p.dir = 3; + ++player.p.walkDist; + } + if (k_up.down){ + player.p.ay -= 1; + player.p.dir = 1; + ++player.p.walkDist; + } + if (k_down.down){ + player.p.ay += 1; + player.p.dir = 0; + ++player.p.walkDist; + } + if (player.p.staminaRechargeDelay % 2 == 0) moveMob(&player, player.p.ax, player.p.ay); + + + if (swimming && player.p.swimTimer % 60 == 0) { + if (player.p.stamina > 0) { + --player.p.stamina; + } else { + hurtEntity(&player,1,-1,0xFFAF00FF); + } + } + + if (k_pause.clicked){ + currentSelection = 0; + currentMenu = MENU_PAUSED; + } + + if(k_attack.clicked){ + if (player.p.stamina != 0) { + player.p.stamina--; + player.p.staminaRecharge = 0; + playerAttack(); + //addEntityToList(newSlimeEntity(1,200,600,1), &eManager); + } + } + + if (k_menu.clicked){ + curInvSel = 0; + if(!playerUse()) currentMenu = MENU_INVENTORY; + } + + if(isSwimming()) ++player.p.swimTimer; + if(player.p.attackTimer > 0) --player.p.attackTimer; } -void updateLevel1Map() { - initMinimapLevel(getLocalPlayer(), 1); +bool isSwimming(){ + return getTile(player.x>>4,player.y>>4)==TILE_WATER; } +void playerSetActiveItem(Item * item) { + player.p.activeItem = item; + if(player.p.activeItem->id > 27 && player.p.activeItem->id < 34) player.p.isCarrying = true; + else player.p.isCarrying = false; +} void reloadColors() { - dirtColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 0)); - dirtColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 1)); - dirtColor[2] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 2)); - dirtColor[3] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 3)); - dirtColor[4] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 4)); + dirtColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 0)); + dirtColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 1)); + dirtColor[2] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 2)); + dirtColor[3] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 3)); + dirtColor[4] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 4)); + + grassColor = SWAP_UINT32(sf2d_get_pixel(icons, 17, 0)); - grassColor = SWAP_UINT32(sf2d_get_pixel(icons, 17, 0)); - myceliumColor = SWAP_UINT32(sf2d_get_pixel(icons, 17, 1)); - mushroomColor = SWAP_UINT32(sf2d_get_pixel(icons, 17, 2)); - - sandColor = SWAP_UINT32(sf2d_get_pixel(icons, 18, 0)); - - waterColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 19, 0)); - waterColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 19, 1)); - - lavaColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 20, 0)); - lavaColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 20, 1)); - - rockColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 0)); - rockColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 1)); - rockColor[2] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 2)); - rockColor[3] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 3)); - - woodColor = SWAP_UINT32(sf2d_get_pixel(icons, 22, 0)); - - ironColor = SWAP_UINT32(sf2d_get_pixel(icons, 23, 0)); - goldColor = SWAP_UINT32(sf2d_get_pixel(icons, 23, 1)); - gemColor = SWAP_UINT32(sf2d_get_pixel(icons, 23, 2)); - - dungeonColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 24, 0)); - dungeonColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 24, 1)); - - snowColor = SWAP_UINT32(sf2d_get_pixel(icons, 25, 0)); - iceColor = SWAP_UINT32(sf2d_get_pixel(icons, 25, 1)); -} + sandColor = SWAP_UINT32(sf2d_get_pixel(icons, 18, 0)); + + waterColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 19, 0)); + waterColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 19, 1)); + + lavaColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 20, 0)); + lavaColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 20, 1)); + + rockColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 0)); + rockColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 1)); + rockColor[2] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 2)); + rockColor[3] = SWAP_UINT32(sf2d_get_pixel(icons, 21, 3)); + + woodColor = SWAP_UINT32(sf2d_get_pixel(icons, 22, 0)); +} \ No newline at end of file diff --git a/source/Globals.h b/source/Globals.h old mode 100755 new mode 100644 index e8a6170..ba4a0f8 --- a/source/Globals.h +++ b/source/Globals.h @@ -1,14 +1,9 @@ #pragma once - #include <3ds.h> -#include "Entity.h" -#include "Player.h" +#include "SaveLoad.h" #include "Input.h" -#include "MapGen.h" -#include "Quests.h" -#include "icons_png.h" -#include "player_png.h" +#include "icons2_png.h" #include "Font_png.h" #include "bottombg_png.h" @@ -20,29 +15,15 @@ #define MENU_TUTORIAL 2 #define MENU_ABOUT 3 #define MENU_SETTINGS 4 -#define MENU_LOADGAME 5 -#define MENU_SETTINGS_REBIND 6 -#define MENU_SETTINGS_TP 7 -#define MENU_MULTIPLAYER_HOST 8 -#define MENU_MULTIPLAYER_JOIN 9 -#define MENU_MULTIPLAYER_WAIT 10 -#define MENU_LOADING 11 - -#define MENU_PAUSED 100 -#define MENU_INVENTORY 101 -#define MENU_CRAFTING 102 -#define MENU_CONTAINER 103 -#define MENU_WIN 104 -#define MENU_LOSE 105 -#define MENU_DUNGEON 106 -#define MENU_NPC 107 -#define MENU_CHARACTER_CUSTOMIZE 108 - -#define NPC_GIRL 0 -#define NPC_PRIEST 1 -#define NPC_FARMER 2 -#define NPC_LIBRARIAN 3 -#define NPC_DWARF 4 +#define MENU_INVENTORY 5 +#define MENU_CRAFTING 6 +#define MENU_CONTAINER 7 +#define MENU_WIN 8 +#define MENU_LOSE 9 +#define MENU_PAUSED 10 +#define MENU_LOADGAME 11 +#define MENU_SETTINGS_REBIND 12 +#define MENU_SETTINGS_TP 13 #define TILE_NULL 255 #define TILE_GRASS 0 @@ -67,51 +48,32 @@ #define TILE_HARDROCK 19 #define TILE_CLOUDCACTUS 20 #define TILE_HOLE 21 - #define TILE_WOOD_WALL 22 -#define TILE_STONE_WALL 23 -#define TILE_IRON_WALL 24 -#define TILE_GOLD_WALL 25 -#define TILE_GEM_WALL 26 -#define TILE_DUNGEON_WALL 27 -#define TILE_DUNGEON_FLOOR 28 -#define TILE_DUNGEON_ENTRANCE 29 -#define TILE_MAGIC_BARRIER 30 -#define TILE_BOOKSHELVES 31 -#define TILE_WOOD_FLOOR 32 -#define TILE_MYCELIUM 33 -#define TILE_MUSHROOM_BROWN 34 -#define TILE_MUSHROOM_RED 35 -#define TILE_ICE 36 #define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24)) -//WARNING: Having this set to different values in different clients will break multiplayer! -#define TESTGODMODE false - -bool paused; - -u32 localUID; - +bool screenShot; int loadedtp; u8 MODEL_3DS; extern char versionText[34]; +Entity player; + bool shouldRenderDebug; bool shouldSpeedup; bool shouldRenderMap; -bool UnderStrengthEffect; -bool UnderSpeedEffect; -bool regening; -bool UnderSwimBreathEffect; +u8 zoomLevel; +char mapText[32]; +s16 mScrollX, mScrollY; sf2d_texture *icons; -sf2d_texture *playerSprites; sf2d_texture *font; sf2d_texture *bottombg; -sf2d_texture *minimap[6]; +sf2d_texture * minimap[5]; +u8 map[5][128*128]; +u8 data[5][128*128]; u32 dirtColor[5]; u32 grassColor; @@ -120,85 +82,53 @@ u32 waterColor[2]; u32 lavaColor[2]; u32 rockColor[4]; u32 woodColor; -u32 ironColor; -u32 goldColor; -u32 gemColor; -u32 dungeonColor[2]; -u32 myceliumColor; -u32 mushroomColor; -u32 snowColor; -u32 iceColor; char currentFileName[256]; extern u8 currentMenu; extern char fpsstr[]; u8 initGame; -u8 initMPGame; -u8 initBGMap; Item noItem; int airWizardHealthDisplay; s16 awX, awY; +u32 tickCount; +RecipeManager* currentRecipes; +Entity* curChestEntity; +s16 curInvSel; 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]; -} WorldData; - -WorldData worldData; - -//TODO: cleanup the order -int getEntities(Entity** result, s8 level, int x0, int y0, int x1, int y1); - -bool moveMob(Entity* e, int xa, int ya); -void hurtEntity(Entity *e, int damage, int dir, u32 hurtColor, Entity *damager); - -void tickTile(s8 level, int x, int y); +void tickTile(int x, int y); bool tileIsSolid(int tile, Entity * e); -s8 itemTileInteract(int tile, PlayerData *pd, Item *item, s8 level, int x, int y, int px, int py, int dir); +s8 itemTileInteract(int tile, Item* item, int x, int y, int px, int py, int dir); void tickEntity(Entity* e); +void tickTouchMap(); +void tickTouchQuickSelect(); + void trySpawn(int count, int level); -int getTile(s8 level, int x, int y); -void setTile(int id, s8 level, int x, int y); -int getData(s8 level, int x, int y); -void setData(int id, s8 level, int x, int y); +int getTile(int x, int y); u32 getTileColor(int tile); +void setTile(int id, int x, int y); +int getData(int x, int y); +void setData(int id, int x, int y); bool intersectsEntity(int x, int y, int r, Entity* e); bool EntityBlocksEntity(Entity* e1, Entity* e2); void EntityVsEntity(Entity* e1, Entity* e2); -bool ItemVsEntity(PlayerData *pd, Item *item, Entity *e, int dir); -void entityTileInteract(Entity* e, int tile, s8 level, int x, int y); +void entityTileInteract(Entity* e, int tile,int x, int y); -void openCraftingMenu(PlayerData *pd, RecipeManager *rm, char *title); -bool useEntity(PlayerData *pd, Entity* e); +void initPlayer(); +void tickPlayer(); +void playerAttack(); +bool isSwimming(); +bool playerUseEnergy(int amount); +void playerHurtTile(int tile, int xt, int yt, int damage, int dir); +bool playerIntersectsEntity(Entity* e); +void playerEntityInteract(Entity* e); +void playerSetActiveItem(Item * item); -bool isWater(s8 level, int xt, int yt); - -void playerHurtTile(PlayerData *pd, int tile, s8 level, int xt, int yt, int damage, int dir); -void playerEntityInteract(PlayerData *pd, Entity* e); - -bool dungeonActive(); -void enterDungeon(PlayerData *pd); -void leaveDungeon(PlayerData *pd); - -void setMinimapVisible(PlayerData *pd, int level, int x, int y, bool visible); -bool getMinimapVisible(PlayerData *pd, int level, int x, int y); -u32 getMinimapColor(PlayerData *pd, int level, int x, int y); -void initMinimapLevel(PlayerData *pd, int level); -void updateLevel1Map(); - -void reloadColors(); +void reloadColors(); \ No newline at end of file diff --git a/source/Ingame.c b/source/Ingame.c deleted file mode 100644 index 74080b0..0000000 --- a/source/Ingame.c +++ /dev/null @@ -1,379 +0,0 @@ -#include "Ingame.h" - -#include "Globals.h" -#include "Player.h" -#include "Entity.h" -#include "IngameMenu.h" -#include "Render.h" -#include "MapGen.h" -#include "Synchronizer.h" -#include "SaveLoad.h" -#include "Network.h" - -#define STALL_TIME 120 - -int stallCounter; -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) { - - //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() { - createAndValidateSkyMap(128, 128, 0, worldData.map[0], worldData.data[0]); - createAndValidateTopMap(128, 128, 1, worldData.map[1], worldData.data[1]); - 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(); -} - -void initMiniMap(PlayerData *pd) { - int i; - for (i = 0; i < 5; ++i) { - initMinimapLevel(pd, i); - } -} - -void startGame(bool load, char *filename) { - // Reset entity manager. - memset(&eManager, 0, sizeof(eManager)); - - // Reset players - for(int i=0; i 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; ientity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y); - - //win/death menus - for(i=0; i=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; ix, 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; - } - } - } -} - -//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); - - 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); - - renderBackground(getLocalPlayer()->entity.level, xscr, yscr); - renderEntities(getLocalPlayer()->entity.level, getLocalPlayer()->entity.x, getLocalPlayer()->entity.y, &eManager); - for(int i=0; ientity.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() { - networkDisconnect(); - synchronizerReset(); - - sf2d_set_clear_color(0xFF); - currentSelection = 0; - currentMenu = MENU_TITLE; - - playMusic(&music_menu); -} diff --git a/source/Ingame.h b/source/Ingame.h deleted file mode 100644 index f930d2b..0000000 --- a/source/Ingame.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include <3ds.h> - -void startGame(bool load, char *filename); -void tickGame(); -void renderGame(); - -void exitGame(); diff --git a/source/IngameMenu.c b/source/IngameMenu.c deleted file mode 100644 index 6247f54..0000000 --- a/source/IngameMenu.c +++ /dev/null @@ -1,528 +0,0 @@ -#include "IngameMenu.h" - -#include "Globals.h" -#include "Menu.h" -#include "Ingame.h" -#include "Player.h" -#include "SaveLoad.h" -#include "Synchronizer.h" - -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_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_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; - pd->ingameMenuInvSel = pd->ingameMenuInvSelOther; - pd->ingameMenuInvSelOther = tmp; - } - if (pd->inputs.k_right.clicked) { - pd->curChestEntityR = 1; - int tmp = pd->ingameMenuInvSel; - 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; - if (pd->ingameMenuInvSel < 0) pd->ingameMenuInvSel = 0; - if (pd->ingameMenuInvSel >= len) pd->ingameMenuInvSel = len - 1; - if (pd->inputs.k_up.clicked) --pd->ingameMenuInvSel; - if (pd->inputs.k_down.clicked) ++pd->ingameMenuInvSel; - 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); - pushItem.chestPtr = pullItem->chestPtr; - pushItemToInventoryFront(pushItem, i2); - if(i2 == &(pd->inventory)){ - int newslot = pd->activeItem->slotNum + 1; - pd->activeItem = &(pd->inventory.items[newslot]); - } else if(pullItem == pd->activeItem){ - pd->activeItem = &noItem; - } - removeItemFromCurrentInv(pullItem); - if (pd->ingameMenuInvSel >= i1->lastSlot) pd->ingameMenuInvSel = i1->lastSlot - 1; - } - 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)); - if(item!=NULL) { - --item->countLevel; - if(item->countLevel==0) { - removeItemFromCurrentInv(item); - } - - enterDungeon(pd); - } else if(shouldRenderDebug) { - 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; - } -} - - -u8 opacity = 255; -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(amntcosts[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; - } - } -} - -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]); - } - } - } - } -} - -void ingameMenuTickTouch(PlayerData *pd) { - tickTouchMap(pd); - tickTouchQuickSelect(pd); -} diff --git a/source/IngameMenu.h b/source/IngameMenu.h deleted file mode 100644 index d3e168f..0000000 --- a/source/IngameMenu.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "Player.h" - -void ingameMenuTick(PlayerData *pd, int menu); -void ingameMenuRender(PlayerData *pd, int menu); - -void ingameMenuTickTouch(PlayerData *pd); diff --git a/source/Input.c b/source/Input.c old mode 100755 new mode 100644 index 80268b4..662cb69 --- a/source/Input.c +++ b/source/Input.c @@ -1,61 +1,23 @@ #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_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 tickKeys(u32 held, u32 down){ + hidTouchRead(&k_touch); // Update touch position + toggleKey(&k_up, held & k_up.input, down & k_up.input); + toggleKey(&k_down, held & k_down.input, down & k_down.input); + toggleKey(&k_left, held & k_left.input, down & k_left.input); + toggleKey(&k_right, held & k_right.input, down & k_right.input); + toggleKey(&k_pause, held & k_pause.input, down & k_pause.input); + toggleKey(&k_attack, held & k_attack.input, down & k_attack.input); + toggleKey(&k_menu, held & k_menu.input, down & k_menu.input); + toggleKey(&k_accept, held & k_accept.input, down & k_accept.input); + toggleKey(&k_decline, held & k_decline.input, down & k_decline.input); + toggleKey(&k_delete, held & k_delete.input, down & k_delete.input); + toggleKey(&k_menuNext, held & k_menuNext.input, down & k_menuNext.input); + toggleKey(&k_menuPrev, held & k_menuPrev.input, down & 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_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_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; -} diff --git a/source/Input.h b/source/Input.h old mode 100755 new mode 100644 index d88693c..761a315 --- a/source/Input.h +++ b/source/Input.h @@ -1,35 +1,24 @@ -#pragma once - #include <3ds.h> -//only down and clicked need to be send, input is for config stuff typedef struct { bool down, clicked; int input; } Key; -typedef struct { - 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; +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; -Inputs localInputs; - -void tickKeys(Inputs *inputs, u32 held, u32 down); -void resetKeys(Inputs *inputs); -void resetClicked(Inputs *inputs); +void tickKeys(u32 held, u32 down); bool clicked(Key key); diff --git a/source/Item.c b/source/Item.c old mode 100755 new mode 100644 index 284e527..ca47720 --- a/source/Item.c +++ b/source/Item.c @@ -2,349 +2,249 @@ 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; +bool isItemEmpty(Item* item){ + 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; - +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; + } -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; +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; } -void removeItemFromCurrentInv(Item* item) { - removeItemFromInventory(item->slotNum, (Inventory*)item->invPtr); +void removeItemFromCurrentInv(Item* item){ + 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. +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. } -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 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 > 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; +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 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 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; } - -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"; - 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_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_LOOM: return "Loom"; - case ITEM_ENCHANTER: return "Enchanter"; - case ITEM_WALL_WOOD: sprintf(currentName,"%d Wood Wall", countLevel); return currentName; - case ITEM_WALL_STONE: sprintf(currentName,"%d Stone Wall", countLevel); return currentName; - case ITEM_WALL_IRON: sprintf(currentName,"%d Iron Wall", countLevel); return currentName; - case ITEM_WALL_GOLD: sprintf(currentName,"%d Gold Wall", countLevel); return currentName; - case ITEM_WALL_GEM: sprintf(currentName,"%d Gem Wall", countLevel); return currentName; - case ITEM_WOOL: sprintf(currentName,"%d Wool", countLevel); return currentName; - case ITEM_STRING: sprintf(currentName,"%d String", countLevel); return currentName; - case ITEM_PORK_RAW: sprintf(currentName,"%d Raw Pork", countLevel); return currentName; - case ITEM_PORK_COOKED: sprintf(currentName,"%d Cooked Pork", countLevel); return currentName; - case ITEM_BEEF_RAW: sprintf(currentName,"%d Raw Beef", countLevel); return currentName; - case ITEM_BEEF_COOKED: sprintf(currentName,"%d Steak", countLevel); return currentName; - case ITEM_LEATHER: sprintf(currentName,"%d Leather", countLevel); return currentName; - case ITEM_ARROW_WOOD: sprintf(currentName,"%d Wood Arrow", countLevel); return currentName; - case ITEM_ARROW_STONE: sprintf(currentName,"%d Rock Arrow", countLevel); return currentName; - case ITEM_ARROW_IRON: sprintf(currentName,"%d Iron Arrow", countLevel); return currentName; - case ITEM_ARROW_GOLD: sprintf(currentName,"%d Gold Arrow", countLevel); return currentName; - case ITEM_ARROW_GEM: sprintf(currentName,"%d Gem Arrow", countLevel); return currentName; - case ITEM_BONE: sprintf(currentName,"%d Bone", countLevel); return currentName; - case ITEM_DUNGEON_KEY: sprintf(currentName,"%d Dungeon Key", countLevel); return currentName; - case ITEM_WIZARD_SUMMON: sprintf(currentName,"%d Wizard Summon", countLevel); return currentName; - case ITEM_DRAGON_EGG: sprintf(currentName,"%d Dragon Egg", countLevel); return currentName; - case ITEM_DRAGON_SCALE: sprintf(currentName,"%d Dragon Scale", countLevel); return currentName; - case ITEM_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; + +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"; + 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_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 TOOL_BUCKET: switch(countLevel){ - 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"; - 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 - } + case 1: return "Water Bucket"; + case 2: return "Lava Bucket"; + default: return "Empty Bucket"; + } + 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"; - 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_LOOM: return "Loom"; - case ITEM_ENCHANTER: return "Enchanter"; - case ITEM_WALL_WOOD: return "Wood Wall"; - case ITEM_WALL_STONE: return "Stone Wall"; - case ITEM_WALL_IRON: return "Iron Wall"; - case ITEM_WALL_GOLD: return "Gold Wall"; - case ITEM_WALL_GEM: return "Gem Wall"; - case ITEM_WOOL: return "Wool"; - case ITEM_STRING: return "String"; - case ITEM_PORK_RAW: return "Raw Pork"; - case ITEM_PORK_COOKED: return "Cooked Pork"; - case ITEM_BEEF_RAW: return "Raw Beef"; - case ITEM_BEEF_COOKED: return "Steak"; - case ITEM_LEATHER: return "Leather"; - case ITEM_ARROW_WOOD: return "Wood Arrow"; - case ITEM_ARROW_STONE: return "Rock Arrow"; - case ITEM_ARROW_IRON: return "Iron Arrow"; - case ITEM_ARROW_GOLD: return "Gold Arrow"; - case ITEM_ARROW_GEM: return "Gem Arrow"; - case ITEM_BONE: return "Bone"; - case ITEM_DUNGEON_KEY: return "Dungeon Key"; - case ITEM_WIZARD_SUMMON: return "Wizard Summon"; - 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_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"; + +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"; + 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_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 TOOL_BUCKET: switch(countLevel){ - 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"; - 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 - } - + case 1: return "Water Bucket"; + case 2: return "Lava Bucket"; + default: return "Empty Bucket"; + } + default: return ""; // null + } + } diff --git a/source/Item.h b/source/Item.h old mode 100755 new mode 100644 index 669c049..6e806e7 --- a/source/Item.h +++ b/source/Item.h @@ -42,69 +42,22 @@ #define ITEM_FURNACE 31 #define ITEM_WORKBENCH 32 #define ITEM_LANTERN 33 - -#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 -#define ITEM_WALL_IRON 53 -#define ITEM_WALL_GOLD 54 -#define ITEM_WALL_GEM 55 -#define ITEM_WOOL 56 -#define ITEM_STRING 57 -#define ITEM_PORK_RAW 58 -#define ITEM_PORK_COOKED 59 -#define ITEM_BEEF_RAW 60 -#define ITEM_BEEF_COOKED 61 -#define ITEM_LEATHER 62 -#define ITEM_ARROW_WOOD 63 -#define ITEM_ARROW_STONE 64 -#define ITEM_ARROW_IRON 65 -#define ITEM_ARROW_GOLD 66 -#define ITEM_ARROW_GEM 67 -#define ITEM_BONE 68 -#define ITEM_DUNGEON_KEY 69 -#define ITEM_WIZARD_SUMMON 70 -#define ITEM_DRAGON_EGG 71 -#define ITEM_DRAGON_SCALE 72 -#define ITEM_BOOKSHELVES 73 -#define ITEM_MAGIC_DUST 74 -#define ITEM_COIN 75 -#define ITEM_GOLD_APPLE 76 -#define ITEM_STRENGTH_POTION 77 -#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); diff --git a/source/MapGen.c b/source/MapGen.c old mode 100755 new mode 100644 index 49e5438..f354420 --- a/source/MapGen.c +++ b/source/MapGen.c @@ -3,11 +3,8 @@ int w = 0; int h = 0; -u8 randomTile[] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 2}; -int randomTileSize = 10; - float nextFloat(){ - return (float)rand()/RAND_MAX; + return (float)rand()/RAND_MAX; } double sample(double * values, int x, int y) { @@ -15,150 +12,122 @@ double sample(double * values, int x, int y) { } double * Noise(int width, int height, int featureSize) { - w = width; - h = height; - double * values = malloc(sizeof(double) * w * h); - int x, y; - for(x = 0; x < w; x+=featureSize){ - for(y = 0; y < w; y+=featureSize){ - values[(x & (w - 1)) + (y & (h - 1)) * w] = nextFloat() * 2 - 1; + w = width; + h = height; + double * values = malloc(sizeof(double) * w * h); + int x, y; + for(x = 0; x < w; x+=featureSize){ + for(y = 0; y < w; y+=featureSize){ + values[(x & (w - 1)) + (y & (h - 1)) * w] = nextFloat() * 2 - 1; + } } + + int stepSize = featureSize; + double scale = 1.0 / w; + double scaleMod = 1; + do { + int halfStep = stepSize / 2; + for(x = 0; x < w; x+=stepSize){ + for(y = 0; y < w; y+=stepSize){ + double a = sample(values,x, y); + double b = sample(values,x + stepSize, y); + double c = sample(values,x, y + stepSize); + double d = sample(values,x + stepSize, y + stepSize); + + double e = (a + b + c + d) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale; + values[((x + halfStep) & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = e; + } + } + for(x = 0; x < w; x+=stepSize){ + for(y = 0; y < w; y+=stepSize){ + double a = sample(values,x, y); + double b = sample(values,x + stepSize, y); + double c = sample(values,x, y + stepSize); + double d = sample(values,x + halfStep, y + halfStep); + double e = sample(values,x + halfStep, y - halfStep); + double f = sample(values,x - halfStep, y + halfStep); + double H = (a + b + d + e) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5; + double g = (a + c + d + f) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5; + values[((x + halfStep) & (w - 1)) + (y & (h - 1)) * w] = H; + values[(x & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = g; + } + } + + stepSize /= 2; + scale *= (scaleMod + 0.8); + scaleMod *= 0.3; + } while (stepSize > 1); + return values; } - - int stepSize = featureSize; - double scale = 1.0 / w; - double scaleMod = 1; - do { - int halfStep = stepSize / 2; - for(x = 0; x < w; x+=stepSize){ - for(y = 0; y < w; y+=stepSize){ - double a = sample(values,x, y); - double b = sample(values,x + stepSize, y); - double c = sample(values,x, y + stepSize); - double d = sample(values,x + stepSize, y + stepSize); - - double e = (a + b + c + d) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale; - values[((x + halfStep) & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = e; - } - } - for(x = 0; x < w; x+=stepSize){ - for(y = 0; y < w; y+=stepSize){ - double a = sample(values,x, y); - double b = sample(values,x + stepSize, y); - double c = sample(values,x, y + stepSize); - double d = sample(values,x + halfStep, y + halfStep); - double e = sample(values,x + halfStep, y - halfStep); - double f = sample(values,x - halfStep, y + halfStep); - double H = (a + b + d + e) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5; - double g = (a + c + d + f) / 4.0 + (nextFloat() * 2 - 1) * stepSize * scale * 0.5; - values[((x + halfStep) & (w - 1)) + (y & (h - 1)) * w] = H; - values[(x & (w - 1)) + ((y + halfStep) & (h - 1)) * w] = g; - } - } - - stepSize /= 2; - scale *= (scaleMod + 0.8); - scaleMod *= 0.3; - } while (stepSize > 1); - return values; + +void newSeed(){ + srand(time(NULL)); } - -//TODO: Will need to reset entity manager if generation is retried -void createAndValidateTopMap(int w, int h, int level, u8 * map, u8 * data) { + +void createAndValidateTopMap(int w, int h, u8 * map, u8 * data) { do { - //reset Entities - (&eManager)->lastSlot[level] = 0; - (&eManager)->entities[level][0] = nullEntity; - - createTopMap(w, h, level, map, data); + createTopMap(w, h, map, data); int count[256]={[0 ... 255] = 0}; - int i; - for (i = 0; i < w * h; ++i) count[map[i] & 0xff]++; + int i; + for (i = 0; i < w * h; ++i) count[map[i] & 0xff]++; if (count[TILE_ROCK & 0xff] < 100) continue; if (count[TILE_SAND & 0xff] < 100) continue; if (count[TILE_GRASS & 0xff] < 100) continue; if (count[TILE_TREE & 0xff] < 100) continue; if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue; - + return; } while (true); } -void createAndValidateUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) { +void createAndValidateUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) { do { - //reset Entities - (&eManager)->lastSlot[level] = 0; - (&eManager)->entities[level][0] = nullEntity; - - createUndergroundMap(w, h, depthLevel, level, map, data); - + createUndergroundMap(w, h, depthLevel, map, data); + int count[256]={[0 ... 255] = 0}; - int i = 0; - for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; + int i = 0; + for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; if (count[TILE_ROCK & 0xff] < 100) continue; if (count[TILE_DIRT & 0xff] < 100) continue; switch(depthLevel){ - case 1: if (count[TILE_IRONORE & 0xff] < 20) continue; break; - case 2: if (count[TILE_GOLDORE & 0xff] < 20 || count[TILE_MYCELIUM & 0xff] < 40) continue; break; - case 3: if (count[TILE_GEMORE & 0xff] < 20) continue; break; - } + case 1: if (count[TILE_IRONORE & 0xff] < 20) continue; break; + case 2: if (count[TILE_GOLDORE & 0xff] < 20) continue; break; + case 3: if (count[TILE_GEMORE & 0xff] < 20) continue; break; + } if (depthLevel < 3) if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue; - + return; } while (true); } - -void createAndValidateDungeonMap(int w, int h, int level, u8 * map, u8 * data) { +void createAndValidateSkyMap(int w, int h, u8 * map, u8 * data) { do { - //reset Entities - (&eManager)->lastSlot[level] = 0; - (&eManager)->entities[level][0] = nullEntity; - - createDungeonMap(w, h, level, map, data); - + createSkyMap(w, h, map, data); + int count[256]={[0 ... 255] = 0}; - int i = 0; - for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; - if (count[TILE_DUNGEON_WALL & 0xff] < 100) continue; - if (count[TILE_DUNGEON_FLOOR & 0xff] < 100) continue; - - return; - } while (true); -} - -void createAndValidateSkyMap(int w, int h, int level, u8 * map, u8 * data) { - do { - //reset Entities - (&eManager)->lastSlot[level] = 0; - (&eManager)->entities[level][0] = nullEntity; - - createSkyMap(w, h, level, map, data); - - int count[256]={[0 ... 255] = 0}; - int i = 0; - for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; + int i = 0; + for (i = 0; i < w * h; ++i)count[map[i] & 0xff]++; if (count[TILE_CLOUD & 0xff] < 1600) continue; if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue; - + return; } while (true); } - - - -void createTopMap(int w, int h, int level, u8 * map, u8 * data) { + + + +void createTopMap(int w, int h, u8 * map, u8 * data) { double* mnoise1 = Noise(w, h, 16); double* mnoise2 = Noise(w, h, 16); double* mnoise3 = Noise(w, h, 16); double* noise1 = Noise(w, h, 32); double* noise2 = Noise(w, h, 32); - + int x,y,i,j,k,xx,yy; - + for(x = 0; x < w; ++x){ - for(y = 0; y < w; ++y){ - int i = x + y * w; + for(y = 0; y < w; ++y){ + int i = x + y * w; double val = fabs(noise1[i] - noise2[i]) * 3 - 2; double mval = fabs(mnoise1[i] - mnoise2[i]); @@ -172,7 +141,7 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) { dist = dist * dist * dist * dist; dist = dist * dist * dist * dist; val = val + 1 - dist * 20; //-2 before to -21.0 after - + if (val < -0.5) { map[i] = TILE_WATER; } else if (val > 0.5 && mval < -1) { @@ -180,10 +149,10 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) { } else { map[i] = TILE_GRASS; } - } - } - - for (i = 0; i < w * h / 2800; ++i) { + } + } + + for (i = 0; i < w * h / 2800; ++i) { int xs = rand()%w; int ys = rand()%h; for (k = 0; k < 10; ++k) { @@ -192,18 +161,16 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) { for (j = 0; j < 100; ++j) { int xo = x + (rand()%5) - (rand()%5); int yo = y + (rand()%5) - (rand()%5); - for (yy = yo - 1;yy <= yo + 1; ++yy){ + for (yy = yo - 1;yy <= yo + 1; ++yy){ for(xx = xo - 1; xx <= xo + 1; ++xx){ if (xx >= 0 && yy >= 0 && xx < w && yy < h) if (map[xx + yy * w] == TILE_GRASS) map[xx + yy * w] = TILE_SAND; - } - } - } + } + } + } } } - - createVillage(w, h, level, map, data); - - for (i = 0; i < w * h / 400; ++i) { + + for (i = 0; i < w * h / 400; ++i) { x = rand()%w; y = rand()%h; for (j = 0; j < 200; ++j) { @@ -216,8 +183,8 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) { } } } - - for (i = 0; i < w * h / 800; ++i) { + + for (i = 0; i < w * h / 800; ++i) { x = rand()%w; y = rand()%h; for (j = 0; j < 30;++j) { @@ -229,10 +196,10 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) { data[xx + yy * w] = rand()%4; // determines mirroring. } } - + } } - + for (i = 0; i < w * h / 100; ++i) { xx = rand()%w; yy = rand()%h; @@ -242,14 +209,14 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) { } } } - - int sCount, attempts = 0; + + int sCount, attempts = 0; for (sCount = 0; sCount < 4;) { xx = rand()%w; yy = rand()%h; if (xx >= 0 && yy >= 0 && xx < w && yy < h) { - if (map[xx + yy * w] == TILE_ROCK) - { + if (map[xx + yy * w] == TILE_ROCK) + { map[xx + yy * w] = TILE_STAIRS_DOWN; map[xx + (yy+1) * w] = TILE_ROCK; map[(xx+1) + yy * w] = TILE_ROCK; @@ -259,40 +226,39 @@ void createTopMap(int w, int h, int level, u8 * map, u8 * data) { map[(xx+1) + (yy+1) * w] = TILE_ROCK; map[(xx+1) + (yy-1) * w] = TILE_ROCK; map[(xx-1) + (yy+1) * w] = TILE_ROCK; - ++sCount; + ++sCount; } } if(attempts < (w*h/100)) ++attempts; else break; } - free(mnoise1); - free(mnoise2); - free(mnoise3); - free(noise1); - free(noise2); - return; + free(mnoise1); + free(mnoise2); + free(mnoise3); + free(noise1); + free(noise2); + return; } -void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) { +void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) { double* mnoise1 = Noise(w, h, 16); double* mnoise2 = Noise(w, h, 16); double* mnoise3 = Noise(w, h, 16); - + double* nnoise1 = Noise(w, h, 16); double* nnoise2 = Noise(w, h, 16); double* nnoise3 = Noise(w, h, 16); - + double* wnoise1 = Noise(w, h, 16); double* wnoise2 = Noise(w, h, 16); double* wnoise3 = Noise(w, h, 16); - + double* noise1 = Noise(w, h, 32); double* noise2 = Noise(w, h, 32); - - int x,y,i,j,k,xx,yy; - + + int x, y; for(x = 0; x < w; ++x){ - for(y = 0; y < w; ++y){ - int i = x + y * w; + for(y = 0; y < w; ++y){ + int i = x + y * w; double val = fabs(noise1[i] - noise2[i]) * 3 - 2; @@ -301,7 +267,7 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 double nval = fabs(nnoise1[i] - nnoise2[i]); nval = fabs(nval - nnoise3[i]) * 3 - 2; - + double wval = fabs(wnoise1[i] - wnoise2[i]); wval = fabs(nval - wnoise3[i]) * 3 - 2; @@ -313,7 +279,7 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 dist = dist * dist * dist * dist; dist = dist * dist * dist * dist; val = val + 1 - dist * 20; - + if (val > -2 && wval < -2.0 + (depthLevel) / 2 * 3) { if (depthLevel > 2) map[i] = TILE_LAVA; @@ -324,43 +290,10 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 } else { map[i] = TILE_ROCK; } - } - } - - //generate dwarf house - if(depthLevel==3) { - createDwarfHouse(w, h, level, map, data); - //generate mushroom patches - } else if(depthLevel==2) { - for (i = 0; i < w * h / 5400; ++i) { - int xs = rand()%w; - int ys = rand()%h; - for (k = 0; k < 10; ++k) { - x = xs + (rand()%13) - 6; - y = ys + (rand()%13) - 6; - for (j = 0; j < 100; ++j) { - int xo = x + (rand()%5) - (rand()%5); - int yo = y + (rand()%5) - (rand()%5); - for (yy = yo - 1;yy <= yo + 1; ++yy){ - for(xx = xo - 1; xx <= xo + 1; ++xx){ - if (xx >= 0 && yy >= 0 && xx < w && yy < h) { - if (map[xx + yy * w] == TILE_DIRT) { - map[xx + yy * w] = TILE_MYCELIUM; - if(rand()%20==0) { - map[xx + yy * w] = TILE_MUSHROOM_BROWN + rand()%2; //BROWN or RED (=BROWN+1) - data[xx + yy * w] = rand()%2; - } - } - } - } - } - } - } - } - } - - //generate ores - for (i = 0; i < w * h / 400; ++i) { + } + } + int i,j; + for (i = 0; i < w * h / 400; ++i) { int x = rand()%w; int y = rand()%h; for(j = 0; j < 30; ++j) { @@ -373,15 +306,13 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 } } } - - //generate stairs down - if (depthLevel < 3){ - int sCount, attempts = 0; + if (depthLevel < 3){ + int sCount, attempts = 0; for (sCount = 0; sCount < 4;) { int xx = rand()%w; int yy = rand()%h; if (xx >= 0 && yy >= 0 && xx < w && yy < h) { - if (map[xx + yy * w] == TILE_ROCK){ + if (map[xx + yy * w] == TILE_ROCK){ map[xx + yy * w] = TILE_STAIRS_DOWN; map[xx + (yy+1) * w] = TILE_ROCK; map[(xx+1) + yy * w] = TILE_ROCK; @@ -392,486 +323,81 @@ void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 map[(xx+1) + (yy-1) * w] = TILE_ROCK; map[(xx-1) + (yy+1) * w] = TILE_ROCK; ++sCount; - } + } } if(attempts < (w*h/100)) ++attempts; else break; } - } - - //generate dungeon entrance - if(depthLevel==3) { - map[w/2+0 + (h/2+0) * w] = TILE_DUNGEON_ENTRANCE; - - map[w/2-1 + (h/2+0) * w] = TILE_DIRT; - map[w/2+1 + (h/2+0) * w] = TILE_DIRT; - map[w/2+0 + (h/2-1) * w] = TILE_DIRT; - map[w/2+1 + (h/2+1) * w] = TILE_DIRT; - - map[w/2-1 + (h/2-1) * w] = TILE_DUNGEON_WALL; - map[w/2-1 + (h/2+1) * w] = TILE_DUNGEON_WALL; - map[w/2+1 + (h/2-1) * w] = TILE_DUNGEON_WALL; - map[w/2+1 + (h/2+1) * w] = TILE_DUNGEON_WALL; - } - - free(mnoise1); - free(mnoise2); - free(mnoise3); - free(nnoise1); - free(nnoise2); - free(nnoise3); - free(wnoise1); - free(wnoise2); - free(wnoise3); - free(noise1); - free(noise2); - + } + free(mnoise1); + free(mnoise2); + free(mnoise3); + free(nnoise1); + free(nnoise2); + free(nnoise3); + free(wnoise1); + free(wnoise2); + free(wnoise3); + free(noise1); + free(noise2); + } + void createSkyMap(int w, int h, u8 * map, u8 * data) { + double* noise1 = Noise(w, h, 8); + double* noise2 = Noise(w, h, 8); + int x, y; + for(x = 0; x < w; ++x){ + for(y = 0; y < w; ++y){ + int i = x + y * w; -void createDungeonMap(int w, int h, int level, u8 * map, u8 * data) { - hasNPC = false; + double val = fabs(noise1[i] - noise2[i]) * 3 - 2; - int i, x, y; - for(x = 0; x < w; ++x){ - for(y = 0; y < w; ++y){ - i = x + y * w; - - //Startroom - if (x >= (w/2-5) && x <= (w/2+5) && y >= (h/2-5) && y <= (h/2+5) ) { - map[i] = TILE_DUNGEON_FLOOR; - data[i] = randomTile[rand()%randomTileSize]; - } else { - map[i] = TILE_DUNGEON_WALL; - data[i] = 0; - } - } - } - - //create dragon chamber(only call once and before other rooms) - createDungeonRoom(w, h, true, level, map, data); - - for(i = 0; i < 40; ++i) { - createDungeonRoom(w, h, false, level, map, data); - } - - //replace paths with actual dungeon floor - for(x = 0; x < w; ++x){ - for(y = 0; y < w; ++y){ - i = x + y * w; - - if (map[i]==255) { - map[i] = TILE_DUNGEON_FLOOR; - data[i] = randomTile[rand()%randomTileSize]; - } - } - } - - //create entrance - map[w/2 + h/2 * w] = TILE_DUNGEON_ENTRANCE; - - map[w/2+1 + h/2 * w] = TILE_DUNGEON_FLOOR; - map[w/2-1 + h/2 * w] = TILE_DUNGEON_FLOOR; - map[w/2 + (h/2+1) * w] = TILE_DUNGEON_FLOOR; - map[w/2 + (h/2-1) * w] = TILE_DUNGEON_FLOOR; - - map[w/2+1 + (h/2+1) * w] = TILE_DUNGEON_WALL; - map[w/2+1 + (h/2-1) * w] = TILE_DUNGEON_WALL; - map[w/2-1 + (h/2+1) * w] = TILE_DUNGEON_WALL; - map[w/2-1 + (h/2-1) * w] = TILE_DUNGEON_WALL; -} - -void createSkyMap(int w, int h, int level, u8 * map, u8 * data) { - double* noise1 = Noise(w, h, 8); - double* noise2 = Noise(w, h, 8); - int x, y; - for(x = 0; x < w; ++x){ - for(y = 0; y < w; ++y){ - int i = x + y * w; - - double val = fabs(noise1[i] - noise2[i]) * 3 - 2; - - double xd = x / (w - 1.0) * 2 - 1; - double yd = y / (h - 1.0) * 2 - 1; - if (xd < 0) xd = -xd; - if (yd < 0) yd = -yd; - double dist = xd >= yd ? xd : yd; - dist = dist * dist * dist * dist; - dist = dist * dist * dist * dist; - val = -val * 1 - 2.2; - val = val + 1 - dist * 20; - - if (val < -0.25) { - map[i] = -1; // render nothing - } else { - map[i] = TILE_CLOUD; - } - } - } - int i; - for (i = 0; i < w * h / 50; ++i) { - int xx = rand()%w; - int yy = rand()%h; - if (xx >= 0 && yy >= 0 && xx < w && yy < h) { - if (map[xx + yy * w] == TILE_CLOUD) map[xx + yy * w] = TILE_CLOUDCACTUS; - } - } - int sCount, attempts = 0; - for (sCount = 0; sCount < 2;) { - int xx = rand()%w; - int yy = rand()%h; - if (xx >= 0 && yy >= 0 && xx < w && yy < h) { - if (map[xx + yy * w] == TILE_CLOUD) - { - map[xx + yy * w] = TILE_STAIRS_DOWN; - map[xx + (yy+1) * w] = TILE_CLOUD; - map[(xx+1) + yy * w] = TILE_CLOUD; - map[xx + (yy-1) * w] = TILE_CLOUD; - map[(xx-1) + yy * w] = TILE_CLOUD; - map[(xx-1) + (yy-1) * w] = TILE_CLOUD; - map[(xx+1) + (yy+1) * w] = TILE_CLOUD; - map[(xx+1) + (yy-1) * w] = TILE_CLOUD; - map[(xx-1) + (yy+1) * w] = TILE_CLOUD; - ++sCount; - } - } - if(attempts < w*h) ++attempts; else break; - } - free(noise1); - free(noise2); -} - -//"Subgenerators" -void findFeatureLocation(int fw, int fh, int * accepted, int aLength, int maxTries, int w, int h, u8 * map, u8 * data) { - int leastNonFitting = fw * fh; - int tries; - - //find the location with the least non fitting tiles out of some randomly tried ones - for(tries=0; triesx) { - map[px + py * w] = TILE_SAND; - --px; - } - hw = 4 + rand()%2; - hh = 4 + rand()%2; - hx = px + 1; - hy = py - hh + 2 + rand()%(hh-2); - ex = px + hw; - ey = py; - createVillageHouse(0, hx, hy, hw, hh, ex, ey, w, h, level, map, data); - - //top - px = cx-1 + rand()%3; - py = cy-1; - while(py>y) { - map[px + py * w] = TILE_SAND; - --py; - } - hw = 5 + rand()%2; - hh = 4 + rand()%2; - hx = px - hw + 2 + rand()%(hw-2); - hy = py + 1; - ex = px; - ey = py+hh; - createVillageHouse(1, hx, hy, hw, hh, ex, ey, w, h, level, map, data); - - //right - px = cx+1; - py = cy-1 + rand()%3; - while(px w-5) wr = (w-5) - x; - if(y+hr > h-5) hr = (h-5) - y; - - //check instersection - bool allowed = true; - for(xr = x-1; xr < x+wr+1; ++xr) { - for(yr = y-1; yr < y+hr+1; ++yr) { - i = xr + yr * w; - - //255 for paths so rooms can overlap paths - if(map[i]!=TILE_DUNGEON_WALL && map[i]!=255) { - allowed = false; - break; - } - } - if(!allowed) break; - } - if(!allowed) continue; - - //create room - for(xr = x; xr < x+wr; ++xr) { - for(yr = y; yr < y+hr; ++yr) { - i = xr + yr * w; - - map[i] = TILE_DUNGEON_FLOOR; - data[i] = randomTile[rand()%randomTileSize]; - } - } - - //Create path back to existing stuff - xp = x + wr/2; - yp = y + hr/2; - i = xp + yp * w; - bool checkForFloor = false; - bool xFirst = (rand()%2)==0; - while((checkForFloor && (map[i]!=TILE_DUNGEON_FLOOR && map[i]!=255)) || (!checkForFloor && (map[i]==TILE_DUNGEON_FLOOR || map[i]==255))) { - if(checkForFloor) { - //make connection - map[i] = 255; - } - - //move - if(xFirst) { - if(xp > w/2) --xp; - else if(xp < w/2) ++xp; - else if(yp > h/2) --yp; - else if(yp < h/2) ++yp; - else break; - } else { - if(yp > h/2) --yp; - else if(yp < h/2) ++yp; - else if(xp > w/2) --xp; - else if(xp < w/2) ++xp; - else break; - } - - i = xp + yp * w; - - //search for end of current room - if(!checkForFloor && (map[i]!=TILE_DUNGEON_FLOOR && map[i]!=255)) checkForFloor = true; - } - - //dekorate dragon room - if(dragon) { - for(xr = x; xr < x+wr; ++xr) { - for(yr = y; yr < y+hr; ++yr) { - i = xr + yr * w; - - if((xr==x+1 || xr==x+wr-2 || yr==y+1 || yr==y+hr-2) && (xr!=x && xr!=x+wr-1 && yr!=y && yr!=y+hr-1)) { - map[i] = TILE_MAGIC_BARRIER; - } - } - } - - //add Dragon Entity - addEntityToList(newDragonEntity((x+wr/2) << 4, (y+hr/2) << 4, level), &eManager); - break; - } - - //dekorate room - bool lava = (rand()%4)==0; - bool pillars = (rand()%4)==0; - bool books = (rand()%4)==0; - for(xr = x; xr < x+wr; ++xr) { - for(yr = y; yr < y+hr; ++yr) { - i = xr + yr * w; - - if(lava && xr > x+1 && xr < x+wr-2 && yr > y+1 && yr < y+hr-2) { - map[i] = TILE_LAVA; - data[i] = 0; - } else if(pillars && xr > x && xr < x+wr-1 && yr > y && yr < y+hr-1 && xr%2 == 0 && yr%2 == 0) { - map[i] = TILE_DUNGEON_WALL; - data[i] = 0; - } else if(books && (xr>x && xry && yr= yd ? xd : yd; + dist = dist * dist * dist * dist; + dist = dist * dist * dist * dist; + val = -val * 1 - 2.2; + val = val + 1 - dist * 20; + + if (val < -0.25) { + map[i] = -1; // render nothing } else { - //add magic pillars for dragon barrier - if(xr==x+wr/2 && yr==y+hr/2) { - int pcount = 0; - int i = 0; - for (i = 0; i < eManager.lastSlot[5]; ++i) { - Entity * e = &eManager.entities[5][i]; - - if(e->type == ENTITY_MAGIC_PILLAR) { - ++pcount; - } - } - if(pcount<8) { - addEntityToList(newMagicPillarEntity((xr << 4) + 8, (yr << 4) + 8, level), &eManager); - } - continue; - } - - if(rand()%50==0) map[i] = TILE_IRONORE + (rand()%3); + map[i] = TILE_CLOUD; } + } + } + int i; + for (i = 0; i < w * h / 50; ++i) { + int xx = rand()%w; + int yy = rand()%h; + if (xx >= 0 && yy >= 0 && xx < w && yy < h) { + if (map[xx + yy * w] == TILE_CLOUD) map[xx + yy * w] = TILE_CLOUDCACTUS; } } - - break; - } -} + int sCount, attempts = 0; + for (sCount = 0; sCount < 2;) { + int xx = rand()%w; + int yy = rand()%h; + if (xx >= 0 && yy >= 0 && xx < w && yy < h) { + if (map[xx + yy * w] == TILE_CLOUD) + { + map[xx + yy * w] = TILE_STAIRS_DOWN; + map[xx + (yy+1) * w] = TILE_CLOUD; + map[(xx+1) + yy * w] = TILE_CLOUD; + map[xx + (yy-1) * w] = TILE_CLOUD; + map[(xx-1) + yy * w] = TILE_CLOUD; + map[(xx-1) + (yy-1) * w] = TILE_CLOUD; + map[(xx+1) + (yy+1) * w] = TILE_CLOUD; + map[(xx+1) + (yy-1) * w] = TILE_CLOUD; + map[(xx-1) + (yy+1) * w] = TILE_CLOUD; + ++sCount; + } + } + if(attempts < w*h) ++attempts; else break; + } + free(noise1); + free(noise2); + } + diff --git a/source/MapGen.h b/source/MapGen.h old mode 100755 new mode 100644 index 8e11015..8ab4ce7 --- a/source/MapGen.h +++ b/source/MapGen.h @@ -2,6 +2,7 @@ #include #include #include +#include #include <3ds.h> #include "Globals.h" @@ -9,21 +10,10 @@ float nextFloat(); double sample(double * values, int x, int y); double * Noise(int w, int h, int featureSize); -void createAndValidateTopMap(int w, int h, int level, u8 * map, u8 * data); -void createTopMap(int w, int h, int level, u8 * map, u8 * data); -void createAndValidateUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data); -void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data); -void createAndValidateDungeonMap(int w, int h, int level, u8 * map, u8 * data); -void createDungeonMap(int w, int h, int level, u8 * map, u8 * data); -void createAndValidateSkyMap(int w, int h, int level, u8 * map, u8 * data); -void createSkyMap(int w, int h, int level, u8 * map, u8 * data); - -int featureX; -int featureY; -void findFeatureLocation(int fw, int fh, int * accepted, int aLength, int maxTries, int w, int h, u8 * map, u8 * data); - -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 newSeed(); +void createAndValidateTopMap(int w, int h, u8 * map, u8 * data); +void createTopMap(int w, int h, u8 * map, u8 * data); +void createAndValidateUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data); +void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data); +void createAndValidateSkyMap(int w, int h, u8 * map, u8 * data); +void createSkyMap(int w, int h, u8 * map, u8 * data); diff --git a/source/Menu.c b/source/Menu.c old mode 100755 new mode 100644 index 9387798..07300ea --- a/source/Menu.c +++ b/source/Menu.c @@ -1,22 +1,20 @@ #include "Menu.h" -#include "PacketHandler.h" -#include "SaveLoad.h" - -char options[][12] = {"Start Game", "Host Game", "Join Game", "How To Play", "Settings", "About", "Exit"}; +char options[][12] = {"Start Game", "How To Play","Settings", "About", "Exit"}; +char pOptions[][24] = {"Return to game", "Save Progress", "Exit to title"}; char keybOptions[][24] = {"Exit and Save", "Exit and Don't save","Reset to default"}; -char setOptions[][24] = {"Rebind Buttons", "Texture packs", "Test Features: ", "N3DS Speedup: ", "Return to title"}; +char setOptions[][24] = {"Rebind Buttons", "Texture packs", "Debug Text: ", "N3DS Speedup: ", "Return to title"}; // Rebind buttons menu (Settings) int keys[] = { - KEY_A,KEY_B,KEY_X,KEY_Y, - KEY_CPAD_UP,KEY_CPAD_DOWN,KEY_CPAD_LEFT,KEY_CPAD_RIGHT, - KEY_DUP, KEY_DDOWN, KEY_DLEFT, KEY_DRIGHT, - KEY_CSTICK_UP,KEY_CSTICK_DOWN,KEY_CSTICK_LEFT,KEY_CSTICK_RIGHT, - KEY_L,KEY_R,KEY_ZL,KEY_ZR, - KEY_START,KEY_SELECT + KEY_A,KEY_B,KEY_X,KEY_Y, + KEY_CPAD_UP,KEY_CPAD_DOWN,KEY_CPAD_LEFT,KEY_CPAD_RIGHT, + KEY_DUP, KEY_DDOWN, KEY_DLEFT, KEY_DRIGHT, + KEY_CSTICK_UP,KEY_CSTICK_DOWN,KEY_CSTICK_LEFT,KEY_CSTICK_RIGHT, + KEY_L,KEY_R,KEY_ZL,KEY_ZR, + KEY_START,KEY_SELECT }; -int keyProp[14] = {[0 ... 13] = 0}; +int keyProp[12] = {[0 ... 11] = 0}; bool areYouSure = false; bool areYouSureSave = false; bool bindOpt = false; @@ -24,7 +22,6 @@ bool left = false; bool selBut = false; s8 errorBut = -1; s8 curSaveSel = 0; -int menuScanTimer = 0; // Load Game Menu (Start Game) char fileNames[1000][256]; @@ -36,7 +33,6 @@ s8 touchDelay = 0; bool isTouching = false; int touchX = 0, touchY = 0, touchW = 0, touchH = 0; s8 errorFileName = 0; -bool toMultiplayer; // Load Texturepacks Menu char tpFileNames[1000][256]; @@ -44,708 +40,686 @@ char tpFileComment[1000][60]; s16 tpFileCount = 0; s8 isLoadingTP = 0; -void readFiles(){ - memset(&fileNames, 0, sizeof(fileNames)); // reset fileNames - worldFileCount = 0; - DIR * d; - struct dirent * dir; - d = opendir("."); - if (d){ - while ((dir = readdir(d)) != NULL) { - if (strncmp(dir->d_name+strlen(dir->d_name)-4, ".msv", 4) == 0) { // Check if filename contains ".msv" - strncpy(fileNames[worldFileCount], dir->d_name, strlen(dir->d_name)-4); - //TODO: This no longer works, update for new format: - //FILE * file = fopen(dir->d_name, "rb"); - //fread(&fileScore[worldFileCount],sizeof(int), 1, file); - //fread(&fileWin[worldFileCount],sizeof(bool), 1, file); - //fclose(file); - fileScore[worldFileCount] = 0; - fileWin[worldFileCount] = false; +s16 pauseSaveDisplayTimer = 0; - ++worldFileCount; - } - } - closedir(d); - } +void readFiles(){ + memset(&fileNames, 0, sizeof(fileNames)); // reset fileNames + worldFileCount = 0; + DIR * d; + struct dirent * dir; + d = opendir("."); + if (d){ + while ((dir = readdir(d)) != NULL) { + if (strstr(dir->d_name, ".wld") != NULL) { // Check if filename contains ".wld" + strncpy(fileNames[worldFileCount], dir->d_name, strlen(dir->d_name)-4); + FILE * file = fopen(dir->d_name, "rb"); + fread(&fileScore[worldFileCount],sizeof(int), 1, file); + fread(&fileWin[worldFileCount],sizeof(bool), 1, file); + fclose(file); + ++worldFileCount; + } + } + closedir(d); + } } void readTPFiles(){ - memset(&tpFileNames, 0, sizeof(tpFileNames)); // reset tp fileNames - memset(&tpFileComment, 0, sizeof(tpFileComment)); // reset zip comments - tpFileCount = 1; // 0 = default. - DIR * d; - struct dirent * dir; - d = opendir("./texturepacks/"); - if (d){ - while ((dir = readdir(d)) != NULL) { - if (strstr(dir->d_name, ".zip") != NULL) { // Check if filename contains ".zip" - strncpy(tpFileNames[tpFileCount], dir->d_name, strlen(dir->d_name)-4); - - char fullDirName[256]; - sprintf(fullDirName,"./texturepacks/%s",dir->d_name); - //int err = - getTexturePackComment(fullDirName, tpFileComment[tpFileCount]); - /* - if(err > 0){ - char errorText[10]; - sprintf(errorText,"err:%d",err); - strncpy(tpFileComment[tpFileCount], errorText, strlen(errorText)); - }*/ - ++tpFileCount; - } - } - closedir(d); - } + memset(&tpFileNames, 0, sizeof(tpFileNames)); // reset tp fileNames + memset(&tpFileComment, 0, sizeof(tpFileComment)); // reset zip comments + tpFileCount = 1; // 0 = default. + DIR * d; + struct dirent * dir; + d = opendir("./texturepacks/"); + if (d){ + while ((dir = readdir(d)) != NULL) { + if (strstr(dir->d_name, ".zip") != NULL) { // Check if filename contains ".zip" + strncpy(tpFileNames[tpFileCount], dir->d_name, strlen(dir->d_name)-4); + + char fullDirName[256]; + sprintf(fullDirName,"./texturepacks/%s",dir->d_name); + //int err = + getTexturePackComment(fullDirName, tpFileComment[tpFileCount]); + /* + if(err > 0){ + char errorText[10]; + sprintf(errorText,"err:%d",err); + strncpy(tpFileComment[tpFileCount], errorText, strlen(errorText)); + }*/ + ++tpFileCount; + } + } + closedir(d); + } } s8 checkFileNameForErrors(){ - int length = strlen(fileNames[worldFileCount]); - if(length < 1)return 1; // Error: Length cannot be 0. - int i; - bool isGood = false; - for(i=0; i < length; ++i){ if(isalnum((int)fileNames[worldFileCount][i])) isGood = true; } - if(!isGood) return 2; // Error: Filename must contain atleast one letter or number. - - DIR * d; - struct dirent * dir; - d = opendir("."); - if (d){ - while ((dir = readdir(d)) != NULL) { - if (strstr(dir->d_name, ".msv") != NULL) { // Check if filename contains ".msv" - char cmprFile[256]; - strncpy(cmprFile, dir->d_name, strlen(dir->d_name)-4); - if(strncmp(fileNames[worldFileCount],cmprFile,strlen(fileNames[worldFileCount])) == 0) return 3; // Error: Filename cannot already exist. - } - } - closedir(d); - } - - return 0; // No errors found! + int length = strlen(fileNames[worldFileCount]); + if(length < 1)return 1; // Error: Length cannot be 0. + int i; + bool isGood = false; + for(i=0; i < length; ++i){ if(isalnum((int)fileNames[worldFileCount][i])) isGood = true; } + if(!isGood) return 2; // Error: Filename must contain atleast one letter or number. + + DIR * d; + struct dirent * dir; + d = opendir("."); + if (d){ + while ((dir = readdir(d)) != NULL) { + if (strstr(dir->d_name, ".wld") != NULL) { // Check if filename contains ".wld" + char cmprFile[256]; + strncpy(cmprFile, dir->d_name, strlen(dir->d_name)-4); + if(strncmp(fileNames[worldFileCount],cmprFile,strlen(fileNames[worldFileCount])) == 0) return 3; // Error: Filename cannot already exist. + } + } + closedir(d); + } + + return 0; // No errors found! } void addToFileName(char * c){ - strncat(fileNames[worldFileCount], c, 1); + strncat(fileNames[worldFileCount], c, 1); } /* Keypad */ void doTouchButton(){ - int xVal = localInputs.k_touch.px, yVal = localInputs.k_touch.py; - int strLength = strlen(fileNames[worldFileCount]); - if(yVal >= 60 && yVal < 80){ // 0 to 9 - if(xVal >= 4 && xVal < 4+16){ touchX = 4; if(strLength < 24)addToFileName("1");} - else if(xVal >= 36 && xVal < 4+32+16){ touchX = 36; if(strLength < 24)addToFileName("2");} - else if(xVal >= 68 && xVal < 4+64+16){ touchX = 68; if(strLength < 24)addToFileName("3");} - else if(xVal >= 100 && xVal < 4+96+16){ touchX = 100; if(strLength < 24)addToFileName("4");} - else if(xVal >= 132 && xVal < 4+128+16){ touchX = 132; if(strLength < 24)addToFileName("5");} - else if(xVal >= 164 && xVal < 4+160+16){ touchX = 164; if(strLength < 24)addToFileName("6");} - else if(xVal >= 196 && xVal < 4+192+16){ touchX = 196; if(strLength < 24)addToFileName("7");} - else if(xVal >= 228 && xVal < 4+224+16){ touchX = 228; if(strLength < 24)addToFileName("8");} - else if(xVal >= 260 && xVal < 4+256+16){ touchX = 260; if(strLength < 24)addToFileName("9");} - else if(xVal >= 292 && xVal < 4+288+16){ touchX = 292; if(strLength < 24)addToFileName("0");} - else return; - touchY = 56; - touchW = 22; - touchH = 22; - touchDelay = 6; - isTouching = true; - } else if(yVal >= 80 && yVal < 100){ // Q to P - if(xVal >= 4 && xVal < 4+16){ touchX = 4; if(strLength < 24)addToFileName("Q");} - else if(xVal >= 36 && xVal < 4+32+16){ touchX = 36; if(strLength < 24)addToFileName("W");} - else if(xVal >= 68 && xVal < 4+64+16){ touchX = 68; if(strLength < 24)addToFileName("E");} - else if(xVal >= 100 && xVal < 4+96+16){ touchX = 100; if(strLength < 24)addToFileName("R");} - else if(xVal >= 132 && xVal < 4+128+16){ touchX = 132; if(strLength < 24)addToFileName("T");} - else if(xVal >= 164 && xVal < 4+160+16){ touchX = 164; if(strLength < 24)addToFileName("Y");} - else if(xVal >= 196 && xVal < 4+192+16){ touchX = 196; if(strLength < 24)addToFileName("U");} - else if(xVal >= 228 && xVal < 4+224+16){ touchX = 228; if(strLength < 24)addToFileName("I");} - else if(xVal >= 260 && xVal < 4+256+16){ touchX = 260; if(strLength < 24)addToFileName("O");} - else if(xVal >= 292 && xVal < 4+288+16){ touchX = 292; if(strLength < 24)addToFileName("P");} - else return; - touchY = 76; - touchW = 22; - touchH = 22; - touchDelay = 6; - isTouching = true; - } else if(yVal >= 100 && yVal < 120){ // A to L - if(xVal >= 20 && xVal < 36){ touchX = 20; if(strLength < 24)addToFileName("A");} - else if(xVal >= 52 && xVal < 68){ touchX = 52; if(strLength < 24)addToFileName("S");} - else if(xVal >= 84 && xVal < 100){ touchX = 84; if(strLength < 24)addToFileName("D");} - else if(xVal >= 116 && xVal < 132){ touchX = 116; if(strLength < 24)addToFileName("F");} - else if(xVal >= 148 && xVal < 164){ touchX = 148; if(strLength < 24)addToFileName("G");} - else if(xVal >= 180 && xVal < 196){ touchX = 180; if(strLength < 24)addToFileName("H");} - else if(xVal >= 212 && xVal < 230){ touchX = 212; if(strLength < 24)addToFileName("J");} - else if(xVal >= 244 && xVal < 262){ touchX = 244; if(strLength < 24)addToFileName("K");} - else if(xVal >= 276 && xVal < 294){ touchX = 276; if(strLength < 24)addToFileName("L");} - else return; - touchY = 96; - touchW = 22; - touchH = 22; - touchDelay = 6; - isTouching = true; - } else if(yVal >= 120 && yVal < 140){ // Z to M - if(xVal >= 52 && xVal < 68){ touchX = 52; if(strLength < 24)addToFileName("Z");} - else if(xVal >= 84 && xVal < 100){ touchX = 84; if(strLength < 24)addToFileName("X");} - else if(xVal >= 116 && xVal < 132){ touchX = 116; if(strLength < 24)addToFileName("C");} - else if(xVal >= 148 && xVal < 164){ touchX = 148; if(strLength < 24)addToFileName("V");} - else if(xVal >= 180 && xVal < 196){ touchX = 180; if(strLength < 24)addToFileName("B");} - else if(xVal >= 212 && xVal < 230){ touchX = 212; if(strLength < 24)addToFileName("N");} - else if(xVal >= 244 && xVal < 262){ touchX = 244; if(strLength < 24)addToFileName("M");} - else return; - touchY = 116; - touchW = 22; - touchH = 22; - touchDelay = 6; - isTouching = true; - } else if(yVal >= 140 && yVal < 160){ // SPACE and BACKSPACE - if(xVal >= 32 && xVal < 112){ - touchX = 32; - touchW = 16*5+14; - if(strLength < 24)addToFileName("_"); // Underscores don't appear in the game. - } - else if(xVal >= 148 && xVal < 262){ - if(strLength <= 0) return; - touchX = 148; - touchW = 16*9+8; - fileNames[worldFileCount][strLength-1] = '\0'; - } - else return; - touchY = 136; - touchH = 22; - touchDelay = 6; - isTouching = true; - } - errorFileName = 0; + int xVal = k_touch.px, yVal = k_touch.py; + int strLength = strlen(fileNames[worldFileCount]); + if(yVal >= 60 && yVal < 80){ // 0 to 9 + if(xVal >= 4 && xVal < 4+16){ touchX = 4; if(strLength < 24)addToFileName("1");} + else if(xVal >= 36 && xVal < 4+32+16){ touchX = 36; if(strLength < 24)addToFileName("2");} + else if(xVal >= 68 && xVal < 4+64+16){ touchX = 68; if(strLength < 24)addToFileName("3");} + else if(xVal >= 100 && xVal < 4+96+16){ touchX = 100; if(strLength < 24)addToFileName("4");} + else if(xVal >= 132 && xVal < 4+128+16){ touchX = 132; if(strLength < 24)addToFileName("5");} + else if(xVal >= 164 && xVal < 4+160+16){ touchX = 164; if(strLength < 24)addToFileName("6");} + else if(xVal >= 196 && xVal < 4+192+16){ touchX = 196; if(strLength < 24)addToFileName("7");} + else if(xVal >= 228 && xVal < 4+224+16){ touchX = 228; if(strLength < 24)addToFileName("8");} + else if(xVal >= 260 && xVal < 4+256+16){ touchX = 260; if(strLength < 24)addToFileName("9");} + else if(xVal >= 292 && xVal < 4+288+16){ touchX = 292; if(strLength < 24)addToFileName("0");} + else return; + touchY = 56; + touchW = 22; + touchH = 22; + touchDelay = 6; + isTouching = true; + } else if(yVal >= 80 && yVal < 100){ // Q to P + if(xVal >= 4 && xVal < 4+16){ touchX = 4; if(strLength < 24)addToFileName("Q");} + else if(xVal >= 36 && xVal < 4+32+16){ touchX = 36; if(strLength < 24)addToFileName("W");} + else if(xVal >= 68 && xVal < 4+64+16){ touchX = 68; if(strLength < 24)addToFileName("E");} + else if(xVal >= 100 && xVal < 4+96+16){ touchX = 100; if(strLength < 24)addToFileName("R");} + else if(xVal >= 132 && xVal < 4+128+16){ touchX = 132; if(strLength < 24)addToFileName("T");} + else if(xVal >= 164 && xVal < 4+160+16){ touchX = 164; if(strLength < 24)addToFileName("Y");} + else if(xVal >= 196 && xVal < 4+192+16){ touchX = 196; if(strLength < 24)addToFileName("U");} + else if(xVal >= 228 && xVal < 4+224+16){ touchX = 228; if(strLength < 24)addToFileName("I");} + else if(xVal >= 260 && xVal < 4+256+16){ touchX = 260; if(strLength < 24)addToFileName("O");} + else if(xVal >= 292 && xVal < 4+288+16){ touchX = 292; if(strLength < 24)addToFileName("P");} + else return; + touchY = 76; + touchW = 22; + touchH = 22; + touchDelay = 6; + isTouching = true; + } else if(yVal >= 100 && yVal < 120){ // A to L + if(xVal >= 20 && xVal < 36){ touchX = 20; if(strLength < 24)addToFileName("A");} + else if(xVal >= 52 && xVal < 68){ touchX = 52; if(strLength < 24)addToFileName("S");} + else if(xVal >= 84 && xVal < 100){ touchX = 84; if(strLength < 24)addToFileName("D");} + else if(xVal >= 116 && xVal < 132){ touchX = 116; if(strLength < 24)addToFileName("F");} + else if(xVal >= 148 && xVal < 164){ touchX = 148; if(strLength < 24)addToFileName("G");} + else if(xVal >= 180 && xVal < 196){ touchX = 180; if(strLength < 24)addToFileName("H");} + else if(xVal >= 212 && xVal < 230){ touchX = 212; if(strLength < 24)addToFileName("J");} + else if(xVal >= 244 && xVal < 262){ touchX = 244; if(strLength < 24)addToFileName("K");} + else if(xVal >= 276 && xVal < 294){ touchX = 276; if(strLength < 24)addToFileName("L");} + else return; + touchY = 96; + touchW = 22; + touchH = 22; + touchDelay = 6; + isTouching = true; + } else if(yVal >= 120 && yVal < 140){ // Z to M + if(xVal >= 52 && xVal < 68){ touchX = 52; if(strLength < 24)addToFileName("Z");} + else if(xVal >= 84 && xVal < 100){ touchX = 84; if(strLength < 24)addToFileName("X");} + else if(xVal >= 116 && xVal < 132){ touchX = 116; if(strLength < 24)addToFileName("C");} + else if(xVal >= 148 && xVal < 164){ touchX = 148; if(strLength < 24)addToFileName("V");} + else if(xVal >= 180 && xVal < 196){ touchX = 180; if(strLength < 24)addToFileName("B");} + else if(xVal >= 212 && xVal < 230){ touchX = 212; if(strLength < 24)addToFileName("N");} + else if(xVal >= 244 && xVal < 262){ touchX = 244; if(strLength < 24)addToFileName("M");} + else return; + touchY = 116; + touchW = 22; + touchH = 22; + touchDelay = 6; + isTouching = true; + } else if(yVal >= 140 && yVal < 160){ // SPACE and BACKSPACE + if(xVal >= 32 && xVal < 112){ + touchX = 32; + touchW = 16*5+14; + if(strLength < 24)addToFileName("_"); // Underscores don't appear in the game. + } + else if(xVal >= 148 && xVal < 262){ + if(strLength <= 0) return; + touchX = 148; + touchW = 16*9+8; + fileNames[worldFileCount][strLength-1] = '\0'; + } + else return; + touchY = 136; + touchH = 22; + touchDelay = 6; + isTouching = true; + } + errorFileName = 0; } void switchGameBut(bool left, int buttonID){ - int id; - for(id = 0; id < 13; ++id){ - if(id > 8 && id < 12) continue; - if(keyProp[id] & buttonID){ - keyProp[id] ^= buttonID; // Toggle buttonID bit - if(left){ - int id2 = id - 1; - if (id2 == 11) id2 = 8; - if (id2 < 0) return; - keyProp[id2] ^= buttonID; - } else { - int id2 = id+1; - if (id2 == 9) id2 = 12; - if (id2 > 13) return; - keyProp[id2] ^= buttonID; - } - return; - } - } - if(left) keyProp[13] ^= buttonID; - else keyProp[0] ^= buttonID; - + int id; + for(id = 0; id < 7; ++id){ + if(keyProp[id] & buttonID){ + keyProp[id] ^= buttonID; // Toggle buttonID bit + if(left){ + int id2 = id -1; + if (id2 < 0) return; + keyProp[id2] ^= buttonID; + } else { + int id2 = id+1; + if (id2 > 6) return; + keyProp[id2] ^= buttonID; + } + return; + } + } + if(left) keyProp[6] ^= buttonID; + else keyProp[0] ^= buttonID; + } void switchMenuBut(bool left, int buttonID){ - int id; - for(id = 0; id < 13; ++id){ - if(id > 3 && id < 9) continue; - if(keyProp[id] & buttonID){ - keyProp[id] ^= buttonID; // Toggle buttonID bit - if(left){ - int id2 = id - 1; - if (id2 == 8) id2 = 3; - if (id2 < 0) return; - keyProp[id2] ^= buttonID; - } else { - int id2 = id+1; - if (id2 == 4) id2 = 9; - if (id2 > 13) return; - keyProp[id2] ^= buttonID; - } - return; - } - } - if(left) keyProp[13] ^= buttonID; - else keyProp[0] ^= buttonID; + int id; + for(id = 0; id < 12; ++id){ + if(id > 3 && id < 7) continue; + if(keyProp[id] & buttonID){ + keyProp[id] ^= buttonID; // Toggle buttonID bit + if(left){ + int id2 = id - 1; + if (id2 == 6) id2 = 3; + if (id2 < 0) return; + keyProp[id2] ^= buttonID; + } else { + int id2 = id+1; + if (id2 == 4) id2 = 7; + if (id2 > 11) return; + keyProp[id2] ^= buttonID; + } + return; + } + } + if(left) keyProp[11] ^= buttonID; + else keyProp[0] ^= buttonID; } s8 checkPropButtons(){ - if(keyProp[0] == 0) return 0; - if(keyProp[1] == 0) return 1; - if(keyProp[2] == 0) return 2; - if(keyProp[3] == 0) return 3; - if(keyProp[4] == 0) return 4; - if(keyProp[5] == 0) return 5; - if(keyProp[6] == 0) return 6; - if(keyProp[7] == 0) return 7; - if(keyProp[8] == 0) return 8; - if(keyProp[9] == 0) return 9; - if(keyProp[10] == 0) return 10; - if(keyProp[11] == 0) return 11; - if(keyProp[12] == 0) return 12; - if(keyProp[13] == 0) return 13; - return -1; -} - -bool menuHasMapLoaded = false; -float mxscr = 400; -float myscr = 400; -float menuxa = 0; -float menuya = 0; -void initMenus() { - readFiles(); - - if(worldFileCount>0) { - memset(¤tFileName, 0, 255); // reset currentFileName - sprintf(currentFileName,"%s.msv",fileNames[currentSelection]); - - initBGMap = 1; - } else { - initBGMap = 2; - } - - menuHasMapLoaded = true; - while(menuxa==0) menuxa = (rand()%3 - 1) * 0.25; - while(menuya==0) menuya = (rand()%3 - 1) * 0.25; + if(keyProp[0] == 0) return 0; + if(keyProp[1] == 0) return 1; + if(keyProp[2] == 0) return 2; + if(keyProp[3] == 0) return 3; + if(keyProp[4] == 0) return 4; + if(keyProp[5] == 0) return 5; + if(keyProp[6] == 0) return 6; + if(keyProp[7] == 0) return 7; + if(keyProp[8] == 0) return 8; + if(keyProp[9] == 0) return 9; + if(keyProp[10] == 0) return 10; + if(keyProp[11] == 0) return 11; + return -1; } Item median; void tickMenu(int menu){ - switch(menu){ - case MENU_SETTINGS_REBIND: - if(!bindOpt){ - if(!selBut){ - if (localInputs.k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection=21;} - if (localInputs.k_down.clicked){ ++currentSelection; if(currentSelection > 21)currentSelection=0;} - if (localInputs.k_left.clicked){ left = true;} - if (localInputs.k_right.clicked){ left = false;} - } else { - if (localInputs.k_left.clicked){ - if(left)switchGameBut(true,keys[currentSelection]); - else switchMenuBut(true,keys[currentSelection]); - } else if (localInputs.k_right.clicked) { - if(left)switchGameBut(false,keys[currentSelection]); - else switchMenuBut(false,keys[currentSelection]); - } - } - - if (localInputs.k_accept.clicked) selBut = !selBut; - if (localInputs.k_decline.clicked){ - bindOpt = true; - curSaveSel = 0; - } - } else { - if (localInputs.k_up.clicked){ --curSaveSel; if(curSaveSel < 0)curSaveSel=2;} - if (localInputs.k_down.clicked){ ++curSaveSel; if(curSaveSel > 2)curSaveSel=0;} - if (localInputs.k_decline.clicked){ - bindOpt = false; - errorBut = -1; - } - if (localInputs.k_accept.clicked){ - switch(curSaveSel){ - case 0: // Exit and save - if(checkPropButtons() == -1){ - localInputs.k_up.input = keyProp[0]; - localInputs.k_down.input = keyProp[1]; - localInputs.k_left.input = keyProp[2]; - localInputs.k_right.input = keyProp[3]; - localInputs.k_attack.input = keyProp[4]; - localInputs.k_pickup.input = keyProp[5]; - localInputs.k_use.input = keyProp[6]; - localInputs.k_menu.input = keyProp[7]; - localInputs.k_pause.input = keyProp[8]; - localInputs.k_accept.input = keyProp[9]; - localInputs.k_decline.input = keyProp[10]; - localInputs.k_delete.input = keyProp[11]; - localInputs.k_menuNext.input = keyProp[12]; - localInputs.k_menuPrev.input = keyProp[13]; - - FILE *fs=fopen("btnSave.bin","wb"); - fwrite(keyProp,sizeof(keyProp),1,fs); - fclose(fs); - - currentSelection = 0; - currentMenu = MENU_SETTINGS; - errorBut = -1; - } else errorBut = checkPropButtons(); - break; - case 1: // Exit and DON'T save - currentSelection = 0; - currentMenu = MENU_SETTINGS; - errorBut = -1; - break; - case 2: // reset defaults - keyProp[0] = KEY_DUP | KEY_CPAD_UP | KEY_CSTICK_UP; - keyProp[1] = KEY_DDOWN | KEY_CPAD_DOWN | KEY_CSTICK_DOWN; - keyProp[2] = KEY_DLEFT | KEY_CPAD_LEFT | KEY_CSTICK_LEFT; - keyProp[3] = KEY_DRIGHT | KEY_CPAD_RIGHT | KEY_CSTICK_RIGHT; - keyProp[4] = KEY_A; - keyProp[5] = KEY_B; - keyProp[6] = KEY_X; - keyProp[7] = KEY_Y ; - keyProp[8] = KEY_START; - keyProp[9] = KEY_A; - keyProp[10] = KEY_B; - keyProp[11] = KEY_X; - keyProp[12] = KEY_R | KEY_ZR; - keyProp[13] = KEY_L | KEY_ZL; - bindOpt = false; - errorBut = -1; - break; - } - } - } - break; - - case MENU_ABOUT: - if (localInputs.k_decline.clicked) currentMenu = MENU_TITLE; - break; - /* - case MENU_ARMOR: - if (k_delete.clicked || k_decline.clicked){ - currentMenu = MENU_NONE; - player.p.activeItem = &noItem; - player.p.isCarrying = false; - } - if (k_accept.clicked){ // Select item from inventory - if(player.p.inv->lastSlot!=0){ - median = player.p.inv->items[curInvSel]; // create copy of item. - removeItemFromInventory(curInvSel, player.p.inv); // remove original - pushItemToInventoryFront(median, player.p.inv); // add copy to front + switch(menu){ + case MENU_SETTINGS_REBIND: + if(!bindOpt){ + if(!selBut){ + if (k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection=21;} + if (k_down.clicked){ ++currentSelection; if(currentSelection > 21)currentSelection=0;} + if (k_left.clicked){ left = true;} + if (k_right.clicked){ left = false;} + } else { + if (k_left.clicked){ + if(left)switchGameBut(true,keys[currentSelection]); + else switchMenuBut(true,keys[currentSelection]); + } else if (k_right.clicked) { + if(left)switchGameBut(false,keys[currentSelection]); + else switchMenuBut(false,keys[currentSelection]); + } + } + + if (k_accept.clicked) selBut = !selBut; + if (k_decline.clicked){ + bindOpt = true; + curSaveSel = 0; + } + } else { + if (k_up.clicked){ --curSaveSel; if(curSaveSel < 0)curSaveSel=2;} + if (k_down.clicked){ ++curSaveSel; if(curSaveSel > 2)curSaveSel=0;} + if (k_decline.clicked){ + bindOpt = false; + errorBut = -1; + } + if (k_accept.clicked){ + switch(curSaveSel){ + case 0: // Exit and save + if(checkPropButtons() == -1){ + k_up.input = keyProp[0]; + k_down.input = keyProp[1]; + k_left.input = keyProp[2]; + k_right.input = keyProp[3]; + k_attack.input = keyProp[4]; + k_menu.input = keyProp[5]; + k_pause.input = keyProp[6]; + k_accept.input = keyProp[7]; + k_decline.input = keyProp[8]; + k_delete.input = keyProp[9]; + k_menuNext.input = keyProp[10]; + k_menuPrev.input = keyProp[11]; + + FILE *fs=fopen("btnSave.bin","wb"); + fwrite(keyProp,sizeof(int),12,fs); + fclose(fs); + + currentSelection = 0; + currentMenu = MENU_SETTINGS; + errorBut = -1; + } else errorBut = checkPropButtons(); + break; + case 1: // Exit and DON'T save + currentSelection = 0; + currentMenu = MENU_SETTINGS; + errorBut = -1; + break; + case 2: // reset defaults + keyProp[0] = KEY_DUP | KEY_CPAD_UP | KEY_CSTICK_UP; + keyProp[1] = KEY_DDOWN | KEY_CPAD_DOWN | KEY_CSTICK_DOWN; + keyProp[2] = KEY_DLEFT | KEY_CPAD_LEFT | KEY_CSTICK_LEFT; + keyProp[3] = KEY_DRIGHT | KEY_CPAD_RIGHT | KEY_CSTICK_RIGHT; + keyProp[4] = KEY_A | KEY_B | KEY_L | KEY_ZR; + keyProp[5] = KEY_X | KEY_Y | KEY_R | KEY_ZL; + keyProp[6] = KEY_START; + keyProp[7] = KEY_A; + keyProp[8] = KEY_B; + keyProp[9] = KEY_X; + keyProp[10] = KEY_R; + keyProp[11] = KEY_L; + bindOpt = false; + errorBut = -1; + break; + } + } + } + break; + case MENU_PAUSED: + if(!areYouSure && !areYouSureSave){ + if(pauseSaveDisplayTimer > 0) --pauseSaveDisplayTimer; + if (k_pause.clicked || k_decline.clicked) currentMenu = MENU_NONE; + if (k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection=2;} + if (k_down.clicked){ ++currentSelection; if(currentSelection > 2)currentSelection=0;} + if (k_accept.clicked){ + switch(currentSelection){ + case 0: + currentMenu = MENU_NONE; + break; + case 1: + areYouSureSave = true; + break; + case 2: + areYouSure = true; + break; + } + } + } else if(areYouSureSave) { + if (k_accept.clicked){ + pauseSaveDisplayTimer = 60; + saveCurrentWorld(currentFileName, &eManager, &player, (u8*)map, (u8*)data); + areYouSureSave = false; + areYouSure = false; + } else if (k_decline.clicked){ + areYouSureSave = false; + areYouSure = false; + } + } else { + if (k_accept.clicked){ + areYouSure = false; + areYouSureSave = false; + sf2d_set_clear_color(0xFF); + currentSelection = 0; + currentMenu = MENU_TITLE; + + playMusic(music_menu); + } else if (k_decline.clicked){ + areYouSure = false; + areYouSureSave = false; + } + } + break; + case MENU_INVENTORY: + if (k_menu.clicked || k_decline.clicked){ + currentMenu = MENU_NONE; + player.p.activeItem = &noItem; + player.p.isCarrying = false; + } + if (k_accept.clicked){ // Select item from inventory + if(player.p.inv->lastSlot!=0){ + median = player.p.inv->items[curInvSel]; // create copy of item. + removeItemFromInventory(curInvSel, player.p.inv); // remove original + pushItemToInventoryFront(median, player.p.inv); // add copy to front playerSetActiveItem(&player.p.inv->items[0]); // active item = copy. - } - currentMenu = MENU_NONE; - } - if (k_up.clicked){ --curInvSel; if(curInvSel < 0)curInvSel=player.p.inv->lastSlot-1;} - if (k_down.clicked){ ++curInvSel; if(curInvSel > player.p.inv->lastSlot-1)curInvSel=0;} - break; - */ - - case MENU_LOADGAME: - if(!enteringName && !areYouSure){ // World select - if (localInputs.k_decline.clicked){ - if(toMultiplayer) { - currentMenu = MENU_MULTIPLAYER_HOST; - } else { - currentMenu = MENU_TITLE; - currentSelection = 0; - } - } - if (localInputs.k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection = worldFileCount;} - if (localInputs.k_down.clicked){ ++currentSelection; if(currentSelection > worldFileCount)currentSelection=0;} - - if(localInputs.k_delete.clicked){ - if(currentSelection < worldFileCount) areYouSure = true; - } - - if(localInputs.k_accept.clicked){ - if(currentSelection == worldFileCount){ - - enteringName = true; - } else { - memset(¤tFileName, 0, 255); // reset currentFileName - sprintf(currentFileName, "%s.msv", fileNames[currentSelection]); - playSound(snd_test); - if(toMultiplayer) { - initMPGame = 2; - } else { - initGame = 1; - } - currentMenu = MENU_LOADING; - } - } - } else if (areYouSure){ - if (localInputs.k_decline.clicked || localInputs.k_delete.clicked) areYouSure = false; - if (localInputs.k_accept.clicked){ - sprintf(currentFileName,"%s.msv",fileNames[currentSelection]); - remove(currentFileName); - readFiles(); - enteringName = false; - areYouSure = false; - memset(¤tFileName, 0, 255); // reset currentFileName - } - } else { // Enter new world name. - if(localInputs.k_decline.clicked) enteringName = false; - if(localInputs.k_accept.clicked && errorFileName == 0){ - errorFileName = checkFileNameForErrors(); - if(errorFileName == 0){ // If no errors are found with the filename, then start a new game! - memset(¤tFileName, 0, 255); // reset currentFileName - sprintf(currentFileName, "%s.msv", fileNames[worldFileCount]); - currentMenu = MENU_LOADING; - playSound(snd_test); - if(toMultiplayer) { - initMPGame = 2; - } else { - initGame = 1; - } - ++worldFileCount; - currentMenu = MENU_LOADING; - } - } - if((localInputs.k_touch.px != 0 || localInputs.k_touch.py != 0) && touchDelay == 0){ - if(!isTouching)doTouchButton(); - } - else if(localInputs.k_touch.px == 0 || localInputs.k_touch.py == 0) isTouching = false; - if(touchDelay > 0) --touchDelay; - } - break; - case MENU_SETTINGS_TP: - - if (localInputs.k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection = tpFileCount-1;} - if (localInputs.k_down.clicked){ ++currentSelection; if(currentSelection > tpFileCount-1)currentSelection=0;} - if (localInputs.k_decline.clicked){ - if(isLoadingTP < 1){ - currentMenu = MENU_SETTINGS; - currentSelection = 1; - } - } - if (localInputs.k_accept.clicked){ - - if(currentSelection > 0){ - isLoadingTP = 4; - } else { - icons = sfil_load_PNG_buffer(icons_png, SF2D_PLACE_RAM); - reloadColors(); - font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM); - bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM); - currentMenu = MENU_SETTINGS; - currentSelection = 1; - remove("lastTP.bin"); - } - } - break; - - case MENU_SETTINGS: - if (localInputs.k_up.clicked){ - --currentSelection; - if(currentSelection == 3 && !((MODEL_3DS & 6) != 0)) --currentSelection; - if(currentSelection < 0)currentSelection=4; - } - if (localInputs.k_down.clicked){ - ++currentSelection; - if(currentSelection == 3 && !((MODEL_3DS & 6) != 0)) ++currentSelection; - if(currentSelection > 4)currentSelection=0; - } - if(localInputs.k_decline.clicked){ - currentMenu = MENU_TITLE; - currentSelection = 4; - } - if(localInputs.k_accept.clicked){ - switch(currentSelection){ - case 0: - keyProp[0] = localInputs.k_up.input; - keyProp[1] = localInputs.k_down.input; - keyProp[2] = localInputs.k_left.input; - keyProp[3] = localInputs.k_right.input; - keyProp[4] = localInputs.k_attack.input; - keyProp[5] = localInputs.k_pickup.input; - keyProp[6] = localInputs.k_use.input; - keyProp[7] = localInputs.k_menu.input; - keyProp[8] = localInputs.k_pause.input; - keyProp[9] = localInputs.k_accept.input; - keyProp[10] = localInputs.k_decline.input; - keyProp[11] = localInputs.k_delete.input; - keyProp[12] = localInputs.k_menuNext.input; - keyProp[13] = localInputs.k_menuPrev.input; - left = true; - selBut = false; - bindOpt = false; - currentSelection = 0; - currentMenu = MENU_SETTINGS_REBIND; - break; - case 1: - readTPFiles(); - currentMenu = MENU_SETTINGS_TP; - currentSelection = 0; - break; - case 2: - shouldRenderDebug = !shouldRenderDebug; // toggle option - break; - case 3: - if((MODEL_3DS & 6) != 0){ // detect if user is using a New 3DS - shouldSpeedup = !shouldSpeedup; // toggle option - osSetSpeedupEnable(shouldSpeedup); - } - break; - case 4: - if(true){ - FILE * fset = fopen("settings.bin","wb"); - fwrite(&shouldRenderDebug,sizeof(bool),1,fset); - fwrite(&shouldSpeedup,sizeof(bool),1,fset); - fclose(fset); - } - currentMenu = MENU_TITLE; - currentSelection = 2; - break; - } - } - break; - case MENU_TITLE: - //Map BG - if(menuHasMapLoaded) { - mxscr += menuxa; - myscr += menuya; - - if (mxscr < 16) { - mxscr = 16; - menuxa = -menuxa; - } else if (mxscr > 1832) { - mxscr = 1832; - menuxa = -menuxa; - } - if (myscr < 16) { - myscr = 16; - menuya = -menuya; - } else if (myscr > 1792) { - myscr = 1792; - menuya = -menuya; - } - } - - if (localInputs.k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection=6;} - if (localInputs.k_down.clicked){ ++currentSelection; if(currentSelection > 6)currentSelection=0;} - - if(localInputs.k_accept.clicked){ - switch(currentSelection){ - case 0: - toMultiplayer = false; - currentMenu = MENU_LOADGAME; - readFiles(); - currentSelection = 0; - enteringName = false; - areYouSure = false; - break; - case 1: - if(networkHost()) { - toMultiplayer = true; - currentMenu = MENU_MULTIPLAYER_HOST; - currentSelection = 0; - } - break; - case 2: - networkScan(); - currentMenu = MENU_MULTIPLAYER_JOIN; - currentSelection = 0; - menuScanTimer = 0; - break; - case 3: - sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); - currentMenu = MENU_TUTORIAL; - break; - case 4: - currentSelection = 0; - currentMenu = MENU_SETTINGS; - break; - case 5: - currentMenu = MENU_ABOUT; - break; - case 6: - quitGame = true; - break; - } - - } - break; - case MENU_TUTORIAL: - if(localInputs.k_decline.clicked){ - currentSelection = 3; - currentMenu = MENU_TITLE; - } - if(localInputs.k_menuNext.clicked){ - if(pageNum < maxPageNum){ - ++pageNum; - sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); - } - } - if(localInputs.k_menuPrev.clicked){ - if(pageNum > 0){ - --pageNum; - sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); - } - } - - break; - case MENU_MULTIPLAYER_HOST: - if (localInputs.k_decline.clicked){ - networkDisconnect(); - - currentMenu = MENU_TITLE; - currentSelection = 1; - } - - if(localInputs.k_accept.clicked){ - if(networkGetNodeCount()>1) { - currentMenu = MENU_LOADGAME; - readFiles(); - currentSelection = 0; - enteringName = false; - areYouSure = false; - } - } - break; - case MENU_MULTIPLAYER_JOIN: - if(menuScanTimer>0) { - menuScanTimer--; - } else { - networkScan(); - menuScanTimer = 30; - } - if(currentSelection >= networkGetScanCount()) currentSelection=networkGetScanCount()-1; - if(currentSelection < 0) currentSelection = 0; - - if (localInputs.k_decline.clicked){ - currentMenu = MENU_TITLE; - currentSelection = 2; - } - if (localInputs.k_up.clicked){ --currentSelection; if(currentSelection < 0) currentSelection = (networkGetScanCount()>0 ? networkGetScanCount()-1 : 0);} - if (localInputs.k_down.clicked){ ++currentSelection; if(currentSelection >= networkGetScanCount()) currentSelection=0;} - - if(localInputs.k_accept.clicked){ - if(networkGetScanCount()!=0) { - for(int t=0; t<10; t++) { //try to connect multiple times, because it will not work the first try every time - if(networkConnect(currentSelection)) { - currentMenu = MENU_MULTIPLAYER_WAIT; - currentSelection = 0; - break; - } - } - } - } - break; - case MENU_MULTIPLAYER_WAIT: - if (localInputs.k_decline.clicked){ - networkDisconnect(); - - currentMenu = MENU_TITLE; - currentSelection = 2; - } - break; - } - + } + currentMenu = MENU_NONE; + } + if (k_up.clicked){ --curInvSel; if(curInvSel < 0)curInvSel=player.p.inv->lastSlot-1;} + if (k_down.clicked){ ++curInvSel; if(curInvSel > player.p.inv->lastSlot-1)curInvSel=0;} + break; + + case MENU_CRAFTING: + if (k_menu.clicked || k_decline.clicked) currentMenu = MENU_NONE; + if (k_accept.clicked){ + int newslot = player.p.activeItem->slotNum + 1; + if(craftItem(currentRecipes, ¤tRecipes->recipes[curInvSel], player.p.inv)){ + playSound(snd_craft); + if(player.p.activeItem != &noItem)player.p.activeItem = &player.p.inv->items[newslot]; + } + } + if (k_up.clicked){ --curInvSel; if(curInvSel < 0)curInvSel=currentRecipes->size-1;} + if (k_down.clicked){ ++curInvSel; if(curInvSel > currentRecipes->size-1)curInvSel=0;} + break; + + case MENU_WIN: + if (k_accept.clicked){ + sf2d_set_clear_color(0xFF); + currentSelection = 0; + currentMenu = MENU_TITLE; + saveCurrentWorld(currentFileName, &eManager, &player, (u8*)map, (u8*)data); + + playMusic(music_menu); + } + break; + case MENU_LOSE: + if (k_accept.clicked){ + sf2d_set_clear_color(0xFF); + currentSelection = 0; + currentMenu = MENU_TITLE; + + playMusic(music_menu); + } + break; + case MENU_ABOUT: + if (k_decline.clicked) currentMenu = MENU_TITLE; + break; + + case MENU_CONTAINER: + if (k_menu.clicked || k_decline.clicked)currentMenu = MENU_NONE; + + if (k_left.clicked) { + curChestEntity->entityFurniture.r = 0; + int tmp = curInvSel; + curInvSel = curChestEntity->entityFurniture.oSel; + curChestEntity->entityFurniture.oSel = tmp; + } + if (k_right.clicked) { + curChestEntity->entityFurniture.r = 1; + int tmp = curInvSel; + curInvSel = curChestEntity->entityFurniture.oSel; + curChestEntity->entityFurniture.oSel = tmp; + } + + Inventory* i1 = curChestEntity->entityFurniture.r == 1 ? player.p.inv : curChestEntity->entityFurniture.inv; + Inventory* i2 = curChestEntity->entityFurniture.r == 0 ? player.p.inv : curChestEntity->entityFurniture.inv; + int len = i1->lastSlot; + if (curInvSel < 0) curInvSel = 0; + if (curInvSel >= len) curInvSel = len - 1; + if (k_up.clicked) --curInvSel; + if (k_down.clicked) ++curInvSel; + if (len == 0) curInvSel = 0; + if (curInvSel < 0) curInvSel += len; + if (curInvSel >= len) curInvSel -= len; + + if(k_accept.clicked && len > 0){ + Item* pullItem = &i1->items[curInvSel]; + Item pushItem = newItem(pullItem->id,pullItem->countLevel); + pushItem.chestPtr = pullItem->chestPtr; + pushItemToInventoryFront(pushItem, i2); + if(i2 == player.p.inv){ + int newslot = player.p.activeItem->slotNum + 1; + player.p.activeItem = &player.p.inv->items[newslot]; + } else if(pullItem == player.p.activeItem){ + player.p.activeItem = &noItem; + } + removeItemFromCurrentInv(pullItem); + if (curInvSel >= i1->lastSlot) curInvSel = i1->lastSlot - 1; + } + + break; + + case MENU_LOADGAME: + if(!enteringName && !areYouSure){ // World select + if (k_decline.clicked){ + currentMenu = MENU_TITLE; + currentSelection = 0; + } + if (k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection = worldFileCount;} + if (k_down.clicked){ ++currentSelection; if(currentSelection > worldFileCount)currentSelection=0;} + + if(k_delete.clicked){ + if(currentSelection < worldFileCount) areYouSure = true; + } + + if(k_accept.clicked){ + if(currentSelection == worldFileCount){ + + enteringName = true; + } else { + memset(¤tFileName, 0, 255); // reset currentFileName + sprintf(currentFileName,"%s.wld",fileNames[currentSelection]); + playSound(snd_test); + initGame = 1; + currentMenu = MENU_NONE; + } + } + } else if (areYouSure){ + if (k_decline.clicked || k_delete.clicked) areYouSure = false; + if (k_accept.clicked){ + sprintf(currentFileName,"%s.wld",fileNames[currentSelection]); + remove(currentFileName); + readFiles(); + enteringName = false; + areYouSure = false; + memset(¤tFileName, 0, 255); // reset currentFileName + } + }else { // Enter new world name. + if(k_decline.clicked) enteringName = false; + if(k_accept.clicked && errorFileName == 0){ + errorFileName = checkFileNameForErrors(); + if(errorFileName == 0){ // If no errors are found with the filename, then start a new game! + memset(¤tFileName, 0, 255); // reset currentFileName + sprintf(currentFileName,"%s.wld",fileNames[worldFileCount]); + currentMenu = MENU_NONE; + playSound(snd_test); + initGame = 2; + ++worldFileCount; + } + } + if((k_touch.px != 0 || k_touch.py != 0) && touchDelay == 0){ + if(!isTouching)doTouchButton(); + } + else if(k_touch.px == 0 || k_touch.py == 0) isTouching = false; + if(touchDelay > 0) --touchDelay; + } + break; + case MENU_SETTINGS_TP: + + if (k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection = tpFileCount-1;} + if (k_down.clicked){ ++currentSelection; if(currentSelection > tpFileCount-1)currentSelection=0;} + if (k_decline.clicked){ + if(isLoadingTP < 1){ + currentMenu = MENU_SETTINGS; + currentSelection = 1; + } + } + if (k_accept.clicked){ + + if(currentSelection > 0){ + isLoadingTP = 4; + } else { + icons = sfil_load_PNG_buffer(icons2_png, SF2D_PLACE_RAM); + reloadColors(); + font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM); + bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM); + currentMenu = MENU_SETTINGS; + currentSelection = 1; + remove("lastTP.bin"); + } + } + break; + + case MENU_SETTINGS: + if (k_up.clicked){ + --currentSelection; + if(currentSelection == 3 && !((MODEL_3DS & 6) != 0)) --currentSelection; + if(currentSelection < 0)currentSelection=4; + } + if (k_down.clicked){ + ++currentSelection; + if(currentSelection == 3 && !((MODEL_3DS & 6) != 0)) ++currentSelection; + if(currentSelection > 4)currentSelection=0; + } + if(k_decline.clicked){ + currentMenu = MENU_TITLE; + currentSelection = 2; + } + if(k_accept.clicked){ + switch(currentSelection){ + case 0: + keyProp[0] = k_up.input; + keyProp[1] = k_down.input; + keyProp[2] = k_left.input; + keyProp[3] = k_right.input; + keyProp[4] = k_attack.input; + keyProp[5] = k_menu.input; + keyProp[6] = k_pause.input; + keyProp[7] = k_accept.input; + keyProp[8] = k_decline.input; + keyProp[9] = k_delete.input; + keyProp[10] = k_menuNext.input; + keyProp[11] = k_menuPrev.input; + left = true; + selBut = false; + bindOpt = false; + currentSelection = 0; + currentMenu = MENU_SETTINGS_REBIND; + break; + case 1: + readTPFiles(); + currentMenu = MENU_SETTINGS_TP; + currentSelection = 0; + break; + case 2: + shouldRenderDebug = !shouldRenderDebug; // toggle option + break; + case 3: + if((MODEL_3DS & 6) != 0){ // detect if user is using a New 3DS + shouldSpeedup = !shouldSpeedup; // toggle option + osSetSpeedupEnable(shouldSpeedup); + } + break; + case 4: + if(true){ + FILE * fset = fopen("settings.bin","wb"); + fwrite(&shouldRenderDebug,sizeof(bool),1,fset); + fwrite(&shouldSpeedup,sizeof(bool),1,fset); + fclose(fset); + } + currentMenu = MENU_TITLE; + currentSelection = 2; + break; + } + } + break; + case MENU_TITLE: + if (k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection=4;} + if (k_down.clicked){ ++currentSelection; if(currentSelection > 4)currentSelection=0;} + + if(k_accept.clicked){ + switch(currentSelection){ + case 0: + currentMenu = MENU_LOADGAME; + readFiles(); + currentSelection = 0; + enteringName = false; + areYouSure = false; + break; + case 1: + sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); + currentMenu = MENU_TUTORIAL; + break; + case 2: + currentSelection = 0; + currentMenu = MENU_SETTINGS; + break; + case 3: + currentMenu = MENU_ABOUT; + break; + case 4: + quitGame = true; + break; + } + + } + break; + case MENU_TUTORIAL: + if(k_decline.clicked){ + currentSelection = 1; + currentMenu = MENU_TITLE; + } + if(k_menuNext.clicked){ + if(pageNum < maxPageNum){ + ++pageNum; + sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); + } + } + if(k_menuPrev.clicked){ + if(pageNum > 0){ + --pageNum; + sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); + } + } + + break; + } + } +u8 opacity = 255; +bool rev = true; char scoreText[15]; char * getButtonFunctionGame(int key){ - if(keyProp[0] & key) return "Move up"; - if(keyProp[1] & key) return "Move down"; - if(keyProp[2] & key) return "Move left"; - if(keyProp[3] & key) return "Move right"; - if(keyProp[4] & key) return "Attack"; - if(keyProp[5] & key) return "Pick up"; - if(keyProp[6] & key) return "Use"; - if(keyProp[7] & key) return "Toggle Menu"; - if(keyProp[8] & key) return "Pause"; - if(keyProp[12] & key) return "Next"; - if(keyProp[13] & key) return "Previous"; - return "Nothing"; + if(keyProp[0] & key) return "Move up"; + if(keyProp[1] & key) return "Move down"; + if(keyProp[2] & key) return "Move left"; + if(keyProp[3] & key) return "Move right"; + if(keyProp[4] & key) return "Attack"; + if(keyProp[5] & key) return "Toggle Menu"; + if(keyProp[6] & key) return "Pause"; + return "Nothing"; } char * getButtonFunctionMenu(int key){ - if(keyProp[0] & key) return "Up"; - if(keyProp[1] & key) return "Down"; - if(keyProp[2] & key) return "Left"; - if(keyProp[3] & key) return "Right"; - if(keyProp[9] & key) return "Accept"; - if(keyProp[10] & key) return "Decline"; - if(keyProp[11] & key) return "Delete"; - if(keyProp[12] & key) return "Next"; - if(keyProp[13] & key) return "Previous"; - return "Nothing"; + if(keyProp[0] & key) return "Up"; + if(keyProp[1] & key) return "Down"; + if(keyProp[2] & key) return "Left"; + if(keyProp[3] & key) return "Right"; + if(keyProp[7] & key) return "Accept"; + if(keyProp[8] & key) return "Decline"; + if(keyProp[9] & key) return "Delete"; + if(keyProp[10] & key) return "Next"; + if(keyProp[11] & key) return "Previous"; + return "Nothing"; } @@ -756,562 +730,600 @@ char guiText3[] = "Z X C V B N M"; char guiText4[] = " SPACE BACKSPACE"; void renderMenu(int menu,int xscr,int yscr){ - int i = 0; - switch(menu){ - case MENU_TUTORIAL: - sf2d_start_frame(GFX_TOP, GFX_LEFT); + int i = 0; + switch(menu){ + case MENU_TUTORIAL: + sf2d_start_frame(GFX_TOP, GFX_LEFT); sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - renderTutorialPage(true); - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + + renderTutorialPage(true); + sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - renderTutorialPage(false); - sf2d_end_frame(); - break; - case MENU_SETTINGS_TP: - offsetX = 0;offsetY = (currentSelection * 40) - 48; - sf2d_start_frame(GFX_TOP, GFX_LEFT); + + renderTutorialPage(false); + sf2d_end_frame(); + break; + case MENU_SETTINGS_TP: + offsetX = 0;offsetY = (currentSelection * 40) - 48; + sf2d_start_frame(GFX_TOP, GFX_LEFT); sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawText("Texture Packs",122,-16); - for(i = 0; i < tpFileCount; ++i){ - int color = 0xFF923232; - char * text = tpFileNames[i]; - char * cmtText = tpFileComment[i]; - if(i == 0){ - text = "Default"; - cmtText = "Regular look of the game"; - color = 0xFF921060; - } - if(i != currentSelection) color &= 0x7FFFFFFF; // Darken color. - else if(areYouSure)color = 0xFF1010DF; - - renderFrame(1,i*5,24,(i*5)+5,color); - drawText(text,(400-(strlen(text)*12))/2,i*80+16); - - if(strlen(cmtText) > 29){ - char cmtTxt1[30],cmtTxt2[30]; - strncpy(cmtTxt1, cmtText, 29); - strncpy(cmtTxt2, cmtText + 29, strlen(cmtText)-29); - drawTextColor(cmtTxt1,(400-(strlen(cmtTxt1)*12))/2,i*80+36,0xFFAFAFAF); - drawTextColor(cmtTxt2,(400-(strlen(cmtTxt2)*12))/2,i*80+50,0xFFAFAFAF); - } else { - drawTextColor(cmtText,(400-(strlen(cmtText)*12))/2,i*80+43,0xFFAFAFAF); - } - } - offsetX = 0;offsetY = 0; - if(isLoadingTP > 0){ - --isLoadingTP; - renderFrame(1,5,24,9,0xFF666666); - drawTextColor("Loading Texture pack...",(400-(23*12))/2,108,0xFF10FFFF); - if(isLoadingTP == 0){ - char fullDirName[256]; - sprintf(fullDirName,"texturepacks/%s.zip",tpFileNames[currentSelection]); - loadedtp = loadTexturePack(fullDirName); - - FILE * fs=fopen("lastTP.bin","w"); - fprintf(fs,"%s", fullDirName); - fclose(fs); - - currentMenu = MENU_SETTINGS; - currentSelection = 1; - } - } - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + + drawText("Texture Packs",122,-16); + for(i = 0; i < tpFileCount; ++i){ + int color = 0xFF923232; + char * text = tpFileNames[i]; + char * cmtText = tpFileComment[i]; + if(i == 0){ + text = "Default"; + cmtText = "Regular look of the game"; + color = 0xFF921060; + } + if(i != currentSelection) color &= 0x7FFFFFFF; // Darken color. + else if(areYouSure)color = 0xFF1010DF; + + renderFrame(1,i*5,24,(i*5)+5,color); + drawText(text,(400-(strlen(text)*12))/2,i*80+16); + + if(strlen(cmtText) > 29){ + char cmtTxt1[30],cmtTxt2[30]; + strncpy(cmtTxt1, cmtText, 29); + strncpy(cmtTxt2, cmtText + 29, strlen(cmtText)-29); + drawTextColor(cmtTxt1,(400-(strlen(cmtTxt1)*12))/2,i*80+36,0xFFAFAFAF); + drawTextColor(cmtTxt2,(400-(strlen(cmtTxt2)*12))/2,i*80+50,0xFFAFAFAF); + } else { + drawTextColor(cmtText,(400-(strlen(cmtText)*12))/2,i*80+43,0xFFAFAFAF); + } + } + offsetX = 0;offsetY = 0; + if(isLoadingTP > 0){ + --isLoadingTP; + renderFrame(1,5,24,9,0xFF666666); + drawTextColor("Loading Texture pack...",(400-(23*12))/2,108,0xFF10FFFF); + if(isLoadingTP == 0){ + char fullDirName[256]; + sprintf(fullDirName,"texturepacks/%s.zip",tpFileNames[currentSelection]); + loadedtp = loadTexturePack(fullDirName); + + FILE * fs=fopen("lastTP.bin","w"); + fprintf(fs,"%s", fullDirName); + fclose(fs); + + currentMenu = MENU_SETTINGS; + currentSelection = 1; + } + } + sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawText("Press to select", 58, 100); - renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 128, 98, 1); - drawText("Press to return", 58, 150); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 148, 1); - sf2d_end_frame(); - break; - case MENU_LOADGAME: - sf2d_start_frame(GFX_TOP, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - if(!enteringName){ // World select - offsetX = 0;offsetY = (currentSelection * 32) - 48; - drawText("Select a file",122,-16); - for(i = 0; i < worldFileCount + 1; ++i){ - int color = 0xFF921020; - char * text = fileNames[i]; - if(i == worldFileCount){ - text = "Generate New World"; - color = 0xFF209210; - } - if(i != currentSelection) color &= 0xFF7F7F7F; // Darken color. - else { - if(areYouSure)color = 0xFF1010DF; - } - - char scoreText[24]; - sprintf(scoreText,"Score: %d",fileScore[i]); - - renderFrame(1,i*4,24,(i*4)+4,color); - if(i != worldFileCount){ - drawText(text,(400-(strlen(text)*12))/2,i*64+12); - drawText(scoreText,(400-(strlen(scoreText)*12))/2,i*64+32); - } else { - drawText(text,(400-(strlen(text)*12))/2,i*64+24); - } - if(fileWin[i] && i != worldFileCount) render16(18,i*32+8,24,208,0); // Render crown - } - offsetX = 0;offsetY = 0; - } else { // Enter new world name. - drawText("Enter a name",128,16); - drawText(fileNames[worldFileCount],(400-(strlen(fileNames[worldFileCount])*12))/2, 48); - - if(errorFileName > 0){ - switch(errorFileName){// Error: Filename cannot already exist. - case 1: drawTextColor("ERROR: Length cannot be 0!",(400-26*12)/2,200,0xFF1010AF); break; - case 2: drawTextColor("ERROR: You need Letters/Numbers!",(400-32*12)/2,200,0xFF1010AF); break; - case 3: drawTextColor("ERROR: Filename already exists!",(400-31*12)/2,200,0xFF1010AF); break; - } - } - } - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - if(!enteringName){ // World select - if(!areYouSure){ - drawTextColor("Load World",100,12,0xFF3FFFFF); - drawText("Press or to scroll", 28, 50); - renderButtonIcon(localInputs.k_up.input & -localInputs.k_up.input, 98, 48, 1); - renderButtonIcon(localInputs.k_down.input & -localInputs.k_down.input, 160, 48, 1); - drawText("Press to load world", (320-21*12)/2, 100); - renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 104, 98, 1); - drawText("Press to return", 58, 150); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 148, 1); - if(currentSelection != worldFileCount){ - drawText("Press to delete",(320-17*12)/2, 200); - renderButtonIcon(localInputs.k_delete.input & -localInputs.k_delete.input, 128, 198, 1); - } - } else { - drawTextColor("Delete File?",88,12,0xFF3F3FFF); - drawText("Press to confirm", (320-18*12)/2, 100); - renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 122, 98, 1); - drawText("Press to return", 58, 150); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 148, 1); - } - - } else { // Draw the "keyboard" - drawTextColor("Touch the keypad below",(320-22*12)/2,12,0xFF33FFFF); - - sf2d_draw_rectangle(0, 50, 320, 110, 0xFF7F7FBF); - - if(touchDelay > 0){ - sf2d_draw_rectangle(touchX, touchY, touchW, touchH, 0xFF0000AF); - } - - drawSizedText(guiText0,4, 60, 2); - drawSizedText(guiText1,4, 80, 2); - drawSizedText(guiText2,12, 100, 2); - drawSizedText(guiText3,28, 120, 2); - drawSizedText(guiText4,12, 140, 2); - - drawText("Press to confirm", (320-18*12)/2, 180); - renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 122, 178, 1); - drawText("Press to return", 58, 210); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 208, 1); - } - sf2d_end_frame(); - break; - case MENU_SETTINGS_REBIND: - sf2d_start_frame(GFX_TOP, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawTextColor("Rebind Buttons",116,12,0xFF00AFAF); - drawText("Button",16,32); - drawText("Game",140,32); - drawText("Menus",280,32); - - char gameButText[34]; - char menuButText[34]; - - for(i = 0; i < 5; ++i){ - if((currentSelection-2) + i > 21 || (currentSelection-2) + i < 0) continue; - renderButtonIcon(keys[(currentSelection-2) + i], 16, (i * 18) + 30, 2); - int ccol = 0xFF7F7F7F; - - sprintf(gameButText,"%s",getButtonFunctionGame(keys[(currentSelection-2) + i])); - sprintf(menuButText,"%s",getButtonFunctionMenu(keys[(currentSelection-2) + i])); - - if(i == 2){ - if(!selBut)ccol = 0xFFFFFFFF; - else{ - ccol = 0xFF00FF00; - if(left)sprintf(gameButText,"<%s>",getButtonFunctionGame(keys[(currentSelection-2) + i])); - else sprintf(menuButText,"<%s>",getButtonFunctionMenu(keys[(currentSelection-2) + i])); - } - } - if(left){ - drawTextColor(gameButText, 112, (i * 33) + 80, ccol); - drawTextColor(menuButText, 280, (i * 33) + 80, 0xFF7F7F7F); - } else { - drawTextColor(gameButText, 112, (i * 33) + 80, 0xFF7F7F7F); - drawTextColor(menuButText, 280, (i * 33) + 80, ccol); - } - } - if(bindOpt){ - renderFrame(1,1,24,14,0xFFBF1010); - drawTextColor("Save changes?",122,32,0xFF00AFAF); - for(i = 2; i >= 0; --i){ - char* msg = keybOptions[i]; - u32 color = 0xFF4F4F4F; - if(i == curSaveSel) color = 0xFFFFFFFF; - drawTextColor(msg,(400 - (strlen(msg) * 12))/2, (i * 24) + 92, color); - } - drawText("Press to return", 98, 190); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 168, 188, 1); - - if(errorBut >= 0 && errorBut < 14){ - char errorText[30]; - switch(errorBut){ - case 0: sprintf(errorText, "Error: Missing 'Move up'"); break; - case 1: sprintf(errorText, "Error: Missing 'Move down'"); break; - case 2: sprintf(errorText, "Error: Missing 'Move right'"); break; - case 3: sprintf(errorText, "Error: Missing 'Move left'"); break; - case 4: sprintf(errorText, "Error: Missing 'Attack'"); break; - case 5: sprintf(errorText, "Error: Missing 'Pick up'"); break; - case 6: sprintf(errorText, "Error: Missing 'Use'"); break; - case 7: sprintf(errorText, "Error: Missing 'Toggle Menu'"); break; - case 8: sprintf(errorText, "Error: Missing 'Pause'"); break; - case 9: sprintf(errorText, "Error: Missing 'Accept'"); break; - case 10: sprintf(errorText, "Error: Missing 'Decline'"); break; - case 11: sprintf(errorText, "Error: Missing 'Delete'"); break; - case 12: sprintf(errorText, "Error: Missing 'Next'"); break; - case 13: sprintf(errorText, "Error: Missing 'Previous'"); break; - } - drawTextColor(errorText,(400 - (strlen(errorText) * 12))/2,50,0xFF0000FF); - } - - } - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - if(!selBut){ - drawText("Press to select", 58, 80); - renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 128, 78, 1); - drawText("Press to return", 58, 130); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 128, 1); - } else { - drawText("Press or to scroll", 28, 50); - renderButtonIcon(localInputs.k_left.input & -localInputs.k_left.input, 98, 48, 1); - renderButtonIcon(localInputs.k_right.input & -localInputs.k_right.input, 160, 48, 1); - drawText("Press to unselect", 46, 100); - renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 118, 98, 1); - drawText("Press to return", 58, 150); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 148, 1); - } - sf2d_end_frame(); - break; - - case MENU_ABOUT: - sf2d_start_frame(GFX_TOP, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawText("About Minicraft",110,12); - drawSizedText("Minicraft was made by Markus Persson for the",24,36,1.0); - drawSizedText("22'nd ludum dare competition in december 2011.",16,48,1.0); - drawSizedText("it is dedicated to my father. <3",72,60,1.0); - drawSizedText("- Markus \"Notch\" Persson",104,76,1.0); - - drawTextColor("3DS Homebrew Edition",74,120,0xFF00FF00); - drawSizedTextColor("This port was made by David Benepe (Davideesk)",16,144,1.0,0xFF00FF00); - drawSizedTextColor("just for fun in September/October 2015.",44,156,1.0,0xFF00FF00); - drawSizedTextColor("Modded by Andre Schweiger (andre111) and ",44,168,1.0,0xFF00FF00); - drawSizedTextColor("Elijah Bansley (ElijahZAwesome)",71,180,1.0,0xFF00FF00); - drawSizedTextColor("TY Notch for creating a fun game to remake!",28,192,1.0,0xFF00FF00); - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawTextColor("Special Thanks to:",52,12,0xFF7F7FFF); - drawTextColor("Smea",136,50,0xFF2020FF); - drawSizedTextColor("for ctrulib",116,70,1.0,0xFF2020FF); - drawTextColor("Xerpi",130,100,0xFFFF2020); - drawSizedTextColor("for sf2dlib",116,120,1.0,0xFFFF2020); - drawTextColor("Music from",100,150,0xFF20FF20); - drawSizedTextColor("opengameart.org/content/",64,170,1.0,0xFF20FF20); - drawSizedTextColor("generic-8-bit-jrpg-soundtrack",48,180,1.0,0xFF20FF20); - - drawText("Press to return", 58, 220); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 218, 1); - sf2d_end_frame(); - break; - case MENU_SETTINGS: - sf2d_start_frame(GFX_TOP, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawText("Settings",(400-(8*12))/2,30); - for(i = 4; i >= 0; --i){ - char* msg = setOptions[i]; - u32 color = 0xFF7F7F7F; - if(i == currentSelection) color = 0xFFFFFFFF; - if(i == 2){ - if(shouldRenderDebug) drawSizedTextColor("On",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF00DF00); - else drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF0000DF); - } else if(i == 3){ - - if((MODEL_3DS & 6) != 0){ // detect if user is using a New 3DS - if(shouldSpeedup) drawSizedTextColor("On",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF00DF00); - else drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF0000DF); - } else { - color = 0xFF3F3F3F; - drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF3F3F3F); - } - } - drawSizedTextColor(msg,(200 - (strlen(msg) * 8))/2, ((8 + i) * 32 - 190) >> 1,2.0, color); - } - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - switch(currentSelection){ - case 0: - drawTextColor("Change the controls",(320 - (19 * 12))/2,24,0xFF7FFFFF); - break; - case 1: - drawTextColor("Change the game's art",(320 - (21 * 12))/2,24,0xFF7FFFFF); - break; - case 2: - drawTextColor("Enable Testing Features.",(320 - (22 * 12))/2,24,0xFF7FFFFF); - break; - case 3: - drawTextColor("Use the N3DS 804mhz mode",(320 - (24 * 12))/2,24,0xFF7FFFFF); - break; - case 4: - drawTextColor("Back to the titlescreen",(320 - (23 * 12))/2,24,0xFF7FFFFF); - break; - } - drawText("Press to select", 58, 100); - renderButtonIcon(localInputs.k_accept.input & -localInputs.k_accept.input, 128, 98, 1); - drawText("Press to return", 58, 150); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 148, 1); - sf2d_end_frame(); - break; - case MENU_TITLE: - /* Top Screen */ - sf2d_start_frame(GFX_TOP, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - //map BG - if(menuHasMapLoaded) { - offsetX = (int) mxscr; offsetY = (int) myscr; - renderBackground(1, (int) mxscr, (int) myscr); - offsetX = 0; offsetY = 0; - - sf2d_draw_rectangle(0, 0, 400, 240, 0xAA0C0C0C); //You might think "real" black would be better, but it actually looks better that way - } - - renderTitle(76,8); - - for(i = 6; i >= 0; --i){ - char* msg = options[i]; - u32 color = 0xFF7F7F7F; - if(i == currentSelection) color = 0xFFFFFFFF; - drawSizedTextColor(msg,((200 - (strlen(msg) * 8))/2) + 1, (((8 + i) * 20 - 74) >> 1) + 1,2.0, 0xFF000000); - drawSizedTextColor(msg,(200 - (strlen(msg) * 8))/2, ((8 + i) * 20 - 74) >> 1,2.0, color); - } - - drawText(versionText,2,225); - sf2d_end_frame(); - - /* Bottom Screen */ - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - //map BG - if(menuHasMapLoaded) { - offsetX = (int) mxscr + 20; offsetY = (int) myscr + 120; - renderBackground(1, (int) mxscr + 20, (int) myscr + 120); - offsetX = 0; offsetY = 0; - - sf2d_draw_rectangle(0, 0, 320, 240, 0xAA0C0C0C); //You might think "real" black would be better, but it actually looks better that way - } - - int startX = 0, startY = 0;// relative coordinates ftw - switch(currentSelection){ - case 0: // "Start Game" - break; - case 1: // "Host Game" - drawTextColor("Host local multiplayer",(320 - (22 * 12))/2,24,0xFF7FFFFF); - break; - case 2: // "Join Game" - drawTextColor("Join local multiplayer",(320 - (22 * 12))/2,24,0xFF7FFFFF); - break; - case 3: // "How To Play" - startX = 72;startY = 54; - render16(startX,startY,96,208,0);//C-PAD - startX = 72;startY = 37; - render16(startX,startY-16,16,112,0);//Player - render16(startX,startY,112,208,0);//C-PAD up - startX = 72;startY = 71; - render16(startX,startY+16,0,112,0);//Player - render16(startX,startY,144,208,0);//C-PAD down - startX = 39;startY = 54; - render16(startX,startY,48,112,1);//Player - render16(startX+16,startY,128,208,0);//C-PAD left - startX = 89;startY = 54; - render16(startX+16,startY,48,112,0);//Player - render16(startX,startY,160,208,0);//C-PAD right - drawTextColor("Learn the basics",64,24,0xFF7FFFFF); - break; - case 4: // "Settings" - drawTextColor("Modify the game's feel",(320 - (22 * 12))/2,24,0xFF7FFFFF); - renderc(48,48,0,112,64,32,0); - break; - case 5: // "About" - drawTextColor("Who made this game?",(320 - (19 * 12))/2,24,0xFF7FFFFF); - - // Secret code ;) - //drawSizedText("497420776173206e6f746368",(320 - (24 * 8))/2,80,1); - //drawSizedText("506f727465642062792044617669646565736b",(320 - (38 * 8))/2,88,1); - //drawSizedText("576879207265616420746869733f",(320 - (28 * 8))/2,96,1); - //drawSizedText("596f75207761737465642074696d65",(320 - (30 * 8))/2,104,1); - //drawSizedText("4861204861204861204861204861",(320 - (28 * 8))/2,112,1); - //drawSizedText("5468652063616b652069732061206c6965",(320 - (34 * 8))/2,120,1); - //drawSizedText("4044617669646565736b2074776974746572",(320 - (36 * 8))/2,128,1); - //drawSizedText("3533363536333732363537343231",(320 - (28 * 8))/2,136,1); - //drawSizedText("4c69617220746578742062656c6f77",(320 - (30 * 8))/2,144,1); - //drawSizedText("(Totally not a secret code or anything)",4,160,1); - - break; - case 6: // "Exit" - drawTextColor("Exit to the home menu",(320 - (21 * 12))/2,24,0xFF7FFFFF); - drawTextColor("(bye-bye)",(320 - (9 * 12))/2,100,0xFF7FFFFF); - break; - } - sf2d_end_frame(); - break; - case MENU_MULTIPLAYER_HOST: - sf2d_start_frame(GFX_TOP, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - networkUpdateStatus(); - drawText("Connected Players",98,8); - int j = 0; - int lastj = 0; - for(i = 0; i 0){ + switch(errorFileName){// Error: Filename cannot already exist. + case 1: drawTextColor("ERROR: Length cannot be 0!",(400-26*12)/2,200,0xFF1010AF); break; + case 2: drawTextColor("ERROR: You need Letters/Numbers!",(400-32*12)/2,200,0xFF1010AF); break; + case 3: drawTextColor("ERROR: Filename already exists!",(400-31*12)/2,200,0xFF1010AF); break; + } } - drawText("Waiting for host to start",(400-25*12)/2,3*26+32); - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); - sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawText("Awaiting game start..", (320-21*12)/2, 100); - drawText("Press to return", 58, 150); - renderButtonIcon(localInputs.k_decline.input & -localInputs.k_decline.input, 128, 148, 1); - sf2d_end_frame(); - break; - case MENU_LOADING: - sf2d_start_frame(GFX_TOP, GFX_LEFT); + } + sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + + if(!enteringName){ // World select + if(!areYouSure){ + drawTextColor("Load World",100,12,0xFF3FFFFF); + drawText("Press or to scroll", 28, 50); + renderButtonIcon(k_up.input & -k_up.input, 98, 48, 1); + renderButtonIcon(k_down.input & -k_down.input, 160, 48, 1); + drawText("Press to load world", (320-21*12)/2, 100); + renderButtonIcon(k_accept.input & -k_accept.input, 104, 98, 1); + drawText("Press to return", 58, 150); + renderButtonIcon(k_decline.input & -k_decline.input, 128, 148, 1); + if(currentSelection != worldFileCount){ + drawText("Press to delete",(320-17*12)/2, 200); + renderButtonIcon(k_delete.input & -k_delete.input, 128, 198, 1); + } + } else { + drawTextColor("Delete File?",88,12,0xFF3F3FFF); + drawText("Press to confirm", (320-18*12)/2, 100); + renderButtonIcon(k_accept.input & -k_accept.input, 122, 98, 1); + drawText("Press to return", 58, 150); + renderButtonIcon(k_decline.input & -k_decline.input, 128, 148, 1); + } + + } else { // Draw the "keyboard" + drawTextColor("Touch the keypad below",(320-22*12)/2,12,0xFF33FFFF); + + sf2d_draw_rectangle(0, 50, 320, 110, 0xFF7F7FBF); + + if(touchDelay > 0){ + sf2d_draw_rectangle(touchX, touchY, touchW, touchH, 0xFF0000AF); + } + + drawSizedText(guiText0,4, 60, 2); + drawSizedText(guiText1,4, 80, 2); + drawSizedText(guiText2,12, 100, 2); + drawSizedText(guiText3,28, 120, 2); + drawSizedText(guiText4,12, 140, 2); + + drawText("Press to confirm", (320-18*12)/2, 180); + renderButtonIcon(k_accept.input & -k_accept.input, 122, 178, 1); + drawText("Press to return", 58, 210); + renderButtonIcon(k_decline.input & -k_decline.input, 128, 208, 1); + } + sf2d_end_frame(); + break; + case MENU_SETTINGS_REBIND: + sf2d_start_frame(GFX_TOP, GFX_LEFT); sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + + drawTextColor("Rebind Buttons",116,12,0xFF00AFAF); + drawText("Button",16,32); + drawText("Game",140,32); + drawText("Menus",280,32); + + char gameButText[34]; + char menuButText[34]; + + for(i = 0; i < 5; ++i){ + if((currentSelection-2) + i > 21 || (currentSelection-2) + i < 0) continue; + renderButtonIcon(keys[(currentSelection-2) + i], 16, (i * 18) + 30, 2); + int ccol = 0xFF7F7F7F; + + sprintf(gameButText,"%s",getButtonFunctionGame(keys[(currentSelection-2) + i])); + sprintf(menuButText,"%s",getButtonFunctionMenu(keys[(currentSelection-2) + i])); + + if(i == 2){ + if(!selBut)ccol = 0xFFFFFFFF; + else{ + ccol = 0xFF00FF00; + if(left)sprintf(gameButText,"<%s>",getButtonFunctionGame(keys[(currentSelection-2) + i])); + else sprintf(menuButText,"<%s>",getButtonFunctionMenu(keys[(currentSelection-2) + i])); + } + } + if(left){ + drawTextColor(gameButText, 112, (i * 33) + 80, ccol); + drawTextColor(menuButText, 280, (i * 33) + 80, 0xFF7F7F7F); + } else { + drawTextColor(gameButText, 112, (i * 33) + 80, 0xFF7F7F7F); + drawTextColor(menuButText, 280, (i * 33) + 80, ccol); + } + } + if(bindOpt){ + renderFrame(1,1,24,14,0xFFBF1010); + drawTextColor("Save changes?",122,32,0xFF00AFAF); + for(i = 2; i >= 0; --i){ + char* msg = keybOptions[i]; + u32 color = 0xFF4F4F4F; + if(i == curSaveSel) color = 0xFFFFFFFF; + drawTextColor(msg,(400 - (strlen(msg) * 12))/2, (i * 24) + 92, color); + } + drawText("Press to return", 98, 190); + renderButtonIcon(k_decline.input & -k_decline.input, 168, 188, 1); + + if(errorBut >= 0 && errorBut < 12){ + char errorText[30]; + switch(errorBut){ + case 0: sprintf(errorText, "Error: Missing 'Move up'"); break; + case 1: sprintf(errorText, "Error: Missing 'Move down'"); break; + case 2: sprintf(errorText, "Error: Missing 'Move right'"); break; + case 3: sprintf(errorText, "Error: Missing 'Move left'"); break; + case 4: sprintf(errorText, "Error: Missing 'Attack'"); break; + case 5: sprintf(errorText, "Error: Missing 'Toggle Menu'"); break; + case 6: sprintf(errorText, "Error: Missing 'Pause'"); break; + case 7: sprintf(errorText, "Error: Missing 'Accept'"); break; + case 8: sprintf(errorText, "Error: Missing 'Decline'"); break; + case 9: sprintf(errorText, "Error: Missing 'Delete'"); break; + case 10: sprintf(errorText, "Error: Missing 'Next'"); break; + case 11: sprintf(errorText, "Error: Missing 'Previous'"); break; + } + drawTextColor(errorText,(400 - (strlen(errorText) * 12))/2,50,0xFF0000FF); + } + + } + sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way - - drawText("Loading game...", (320-15*12)/2, 100); - sf2d_end_frame(); - break; - } + + if(!selBut){ + drawText("Press to select", 58, 80); + renderButtonIcon(k_accept.input & -k_accept.input, 128, 78, 1); + drawText("Press to return", 58, 130); + renderButtonIcon(k_decline.input & -k_decline.input, 128, 128, 1); + } else { + drawText("Press or to scroll", 28, 50); + renderButtonIcon(k_left.input & -k_left.input, 98, 48, 1); + renderButtonIcon(k_right.input & -k_right.input, 160, 48, 1); + drawText("Press to unselect", 46, 100); + renderButtonIcon(k_accept.input & -k_accept.input, 118, 98, 1); + drawText("Press to return", 58, 150); + renderButtonIcon(k_decline.input & -k_decline.input, 128, 148, 1); + } + sf2d_end_frame(); + break; + + case MENU_PAUSED: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + if(currentLevel == 0){ + sf2d_draw_texture_part_scale(minimap[1],(-xscr/3)-256,(-yscr/3)-32,0,0,128,128,12.5,7.5); + sf2d_draw_rectangle(0,0,400,240, 0xAFDFDFDF); + } + offsetX = xscr;offsetY = yscr; + renderMenuBackground(xscr,yscr); + offsetX = 0;offsetY = 0; + renderFrame(1,1,24,14,0xFF1010AF); + drawText("Paused",164,32); + for(i = 2; i >= 0; --i){ + char* msg = pOptions[i]; + u32 color = 0xFF7F7F7F; + if(i == currentSelection) color = 0xFFFFFFFF; + drawTextColor(msg,(400 - (strlen(msg) * 12))/2, (i * 24) + 100, color); + } + + if(pauseSaveDisplayTimer > 0) drawTextColor("Game Saved!", (400-(11*12))/2, 64,0xFF20FF20); + + if(areYouSure || areYouSureSave){ + if(areYouSure)renderFrame(6,5,19,10,0xFF10108F); + else renderFrame(6,5,19,10,0xFF108F10); + + drawText("Are you sure?",122,96); + drawText(" Yes", 164, 117); + renderButtonIcon(k_accept.input & -k_accept.input, 166, 114, 1); + drawText(" No", 170, 133); + renderButtonIcon(k_decline.input & -k_decline.input, 166, 130, 1); + } + + sf2d_end_frame(); + break; + case MENU_WIN: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + if(currentLevel == 0){ + sf2d_draw_texture_part_scale(minimap[1],(-xscr/3)-256,(-yscr/3)-32,0,0,128,128,12.5,7.5); + sf2d_draw_rectangle(0,0,400,240, 0xAFDFDFDF); + } + offsetX = xscr;offsetY = yscr; + renderMenuBackground(xscr,yscr); + offsetX = 0;offsetY = 0; + 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", player.p.score); + drawTextColor("You Win!",158,76,0x0000AFAF + (opacity << 24)); + drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100); + drawText("Press to continue", 96, 150); + renderButtonIcon(k_attack.input & -k_attack.input, 166, 148, 1); + + //printf("0x%08X",k_attack.input & -k_attack.input); + sf2d_end_frame(); + break; + case MENU_LOSE: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + if(currentLevel == 0){ + sf2d_draw_texture_part_scale(minimap[1],(-xscr/3)-256,(-yscr/3)-32,0,0,128,128,12.5,7.5); + sf2d_draw_rectangle(0,0,400,240, 0xAFDFDFDF); + } + offsetX = xscr;offsetY = yscr; + renderMenuBackground(xscr,yscr); + offsetX = 0;offsetY = 0; + 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", player.p.score); + drawTextColor("You DIED!",158,76,0x000000AF + (opacity << 24)); + drawText(scoreText, 200-((strlen(scoreText)-1)*6), 100); + drawText("Press to continue", 96, 150); + renderButtonIcon(k_attack.input & -k_attack.input, 166, 148, 1); + //printf("0x%08X",k_attack.input & -k_attack.input); + sf2d_end_frame(); + break; + case MENU_INVENTORY: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + if(currentLevel == 0){ + sf2d_draw_texture_part_scale(minimap[1],(-xscr/3)-256,(-yscr/3)-32,0,0,128,128,12.5,7.5); + sf2d_draw_rectangle(0,0,400,240, 0xAFDFDFDF); + } + offsetX = xscr;offsetY = yscr; + renderMenuBackground(xscr,yscr); + offsetX = 0;offsetY = 0; + renderFrame(1,1,24,14,0xFFFF1010); + renderItemList(player.p.inv, 1,1,24,14, curInvSel); + sf2d_end_frame(); + break; + case MENU_CRAFTING: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + if(currentLevel == 0){ + sf2d_draw_texture_part_scale(minimap[1],(-xscr/3)-256,(-yscr/3)-32,0,0,128,128,12.5,7.5); + sf2d_draw_rectangle(0,0,400,240, 0xAFDFDFDF); + } + offsetX = xscr;offsetY = yscr; + renderMenuBackground(xscr,yscr); + offsetX = 0;offsetY = 0; + + renderFrame(15,1,24,4,0xFFFF1010); + renderFrame(15,5,24,14,0xFFFF1010); + renderFrame(1,1,14,14,0xFFFF1010); + renderRecipes(currentRecipes, 1, 1, 14, 14, curInvSel); + + Recipe* rec = ¤tRecipes->recipes[curInvSel]; + renderItemIcon(rec->itemResult,rec->itemAmountLevel,128,16); + char craftText[12]; + sprintf(craftText,"%d",countItemInv(rec->itemResult,rec->itemAmountLevel, player.p.inv)); + 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, player.p.inv); + int ttlCst = rec->costs[i].costAmount; + int col = 0xFFFFFFFF; if(amntcosts[i].costItem,1,128,48+(i*8)); + sprintf(craftText,"%d/%d",amnt,ttlCst); + drawTextColor(craftText,274,96+(i*18),col); + } + } + + sf2d_end_frame(); + break; + + case MENU_CONTAINER: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + if(currentLevel == 0){ + sf2d_draw_texture_part_scale(minimap[1],(-xscr/3)-256,(-yscr/3)-32,0,0,128,128,12.5,7.5); + sf2d_draw_rectangle(0,0,400,240, 0xAFDFDFDF); + } + offsetX = xscr;offsetY = yscr; + renderMenuBackground(xscr,yscr); + if (curChestEntity->entityFurniture.r == 1){ offsetX = 48;offsetY = 0;} + else {offsetX = 0;offsetY = 0;} + + renderFrame(1,1,14,14,0xFFFF1010); + renderItemList(curChestEntity->entityFurniture.inv,1,1,14,14, + curChestEntity->entityFurniture.r == 0 ? curInvSel : -curChestEntity->entityFurniture.oSel - 1); + renderFrame(15,1,28,14,0xFFFF1010); + renderItemList(player.p.inv,15,1,28,14, + curChestEntity->entityFurniture.r == 1 ? curInvSel : -curChestEntity->entityFurniture.oSel - 1); + offsetX = 0;offsetY = 0; + sf2d_end_frame(); + break; + + case MENU_ABOUT: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + + drawText("About Minicraft",110,12); + drawSizedText("Minicraft was made by Markus Persson for the",24,36,1.0); + drawSizedText("22'nd ludum dare competition in december 2011.",16,48,1.0); + drawSizedText("it is dedicated to my father. <3",72,60,1.0); + drawSizedText("- Markus \"Notch\" Persson",104,76,1.0); + + drawTextColor("3DS Homebrew Edition",74,120,0xFF00FF00); + drawSizedTextColor("This port was made by David Benepe (Davideesk)",16,144,1.0,0xFF00FF00); + drawSizedTextColor("just for fun in September/October 2015.",44,156,1.0,0xFF00FF00); + drawSizedTextColor("Updated and modded by Andre Schweiger (andre111)",8,168,1.0,0xFF00FF00); + drawSizedTextColor("TY Notch for creating a fun game to remake!",28,192,1.0,0xFF00FF00); + sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + + drawTextColor("Special Thanks to:",52,12,0xFF7F7FFF); + drawTextColor("Smea",136,50,0xFF2020FF); + drawSizedTextColor("for ctrulib",116,70,1.0,0xFF2020FF); + drawTextColor("Xerpi",130,100,0xFFFF2020); + drawSizedTextColor("for sf2dlib",116,120,1.0,0xFFFF2020); + drawTextColor("Music from",100,150,0xFF20FF20); + drawSizedTextColor("opengameart.org/content/",64,170,1.0,0xFF20FF20); + drawSizedTextColor("generic-8-bit-jrpg-soundtrack",48,180,1.0,0xFF20FF20); + + drawText("Press to return", 58, 220); + renderButtonIcon(k_decline.input & -k_decline.input, 128, 218, 1); + sf2d_end_frame(); + break; + case MENU_SETTINGS: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + + drawText("Settings",(400-(8*12))/2,30); + for(i = 4; i >= 0; --i){ + char* msg = setOptions[i]; + u32 color = 0xFF7F7F7F; + if(i == currentSelection) color = 0xFFFFFFFF; + if(i == 2){ + if(shouldRenderDebug) drawSizedTextColor("On",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF00DF00); + else drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF0000DF); + } else if(i == 3){ + + if((MODEL_3DS & 6) != 0){ // detect if user is using a New 3DS + if(shouldSpeedup) drawSizedTextColor("On",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF00DF00); + else drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF0000DF); + } else { + color = 0xFF3F3F3F; + drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xFF3F3F3F); + } + } + drawSizedTextColor(msg,(200 - (strlen(msg) * 8))/2, ((8 + i) * 32 - 190) >> 1,2.0, color); + } + sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + + switch(currentSelection){ + case 0: + drawTextColor("Change the controls",(320 - (19 * 12))/2,24,0xFF7FFFFF); + break; + case 1: + drawTextColor("Change the game's art",(320 - (21 * 12))/2,24,0xFF7FFFFF); + break; + case 2: + drawTextColor("Show FPS/Pos/Entities",(320 - (22 * 12))/2,24,0xFF7FFFFF); + break; + case 3: + drawTextColor("Use the N3DS 804mhz mode",(320 - (24 * 12))/2,24,0xFF7FFFFF); + break; + case 4: + drawTextColor("Back to the titlescreen",(320 - (23 * 12))/2,24,0xFF7FFFFF); + break; + } + drawText("Press to select", 58, 100); + renderButtonIcon(k_accept.input & -k_accept.input, 128, 98, 1); + drawText("Press to return", 58, 150); + renderButtonIcon(k_decline.input & -k_decline.input, 128, 148, 1); + sf2d_end_frame(); + break; + case MENU_TITLE: + /* Top Screen */ + sf2d_start_frame(GFX_TOP, GFX_LEFT); + sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + + renderTitle(76,16); + + for(i = 4; i >= 0; --i){ + char* msg = options[i]; + u32 color = 0xFF7F7F7F; + if(i == currentSelection) color = 0xFFFFFFFF; + drawSizedTextColor(msg,(200 - (strlen(msg) * 8))/2, ((8 + i) * 20 - 50) >> 1,2.0, color); + } + + drawText(versionText,2,225); + sf2d_end_frame(); + + /* Bottom Screen */ + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + + int startX = 0, startY = 0;// relative coordinates ftw + switch(currentSelection){ + case 0: // "Start Game" + startX = 20;startY = 50; + render16(startX,startY+12,0,128,0);//Player(Carrying) + render16(startX,startY,128,128,0);//Workbench + startX = 120;startY = 20; + menuRenderTilePit(startX,startY,176,16,waterColor[0]);// water pit + renderc (startX+8,startY+12,48,160,16,8,0);//Waves + renderc (startX+8,startY+8,0,112,16,8,0);//Player (Top-Half) + startX = 110;startY = 76; + render16 (startX,startY,48,112,0);//Player + renderc (startX+12,startY,40,160,8,16,0);//Slash + render (startX+14,startY+4,152,144,0);//Pickaxe + render16b(startX+18,startY,80,0,0,0xFFAEC6DC);//Iron ore + startX = 40;startY = 90; + render16b (startX,startY,128,112,0,0xFFADFFAD);//Slime + render16 (startX+18,startY,48,112,1);//Player (Mirrored) + renderc (startX+14,startY,32,160,8,16,0);//Slash + render (startX+12,startY+4,104,144,1);//Sword + startX = 64;startY = 40; + menuRenderTilePit(startX,startY,112,16,grassColor);// grass pit + render16 (startX+8,startY+4,0,16,0);//Tree + render (startX+1,startY+14,80,152,0);// Apple + render16 (startX+9,startY+18,16,112,0);//Player + renderc (startX+9,startY+14,16,160,16,8,0);//Slash + drawTextColor("Play minicraft",24,24,0xFF7FFFFF); + break; + case 1: // "How To Play" + startX = 72;startY = 54; + render16(startX,startY,96,208,0);//C-PAD + startX = 72;startY = 37; + render16(startX,startY-16,16,112,0);//Player + render16(startX,startY,112,208,0);//C-PAD up + startX = 72;startY = 71; + render16(startX,startY+16,0,112,0);//Player + render16(startX,startY,144,208,0);//C-PAD down + startX = 39;startY = 54; + render16(startX,startY,48,112,1);//Player + render16(startX+16,startY,128,208,0);//C-PAD left + startX = 89;startY = 54; + render16(startX+16,startY,48,112,0);//Player + render16(startX,startY,160,208,0);//C-PAD right + + drawTextColor("Learn the basics",64,24,0xFF7FFFFF); + break; + case 2: // "Settings" + drawTextColor("Modify the game's feel",(320 - (22 * 12))/2,24,0xFF7FFFFF); + renderc(48,48,0,112,64,32,0); + break; + case 3: // "About" + drawTextColor("Who made this game?",(320 - (19 * 12))/2,24,0xFF7FFFFF); + + // Secret code ;) + //drawSizedText("497420776173206e6f746368",(320 - (24 * 8))/2,80,1); + //drawSizedText("506f727465642062792044617669646565736b",(320 - (38 * 8))/2,88,1); + //drawSizedText("576879207265616420746869733f",(320 - (28 * 8))/2,96,1); + //drawSizedText("596f75207761737465642074696d65",(320 - (30 * 8))/2,104,1); + //drawSizedText("4861204861204861204861204861",(320 - (28 * 8))/2,112,1); + //drawSizedText("5468652063616b652069732061206c6965",(320 - (34 * 8))/2,120,1); + //drawSizedText("4044617669646565736b2074776974746572",(320 - (36 * 8))/2,128,1); + //drawSizedText("3533363536333732363537343231",(320 - (28 * 8))/2,136,1); + //drawSizedText("4c69617220746578742062656c6f77",(320 - (30 * 8))/2,144,1); + //drawSizedText("(Totally not a secret code or anything)",4,160,1); + + break; + case 4: // "Exit" + drawTextColor("Exit to the homebrew menu",(320 - (25 * 12))/2,24,0xFF7FFFFF); + drawTextColor("(bye-bye)",(320 - (9 * 12))/2,100,0xFF7FFFFF); + break; + } + sf2d_end_frame(); + break; + } } -void menuRenderTilePit(int x,int y,int xt,int yt) { - render16(x+8,y+8,xt+48,yt,0); - - render(x, y, xt, yt, 0); - render(x+24,y, xt+8, yt, 0); - render(x, y+24,xt, yt+8,0); - render(x+24,y+24,xt+8, yt+8,0); - - render(x+8, y, xt+16,yt, 0); - render(x+16,y, xt+24,yt, 0); - render(x+8, y+24,xt+16,yt+8,0); - render(x+16,y+24,xt+24,yt+8,0); - - render(x, y+8, xt+32,yt, 0); - render(x, y+16,xt+32,yt, 0); - render(x+24,y+8, xt+40,yt, 0); - render(x+24,y+16,xt+40,yt, 0); +void menuRenderTilePit(int x,int y,int xt,int yt,u32 color) { + render16b(x+8,y+8,xt+48,yt,0,color); + + renderb(x, y, xt, yt, 0,color); + renderb(x+24,y, xt+8, yt, 0,color); + renderb(x, y+24,xt, yt+8,0,color); + renderb(x+24,y+24,xt+8, yt+8,0,color); + + renderb(x+8, y, xt+16,yt, 0,color); + renderb(x+16,y, xt+24,yt, 0,color); + renderb(x+8, y+24,xt+16,yt+8,0,color); + renderb(x+16,y+24,xt+24,yt+8,0,color); + + renderb(x, y+8, xt+32,yt, 0,color); + renderb(x, y+16,xt+32,yt, 0,color); + renderb(x+24,y+8, xt+40,yt, 0,color); + renderb(x+24,y+16,xt+40,yt, 0,color); } diff --git a/source/Menu.h b/source/Menu.h old mode 100755 new mode 100644 index ca0c38b..8899882 --- a/source/Menu.h +++ b/source/Menu.h @@ -2,12 +2,8 @@ #include "MenuTutorial.h" #include "texturepack.h" -#include "Quests.h" -#include "Network.h" - -void initMenus(); void renderMenu(int menu,int xscr,int yscr); void tickMenu(int menu); -void menuRenderTilePit(int x,int y,int xt,int yt); +void menuRenderTilePit(int x,int y,int xt,int yt,u32 color); diff --git a/source/MenuTutorial.c b/source/MenuTutorial.c old mode 100755 new mode 100644 index 3e36c15..a7c33c8 --- a/source/MenuTutorial.c +++ b/source/MenuTutorial.c @@ -1,260 +1,250 @@ #include "MenuTutorial.h" u8 pageNum = 0; -u8 maxPageNum = 7; +u8 maxPageNum = 6; 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; - 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 - - 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; - 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); - } + 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(k_up.input), 164, 88, 1); + drawText("Press to move down",80,120); + renderButtonIcon(biasedCirclePad(k_down.input), 152, 118, 1); + drawText("Press to move left",80,150); + renderButtonIcon(biasedCirclePad(k_left.input), 152, 148, 1); + drawText("Press to move right",74,180); + renderButtonIcon(biasedCirclePad(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(k_attack.input & -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(k_menu.input), 126, 78, 1); + drawText("Press to scroll up",80,110); + renderButtonIcon(biasedCirclePad(k_up.input), 152, 108, 1); + drawText("Press to scroll down",68,140); + renderButtonIcon(biasedCirclePad(k_down.input), 140, 138, 1); + drawText("Press to select an item",50,170); + renderButtonIcon(k_accept.input & -k_accept.input, 120, 168, 1); + drawText("Press to close the menu",50,200); + renderButtonIcon(k_decline.input & -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(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(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(k_accept.input & -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; + } + } else { + switch(pageNum){ + case 0: // Moving the character + render16(30,56,16,112,0);//Player up + renderButtonIcon(biasedCirclePad(k_up.input), 30,40, 2); + render16(60,56,0,112,0);//Player down + renderButtonIcon(biasedCirclePad(k_down.input), 60,40, 2); + render16(90,56,48,112,1);//Player left + renderButtonIcon(biasedCirclePad(k_left.input), 90,40, 2); + render16(120,56,48,112,0);//Player right + renderButtonIcon(biasedCirclePad(k_right.input), 120,40, 2); + break; + case 1: // Attacking + render16(60,56,0,112,0);//Player-down + renderButtonIcon(k_attack.input & -k_attack.input, 80, 56, 2); + renderc(60,68,16,160,16,8,2);//Slash + + menuRenderTilePit(12,20,112,16,grassColor);// grass pit + render16(12+8,20+4,0,16,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,112,16,sandColor);// sand pit + render16b(130,70,176,16,0,0xFF383838);// hole + render16(116,70,48,112,0);//Player-right + renderb(136,76,16,152,0,0xFF8197AF);// Dirt 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,0xFFAF); + 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(k_up.input), 44, 92, 1); + renderButtonIcon(k_accept.input & -k_accept.input, 44, 108, 1); + renderButtonIcon(biasedCirclePad(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,144,0,112,16,0); // Wheat Stages + + render16(20,40,144,0,0); // Farm Tile + render16(36,40,240,0,0); // Wheat Tile + render16(52,40,240,0,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,144,0,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 + render16b(108, 40, 112, 16, 0, grassColor); // Grass + render16(124, 40,144,0,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 + render16b(56, 78, 112, 16, 0, grassColor); // Grass + sf2d_draw_rectangle(80, 156, 32, 32, dirtColor[1]); // Dirt color + render16b(40, 78, 0, 0, 0, 0xFF8F8FA8); // 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 + render16b(23,32,80,0,0,0xFFC8C8DF); // iron ore + render16b(23,52,80,0,0,0xFFB9E8E5); // gold ore + render16b(23,72,80,0,0,0xFFDE98DF); // gem ore + renderb(41,38,88,152,0,0xFFC8C8DF); // Iron ore item + renderb(41,58,88,152,0,0xFFB9E8E5); // 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,64,128,0); // Anvil + drawText(">",160,74); + drawText(">",160,114); + drawText(">",160,154); + renderb(88,36,96,152,0,0xFFC8C8DF); // Iron ingot item + renderb(88,56,96,152,0,0xFFB9E8E5); // Gold ingot item + renderb(88,76,152,144,0,0xFFB9E8E5); // 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; + } + + drawText(pageText,(320-(strlen(pageText))*12)/2,12); + if(pageNum > 0){ + drawText("<",2,16); + renderButtonIcon(k_menuPrev.input & -k_menuPrev.input, 8, 2, 2); + } + if(pageNum < maxPageNum){ + drawText(">",306,16); + renderButtonIcon(k_menuNext.input & -k_menuNext.input, 136, 2, 2); + } + drawText("Press to exit",(320-(15*12))/2,218); + renderButtonIcon(k_decline.input & -k_decline.input, 140, 216, 1); + } } diff --git a/source/MenuTutorial.h b/source/MenuTutorial.h old mode 100755 new mode 100644 index 5ce7f4e..682d7c7 --- a/source/MenuTutorial.h +++ b/source/MenuTutorial.h @@ -1,7 +1,7 @@ #pragma once #include <3ds.h> -#include +#include #include #include #include diff --git a/source/Network.c b/source/Network.c deleted file mode 100755 index 1489bbe..0000000 --- a/source/Network.c +++ /dev/null @@ -1,620 +0,0 @@ -#include "Network.h" - -#include "PacketHandler.h" -#include -#include -#include - -bool udsRunning; - -size_t scannedNetworksCount; -udsNetworkScanInfo *scannedNetworks; - -bool isConnected; -bool isServer; - -size_t networkBufferSize; -void *networkBuffer; - -udsNetworkStruct networkStruct; -udsBindContext networkBindCtx; - -udsConnectionStatus networkStatus; - -u16 networkConnectedMask; - -//new code -//structure in buffer is u16(seqID),u16(size),size(data), ... -void *networkSendBuffer; -size_t networkSendBufferStartPos; -size_t networkSendBufferEndPos; -size_t networkSendBufferWrapPos; - -u16 networkSeqSendNext; -u16 networkSeqSendConf[UDS_MAXNODES+1]; -u16 networkSeqRecvLast[UDS_MAXNODES+1]; -void *networkAckBuffer; - -//async internal send/recieve handling -Thread networkThread; -volatile bool networkRunThread; -LightLock sendBufferLock; - -void networkHandleSend(); -void networkHandleRecieve(); -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); - } -} - -void networkUpdateStatus() { - /*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; - u16 sourceNetworkNodeID; - 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 - 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+currentSize0) { - //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); -} - -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; - } -} - -void networkInit() { - Result ret = udsInit(0x3000, NULL); - if(R_FAILED(ret)) { - udsRunning = false; - } else { - udsRunning = true; - - scannedNetworksCount = 0; - scannedNetworks = NULL; - isConnected = false; - isServer = false; - networkConnectedMask = 0; - - 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=scannedNetworksCount) return false; - - Result ret = udsGetNodeInfoUsername(&(scannedNetworks[pos].nodes[0]), name); - if(R_FAILED(ret)) { - //TODO: what do? - return false; - } - return true; - } - return false; -} - -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); - isConnected = true; - isServer = false; - networkConnectedMask = 0; - return true; - } - } - return false; -} - -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; i20*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(); - } else { - 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(); - } -} - - -bool networkConnected() { - return isConnected; -} - -int networkGetNodeCount() { - if(udsRunning && isConnected) { - return networkStatus.total_nodes; - } else { - return 0; - } -} - -u16 networkGetLocalNodeID() { - 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; - } -} - -bool networkGetNodeName(u16 id, char *name) { - if(udsRunning && isConnected && networkIsNodeConnected(id)) { - udsNodeInfo nodeInfo; - udsGetNodeInformation(id, &nodeInfo); - - Result ret = udsGetNodeInfoUsername(&nodeInfo, name); - if(R_FAILED(ret)) { - //TODO: what do? - return false; - } - return true; - } - 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+sizesize) { - 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) - 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); -} - -void networkSendWaitFlush() { - while(networkSendBufferStartPos!=networkSendBufferEndPos) { - svcSleepThread(4500 * 1000); - } -} diff --git a/source/Network.h b/source/Network.h deleted file mode 100755 index 92c1e32..0000000 --- a/source/Network.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include <3ds.h> - -#define NETWORK_WLANCOMMID 0x11441850 -#define NETWORK_PASSPHRASE "minicraft3dsLP" -#define NETWORK_CHANNEL 1 - -#define NETWORK_RECVBUFSIZE UDS_DEFAULT_RECVBUFSIZE - -#define NETWORK_MAXDATASIZE 1024 -#define NETWORK_SENDBUFFERSIZE ((NETWORK_MAXDATASIZE+256)*10) - -#define NETWORK_STACKSIZE (8*1024) - -#define NETWORK_MAXPLAYERS 8 - -void *networkWriteBuffer; - -void networkInit(); -void networkExit(); - -bool networkAvailable(); - -bool networkHost(); -void networkHostStopConnections(); -void networkScan(); -int networkGetScanCount(); -bool networkGetScanName(char *name, int pos); -bool networkConnect(int pos); -void networkDisconnect(); - -void networkStart(); - -void networkUpdateStatus(); -bool networkConnected(); - -int networkGetNodeCount(); -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(); diff --git a/source/PacketHandler.c b/source/PacketHandler.c deleted file mode 100755 index 5322a31..0000000 --- a/source/PacketHandler.c +++ /dev/null @@ -1,357 +0,0 @@ -#include "PacketHandler.h" -#include -#include "Synchronizer.h" - -FILE *recvFile; -size_t recvFileSize; - -void * writeBool(void *buffer, size_t *size, bool value) { - *((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); -} - -void * writeU16(void *buffer, size_t *size, u16 value) { - *((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); -} - -void * writeSizeT(void *buffer, size_t *size, size_t value) { - *((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); -} - -void * readU8(void *buffer, size_t *size, u8 *value) { - *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); -} - -void * readU32(void *buffer, size_t *size, u32 *value) { - *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); -} - -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; ik_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_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); - } -} - -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 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 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); -} diff --git a/source/PacketHandler.h b/source/PacketHandler.h deleted file mode 100755 index 0001e79..0000000 --- a/source/PacketHandler.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include "Network.h" -#include "Player.h" - -#define PACKET_START 0 -#define PACKET_START_FILEHEADER 1 -#define PACKET_START_FILEDATA 2 -#define PACKET_START_REQUEST_IDS 3 -#define PACKET_START_ID 4 -#define PACKET_START_READY 5 - -#define PACKET_TURN_START 10 -#define PACKET_TURN_INPUT 11 - -void processPacket(void *packet, size_t size); - -u8 packetGetID(void *packet); -u8 packetGetSender(void *packet); -u32 packetGetTurn(void *packet); -void * packetGetDataStart(void *packet); -size_t packetGetDataSize(size_t size); - -size_t writeStartPacket(void *buffer, u32 seed); -size_t writeStartRequestPacket(void *buffer); - -size_t writeInputPacket(void *buffer, Inputs *inputs, u8 playerID, u32 turnNumber); -bool readInputPacketData(void *buffer, size_t size, Inputs *inputs); - -void sendFile(FILE *file, u8 fileType, u8 id); -void sendIDPacket(u8 playerID, u32 uid); -void sendStartReadyPacket(u8 playerID); -void sendStartSyncPacket(); diff --git a/source/Player.c b/source/Player.c deleted file mode 100644 index f757b42..0000000 --- a/source/Player.c +++ /dev/null @@ -1,657 +0,0 @@ -#include "Player.h" - -#include -#include "Globals.h" - -void potionEffect(int type) { - if(type == 1) { - UnderStrengthEffect = true; - } - if(type == 2) { - UnderSpeedEffect = true; - } - if (type == 3) { - regening = true; - } - if (type == 4) { - UnderSwimBreathEffect = true; - } -} - -void initPlayers() { - for(int i=0; ientity.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; - - 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)); - } -} - -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; -} - -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->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; -} - -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; -} - -void freePlayer(PlayerData *pd) { - freeQuests(&(pd->questManager)); -} - -PlayerData* getNearestPlayer(s8 level, s16 x, s16 y) { - int nearest = -1; - unsigned int nearestDist = UINT_MAX; - - for(int i=0; iactiveItem->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; - case ITEM_SPEED_POTION: - if(pd->entity.p.health < 20 && pd->entity.p.speedTimer == 0){ - potionEffect(2); - --(pd->activeItem->countLevel); - } - return 0; - case ITEM_REGEN_POTION: - if(pd->entity.p.health < 20 && pd->entity.p.regenTimer == 0){ - potionEffect(3); - --(pd->activeItem->countLevel); - } - 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; - case ITEM_GOLD_APPLE: - 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; - case ITEM_PORK_RAW: - 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; - case ITEM_BEEF_RAW: - 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; - //special item - case ITEM_WIZARD_SUMMON: - if(pd->entity.level==0) { - --(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; - } - - return false; -} - -bool playerInteract(PlayerData *pd, int x0, int y0, int x1, int y1) { - 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 (ItemVsEntity(pd, pd->activeItem, ent, pd->entity.p.dir)) return true; - } - } - return false; -} - -void playerAttack(PlayerData *pd) { - bool done = false; - pd->entity.p.attackTimer = 5; - int yo = -2; - 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; - } - - int xt = pd->entity.x >> 4; - int yt = (pd->entity.y + yo) >> 4; - int r = 12; - if (pd->entity.p.dir == 0) yt = (pd->entity.y + r + yo) >> 4; - if (pd->entity.p.dir == 1) yt = (pd->entity.y - r + yo) >> 4; - if (pd->entity.p.dir == 2) xt = (pd->entity.x - r) >> 4; - if (pd->entity.p.dir == 3) xt = (pd->entity.x + r) >> 4; - - //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; - } - - 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); - } - } -} - -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; - } - return false; -} - -bool playerUse(PlayerData *pd) { - int yo = -2; - if (pd->entity.p.dir == 0 && playerUseArea(pd, pd->entity.x - 8, pd->entity.y + 4 + yo, pd->entity.x + 8, pd->entity.y + 12 + yo)) return true; - if (pd->entity.p.dir == 1 && playerUseArea(pd, pd->entity.x - 8, pd->entity.y - 12 + yo, pd->entity.x + 8, pd->entity.y - 4 + yo)) return true; - if (pd->entity.p.dir == 3 && playerUseArea(pd, pd->entity.x + 4, pd->entity.y - 8 + yo, pd->entity.x + 12, pd->entity.y + 8 + yo)) return true; - if (pd->entity.p.dir == 2 && playerUseArea(pd, pd->entity.x - 12, pd->entity.y - 8 + yo, pd->entity.x - 4, pd->entity.y + 8 + yo)) return true; - return false; -} - -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) { - pd->entity.p.staminaRechargeDelay = 40; - } - - if (pd->entity.p.staminaRechargeDelay > 0) { - --pd->entity.p.staminaRechargeDelay; - } - - 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(UnderSpeedEffect) { - pd->entity.p.ax -= 2; - pd->entity.p.dir = 2; - ++pd->entity.p.walkDist; - ++pd->entity.p.walkDist; - } else { - pd->entity.p.ax -= 1; - pd->entity.p.dir = 2; - ++pd->entity.p.walkDist; - } - } - if (pd->inputs.k_right.down){ - if(UnderSpeedEffect) { - pd->entity.p.ax += 2; - pd->entity.p.dir = 3; - ++pd->entity.p.walkDist; - ++pd->entity.p.walkDist; - } else { - pd->entity.p.ax += 1; - pd->entity.p.dir = 3; - ++pd->entity.p.walkDist; - } - } - if (pd->inputs.k_up.down){ - if(UnderSpeedEffect) { - pd->entity.p.ay -= 2; - pd->entity.p.dir = 1; - ++pd->entity.p.walkDist; - ++pd->entity.p.walkDist; - } else { - pd->entity.p.ay -= 1; - pd->entity.p.dir = 1; - ++pd->entity.p.walkDist; - } - } - if (pd->inputs.k_down.down){ - if(UnderSpeedEffect) { - pd->entity.p.ay += 2; - pd->entity.p.dir = 0; - ++pd->entity.p.walkDist; - ++pd->entity.p.walkDist; - } else { - pd->entity.p.ay += 1; - 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); - } - } - - //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; ientityFurniture.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); - } - } - - //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(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; - - //TODO - maybe move to own function - //Update Minimap - int xp; - int yp; - for(xp = (pd->entity.x>>4)-5; xp<(pd->entity.x>>4)+5; ++xp) { - for(yp = (pd->entity.y>>4)-5; yp<(pd->entity.y>>4)+5; ++yp) { - if(xp>=0 && xp<128 && yp>=0 && yp<128) { - if(!getMinimapVisible(pd, pd->entity.level, xp, yp)) { - setMinimapVisible(pd, pd->entity.level, xp, yp, true); - } - } - } - } -} - -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; -} - -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; -} - -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); -} - -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; - } - } -} diff --git a/source/Player.h b/source/Player.h deleted file mode 100644 index b3d28bc..0000000 --- a/source/Player.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include "Input.h" -#include "Entity.h" -#include "QuestsData.h" -#include "Crafting.h" - -#define MAX_PLAYERS 8 -#define MAX_INPUT_BUFFER 3 - -#define PLAYER_SPRITE_HEAD_COUNT 4 -#define PLAYER_SPRITE_EYES_COUNT 5 -#define PLAYER_SPRITE_BODY_COUNT 6 -#define PLAYER_SPRITE_ARMS_COUNT 6 -#define PLAYER_SPRITE_LEGS_COUNT 5 - - -typedef struct _plrsp { - 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]; - - 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; -} PlayerData; - -PlayerData players[MAX_PLAYERS]; -int playerCount; -int playerLocalID; - -void initPlayers(); -void freePlayers(); - -void initPlayer(PlayerData *pd); -void freePlayer(PlayerData *pd); - -PlayerData* getNearestPlayer(s8 level, s16 x, s16 y); -PlayerData* getLocalPlayer(); - -void tickPlayer(PlayerData *pd, bool inmenu); -void playerSetActiveItem(PlayerData *pd, Item * item); -bool playerUseEnergy(PlayerData * pd, int amount); -void playerHeal(PlayerData *pd, int amount); -void playerSpawn(PlayerData *pd); diff --git a/source/Quests.c b/source/Quests.c deleted file mode 100755 index 9f10b43..0000000 --- a/source/Quests.c +++ /dev/null @@ -1,437 +0,0 @@ -#include "Quests.h" - -#include "Globals.h" -#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.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 -} - -void freeTrades() { - 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)); -} - -void resetQuests(QuestlineManager *questManager) { - int i; - for(i=0; isize; ++i) { - questManager->questlines[i].currentQuest = 0; - questManager->questlines[i].currentQuestDone = false; - } -} - -void freeQuests(QuestlineManager *questManager) { - 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 = ""; -} - -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; - } -} - -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; - } -} - -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); - - - 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); - 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); -} - -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; - } -} diff --git a/source/Quests.h b/source/Quests.h deleted file mode 100755 index 05a581e..0000000 --- a/source/Quests.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include -#include "QuestsData.h" -#include "Player.h" -#include "Crafting.h" - -#define NPC_MENU_TALK 0 - -RecipeManager priestTrades; -RecipeManager farmerTrades; -RecipeManager dwarfTrades; - -void initTrades(); -void freeTrades(); - -void initQuests(QuestlineManager *questManager); -void resetQuests(QuestlineManager *questManager); -void freeQuests(QuestlineManager *questManager); - -void resetNPCMenuData(NPC_MenuData *data); -void openNPCMenu(PlayerData *pd, int npc); -void tickNPCMenu(PlayerData *pd); -void renderNPCMenu(NPC_MenuData *data); diff --git a/source/QuestsData.h b/source/QuestsData.h deleted file mode 100644 index 91a770e..0000000 --- a/source/QuestsData.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <3ds.h> - -typedef struct _questline { - int currentQuest; - bool currentQuestDone; -} Questline; - -typedef struct _questlineManager { - int size; - Questline * questlines; -} QuestlineManager; - -typedef struct _npcMenuData { - u8 currentNPC; - - 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; -} NPC_MenuData; - -//TODO: Actually move the data here diff --git a/source/Render.c b/source/Render.c old mode 100755 new mode 100644 index 3496c0a..6f200db --- a/source/Render.c +++ b/source/Render.c @@ -1,7 +1,5 @@ #include "Render.h" -extern u32 syncTickCount; - void render(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits) { xp -= offsetX; yp -= offsetY; @@ -144,34 +142,10 @@ void render16s(s32 xp, s32 yp, u32 tile, u8 bits, u32 color) { 16, 16, scaleX, scaleY, color); } -void render32(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits) { - xp -= offsetX; - yp -= offsetY; - int scaleX = 2, scaleY = 2; - if ((bits & 1) > 0) { - scaleX = -2; - xp += 32; - } - if ((bits & 2) > 0) { - scaleY = -2; - yp += 32; - } - sf2d_draw_texture_part_scale(icons, xp << 1, yp << 1, xTile, yTile, 32, 32, - scaleX, scaleY); -} - -int playerScale = 2; -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); -} - void renderTitle(int x, int y) { - sf2d_draw_texture_part_scale(icons, (x - 26) << 1, y << 1, 0, 240, 104, 16, 2.0, 2.0); // MINICRAFT - sf2d_draw_texture_part(icons, x + 48, y + 44, 104, 240, 152, 16); // 3DS HOMEBREW EDITION + sf2d_draw_texture_part_scale(icons, (x - 26) << 1, y << 1, 0, 240, 104, 16, + 2.0, 2.0); // MINICRAFT + sf2d_draw_texture_part(icons, x + 48, y + 52, 104, 240, 152, 16); // 3DS HOMEBREW EDITION } void renderButtonIcon(u32 keyIcon, int x, int y, float scale) { @@ -284,81 +258,61 @@ 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); + lanternLightBake = sf2d_create_texture(128, 128, 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); } void freeLightBakes() { sf2d_free_texture(playerLightBake); sf2d_free_texture(lanternLightBake); - - sf2d_free_texture(glowwormLightBake); - sf2d_free_texture(glowwormBigLightBake); } -void renderLightsToStencil(PlayerData *pd, bool force, bool invert, bool rplayer) { - if (force || (pd->entity.level > 1 && pd->entity.level != 5)) { - C3D_DepthTest(true, GPU_NEVER, 0); - C3D_StencilTest(true, GPU_NEVER, 1, 0xFF, 0xFF); - 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); +void renderLightsToStencil() { + if (currentLevel > 1) { + GPU_SetDepthTestAndWriteMask(true, GPU_NEVER, 0); + GPU_SetStencilTest(true, GPU_NEVER, 1, 0xFF, 0xFF); + GPU_SetStencilOp(GPU_STENCIL_REPLACE, GPU_STENCIL_KEEP, + GPU_STENCIL_KEEP); + GPU_SetAlphaTest(true, GPU_GREATER, 0); + if(player.p.activeItem->id == ITEM_LANTERN) renderLight(player.x, player.y, lanternLightBake); + else renderLight(player.x, player.y, playerLightBake); + int i; - for (i = 0; i < eManager.lastSlot[pd->entity.level]; ++i) { - Entity e = eManager.entities[pd->entity.level][i]; - if (e.type == ENTITY_FURNITURE) { - if (e.entityFurniture.itemID == ITEM_LANTERN && e.x > pd->entity.x - 160 && e.y > pd->entity.y - 125 && e.x < pd->entity.x + 160 && e.y < pd->entity.y + 125) - renderLight(e.x, e.y, lanternLightBake); - } else if(e.type == ENTITY_GLOWWORM && e.x > pd->entity.x - 160 && e.y > pd->entity.y - 125 && e.x < pd->entity.x + 160 && e.y < pd->entity.y + 125) { //TODO could be made smaller becuase of smaller light radius - if(rand()%10==0) continue; - else if(rand()%100==0) renderLight(e.x+20, e.y-20, glowwormBigLightBake); - else renderLight(e.x+8, e.y-8, glowwormLightBake); - } + for (i = 0; i < eManager.lastSlot[currentLevel]; ++i) { + Entity e = eManager.entities[currentLevel][i]; + if (e.type != ENTITY_FURNITURE)continue; + if (e.entityFurniture.itemID == ITEM_LANTERN && e.x > player.x - 160 + && e.y > player.y - 125 && e.x < player.x + 160 && e.y < player.y + 125) + renderLight(e.x, e.y, lanternLightBake); } - + int xo = offsetX >> 4; int yo = offsetY >> 4; int x, y; //added offset to render lights from lava which is offscreen - //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) { - //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; - } - renderLight((x << 4) + 8, (y << 4) + 8, playerLightBake); - } - } + for (y = yo-2; y <= 8 + yo+2; ++y) + if(getTile(x, y) == TILE_LAVA) renderLight(x << 4, y << 4, playerLightBake); } - - - C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL); - if(invert) { - C3D_StencilTest(true, GPU_EQUAL, 0, 0xFF, 0x0); - } else { - C3D_StencilTest(true, GPU_EQUAL, 1, 0xFF, 0x0); - } - C3D_AlphaTest(false, GPU_ALWAYS, 0x00); - C3D_StencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_REPLACE); + + + GPU_SetDepthTestAndWriteMask(true, GPU_GEQUAL, GPU_WRITE_ALL); + GPU_SetStencilTest(true, GPU_EQUAL, 1, 0xFF, 0x0); + GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00); + GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, + GPU_STENCIL_REPLACE); } } void resetStencilStuff() { - C3D_StencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00); - C3D_StencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP); + if (currentLevel > 1) { + GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00); + GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP); + } } void renderLight(int x, int y, sf2d_texture* texture) { @@ -415,17 +369,11 @@ bool tur = false; bool tdl = false; bool tdr = false; -void renderDots(int x, int y, u8 bits1, u8 bits2, u8 bits3, u8 bits4, u32 xTile, u32 yTile) { - //another speedhack for o3DS - if(tu && tl && tr && td) { - 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); - if(td && tr) render(x + 8, y + 8, xTile+8, yTile+8, bits4); +void renderDotsWithColor(int x, int y, u8 bits1, u8 bits2, u8 bits3, u8 bits4, u32 color) { + if(tu && tl) renderb(x, y, 0, 0, bits1, color); + if(tu && tr) renderb(x + 8, y, 8, 0, bits2, color); + if(td && tl) renderb(x, y + 8, 0, 8, bits3, color); + if(td && tr) renderb(x + 8, y + 8, 8, 8, bits4, color); } void resetSurrTiles() { @@ -440,578 +388,377 @@ void resetSurrTiles() { tdr = false; } -void checkSurrTiles8(u8 level, int xt, int yt, int id) { - if (getTile(level, xt, yt - 1) == id) +void checkSurrTiles8(int xt, int yt, int id) { + if (getTile(xt, yt - 1) == id) tu = true; - if (getTile(level, xt - 1, yt) == id) + if (getTile(xt - 1, yt) == id) tl = true; - if (getTile(level, xt + 1, yt) == id) + if (getTile(xt + 1, yt) == id) tr = true; - if (getTile(level, xt, yt + 1) == id) + if (getTile(xt, yt + 1) == id) td = true; - if (getTile(level, xt - 1, yt - 1) == id) + if (getTile(xt - 1, yt - 1) == id) tul = true; - if (getTile(level, xt + 1, yt - 1) == id) + if (getTile(xt + 1, yt - 1) == id) tur = true; - if (getTile(level, xt - 1, yt + 1) == id) + if (getTile(xt - 1, yt + 1) == id) tdl = true; - if (getTile(level, xt + 1, yt + 1) == id) + if (getTile(xt + 1, yt + 1) == id) tdr = true; } -void checkSurrTiles4(u8 level, int xt, int yt, int id) { - if (getTile(level, xt, yt - 1) == id) +void checkSurrTiles4(int xt, int yt, int id) { + if (getTile(xt, yt - 1) == id) tu = true; - if (getTile(level, xt - 1, yt) == id) + if (getTile(xt - 1, yt) == id) tl = true; - if (getTile(level, xt + 1, yt) == id) + if (getTile(xt + 1, yt) == id) tr = true; - if (getTile(level, xt, yt + 1) == id) + if (getTile(xt, yt + 1) == id) td = true; } u8 tData = 0; -void renderTile(int i, int d, u8 level, int x, int y) { +void renderTile(int i, int x, int y) { int age = 0; switch (i) { case TILE_GRASS: - checkSurrTiles4(level, x >> 4, y >> 4, TILE_GRASS); - 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); - else renderConnectedTile4(x, y, 256, 0); + checkSurrTiles4(x >> 4, y >> 4, TILE_GRASS); + checkSurrTiles4(x >> 4, y >> 4, TILE_TREE); + checkSurrTiles4(x >> 4, y >> 4, TILE_FLOWER); + checkSurrTiles4(x >> 4, y >> 4, TILE_SAPLING_TREE); + + renderConnectedTile4(x, y, 112, 16, grassColor); 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); - } - + renderTile(TILE_GRASS, x, y); + + checkSurrTiles8(x >> 4, y >> 4, TILE_TREE); + + render(x, y, 0+((tu && tl && tul) ? 16 : 0), 16, 0); + render(x+8, y, 8+((tu && tr && tur) ? 16 : 0), 16, 0); + render(x, y+8, 0+((td && tl && tdl) ? 16 : 0), 24, 0); + render(x+8, y+8, 8+((td && tr && tdr) ? 16 : 0), 24, 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); + checkSurrTiles8(x >> 4, y >> 4, TILE_ROCK); + renderConnectedTile8(x, y, 32, 16, rockColor[0]); break; case TILE_HARDROCK: - checkSurrTiles8(level, x >> 4, y >> 4, TILE_HARDROCK); - renderConnectedTile8(x, y, 416, 64); + checkSurrTiles8(x >> 4, y >> 4, TILE_HARDROCK); + renderConnectedTile8(x, y, 32, 16, rockColor[2]); break; case TILE_DIRT: // render dots. - if (level > 1) - render16(x, y, 320, 80, 0); + if (currentLevel > 1) + render16b(x, y, 0, 0, 0, 0xFF383838); else - render16(x, y, 336, 80, 0); + render16b(x, y, 0, 0, 0, 0xFF8F8FA8); break; case TILE_SAND: - 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); - } else { - renderConnectedTile4(x, y, 320, 0); - - if (d > 0) { - render16(x, y, 336, 48, 0); - } - } + checkSurrTiles4(x >> 4, y >> 4, TILE_SAND); + checkSurrTiles4(x >> 4, y >> 4, TILE_CACTUS); + checkSurrTiles4(x >> 4, y >> 4, TILE_SAPLING_CACTUS); + + renderConnectedTile4(x, y, 112, 16, sandColor); 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); + checkSurrTiles4(x >> 4, y >> 4, TILE_WATER); + checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE); + + renderConnectedTile4(x, y, 176, 16, waterColor[0]); + + srand((tickCount + (x / 2 - y) * 4311) / 10); + renderDotsWithColor(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, waterColor[1]); 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); + checkSurrTiles4(x >> 4, y >> 4, TILE_LAVA); + checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE); + + renderConnectedTile4(x, y, 176, 16, lavaColor[0]); + + srand((tickCount + (x / 2 - y) * 4311) / 10); + renderDotsWithColor(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, lavaColor[1]); break; case TILE_HOLE: - 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); + checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE); + checkSurrTiles4(x >> 4, y >> 4, TILE_WATER); + checkSurrTiles4(x >> 4, y >> 4, TILE_LAVA); + + renderConnectedTile4(x, y, 176, 16, 0xFF383838); break; case TILE_CACTUS: - renderTile(TILE_SAND, 0, level, x, y); - render16(x, y, 304, 48, 0); + renderTile(TILE_SAND, x, y); + render16(x, y, 48, 0, 0); break; 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); + renderTile(TILE_GRASS, x, y); + render16(x, y, 64, 0, getData(x >> 4, y >> 4)); break; case TILE_STAIRS_DOWN: - if (level == 0) - renderTile(TILE_CLOUD, 0, level, x, y); - render16(x, y, 256, 64, 0); + if (currentLevel == 0) + renderTile(TILE_CLOUD, x, y); + render16(x, y, 96, 0, 0); break; case TILE_STAIRS_UP: - render16(x, y, 272, 64, 0); + render16(x, y, 112, 0, 0); break; case TILE_IRONORE: - render16(x, y, 464, 48, 0); + render16b(x, y, 80, 0, 0, 0xFFC8C8DF); break; case TILE_GOLDORE: - render16(x, y, 480, 48, 0); + render16b(x, y, 80, 0, 0, 0xFFB9E8E5); break; case TILE_GEMORE: - render16(x, y, 496, 48, 0); + render16b(x, y, 80, 0, 0, 0xFFDE98DF); break; case TILE_CLOUD: - 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); + checkSurrTiles4(x >> 4, y >> 4, TILE_CLOUD); + checkSurrTiles4(x >> 4, y >> 4, TILE_STAIRS_DOWN); + checkSurrTiles4(x >> 4, y >> 4, TILE_CLOUDCACTUS); + + renderConnectedTile4(x, y, 64, 32, 0xFFFFFFFF); break; case TILE_CLOUDCACTUS: - renderTile(TILE_CLOUD, 0, level, x, y); - render16(x, y, 496, 64, 0); + renderTile(TILE_CLOUD, x, y); + render16(x, y, 80, 0, 0); break; case TILE_SAPLING_TREE: - renderTile(TILE_GRASS, 0, level, x, y); - render16(x, y, 288, 48, 0); + renderTile(TILE_GRASS, x, y); + render16(x, y, 32, 0, 0); break; case TILE_SAPLING_CACTUS: - renderTile(TILE_SAND, 0, level, x, y); - render16(x, y, 288, 48, 0); + renderTile(TILE_SAND, x, y); + render16(x, y, 32, 0, 0); break; case TILE_FARM: - render16(x, y, 352, 48, 0); + render16(x, y, 144, 0, 0); break; case TILE_WHEAT: - age = d / 20; + age = getData(x >> 4, y >> 4) / 20; if (age > 5) age = 5; - render16(x, y, 368 + (age << 4), 48, 0); + render16(x, y, 160 + (age << 4), 0, 0); 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: - render16(x, y, 464 + d*16, 32, 0); - break; - case TILE_DUNGEON_ENTRANCE: - render16(x, y, 352 + (level==5 ? 16 : 0), 80, 0); - break; - 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(); - 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: - 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: - 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); - render16(x, y, 448 + (d&0x1)*16, 96, 0); - 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: - 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); + checkSurrTiles4(x >> 4, y >> 4, TILE_WOOD_WALL); + + renderConnectedTile4(x, y, 0, 32, woodColor); break; } resetSurrTiles(); } -void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile) { +void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile, u32 color) { //render complete tile in one piece to reduce strain(added for o3DS) if (tl && tr && tu && td) { - render16(x, y, xTile+48, yTile, 0); + render16b(x, y, xTile+48, yTile, 0, color); 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); - render(x+8, y+8, xTile+8+r+d, yTile+8, 0); + + renderb(x, y, xTile +l+u, yTile, 0, color); + renderb(x+8, y, xTile+8+r+u, yTile, 0, color); + renderb(x, y+8, xTile +l+d, yTile+8, 0, color); + renderb(x+8, y+8, xTile+8+r+d, yTile+8, 0, color); } -void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile) { +void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile, u32 color) { //render complete tile in one piece to reduce strain(added for o3DS) if (tl && tr && tu && td && tul && tur && tdl && tdr) { - render16(x, y, xTile+64, yTile, 0); + render16b(x, y, xTile+64, yTile, 0, color); 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); - render(x+8, y+8, xTile+8+r+d+((tr && td && tdr) ? 16 : 0), yTile+8, 0); + + renderb(x, y, xTile +l+u+((tl && tu && tul) ? 16 : 0), yTile, 0, color); + renderb(x+8, y, xTile+8+r+u+((tr && tu && tur) ? 16 : 0), yTile, 0, color); + renderb(x, y+8, xTile +l+d+((tl && td && tdl) ? 16 : 0), yTile+8, 0, color); + renderb(x+8, y+8, xTile+8+r+d+((tr && td && tdr) ? 16 : 0), yTile+8, 0, color); } -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; - sf2d_draw_texture_scale(minimap[pd->entity.level], mx, my, pd->mapZoomLevel, pd->mapZoomLevel); // zoomed map - +void renderZoomedMap() { + int mx = mScrollX; + int my = mScrollY; + if(zoomLevel == 2) mx = 32; + sf2d_draw_texture_scale(minimap[currentLevel], mx, my, zoomLevel, zoomLevel); // zoomed map // Airwizard on zoomed map - if(pd->entity.level == 0){ + if(currentLevel == 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)*zoomLevel)-16)/2, + (my+((awY/16)*zoomLevel)-16)/2, + 160, 112, + ((player.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 + render16c( + (mx+((player.x/16)*zoomLevel)-16)/2, + (my+((player.y/16)*zoomLevel)-16)/2, + 0, 112, + ((player.p.walkDist >> 6) & 1) == 0 ? 0 : 1, + 2, 2 + ); + + drawText(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(zoomLevel < 3) sf2d_draw_rectangle(258, 210, 26, 20, 0x7F4F4F4F); // gray out minus button + else if(zoomLevel > 5) sf2d_draw_rectangle(284, 210, 26, 20, 0x7F4F4F4F); // gray out minus button } char scoreT[32]; -void renderGui(PlayerData *pd) { +void renderGui() { int i; - //health and stamina for (i = 0; i < 10; ++i) { - if (i < pd->entity.p.health) + if (i < player.p.health) render(i * 8 + 6, 5, 168, 152, 0); else render(i * 8 + 6, 5, 176, 152, 0); - if (i < pd->entity.p.stamina) + if (i < player.p.stamina) render(i * 8 + 6, 14, 184, 152, 0); else render(i * 8 + 6, 14, 191, 152, 0); } - - //minimap - sf2d_draw_texture(minimap[pd->entity.level], 10, 102); - - //active item - renderItemWithTextCentered(pd->activeItem, 320, 66); - itoa(pd->score, scoreT, 10); // integer to base10 string + sf2d_draw_texture(minimap[currentLevel], 10, 102); + renderItemWithTextCentered(player.p.activeItem, 320, 66); + itoa(player.p.score, scoreT, 10); // integer to base10 string drawText("Score:",214,12); drawText(scoreT,(140-(strlen(scoreT)*12))/2 + 180,29); - if(pd->entity.level == 0){ + if(currentLevel == 0){ 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? - renderc(1 + (pd->entity.x/32), 47 + (pd->entity.y/32), 88, 208, 8, 8, 0); // Mini-Player head. - + } + renderc(1 + (player.x/32), 47 + (player.y/32), 88, 208, 8, 8, 0); // Mini-Player head. + //quick select drawText("Quickselect:",164,118); - Inventory * inv = &(pd->inventory); + Inventory * inv = player.p.inv; Item * item; for (i = 0; i < 8; ++i) { 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); } } } -void renderPlayer(PlayerData *pd) { - if (pd->entity.level!=getLocalPlayer()->entity.level) { +void renderPlayer() { + if (player.p.isDead) return; - } - if (pd->entity.p.isDead) { - return; - } - int xo = pd->entity.x - 8; - int yo = pd->entity.y - 8; + int xo = player.x - 8; + int yo = player.y - 8; - //attack animation upwards - if (pd->entity.p.attackTimer > 0 && pd->entity.p.dir == 1) { + if (player.p.attackTimer > 0 && player.p.dir == 1) { renderc(xo, yo - 4, 16, 160, 16, 8, 0); - renderItemIcon(pd->activeItem->id, pd->activeItem->countLevel, xo + 4, yo - 4); + renderItemIcon(player.p.activeItem->id, player.p.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; + u8 walk = (player.p.walkDist >> 4) & 1; + bool swimming = isSwimming(); + switch (player.p.dir) { + case 0: // down + if (swimming) + renderc(xo, yo + 4, 48, + 160 + (((player.p.swimTimer >> 4) & 1) << 3), 16, 8, 0); + else + renderc(xo, yo + 8, 0, 120 + (player.p.isCarrying ? 16 : 0), 16, 8, + walk == 0 ? 0 : 1); + renderc(xo, yo, 0, 112 + (player.p.isCarrying ? 16 : 0), 16, 8, + walk == 0 ? 0 : 1); break; - case 1: //up - aIndexBig = 2; - aIndexSmall = 1; + case 1: // up + if (swimming) + renderc(xo, yo + 4, 48, + 160 + (((player.p.swimTimer >> 4) & 1) << 3), 16, 8, 0); + else + renderc(xo, yo + 8, 16, 120 + (player.p.isCarrying ? 16 : 0), 16, 8, + walk == 0 ? 0 : 1); + renderc(xo, yo, 16, 112 + (player.p.isCarrying ? 16 : 0), 16, 8, + walk == 0 ? 0 : 1); break; - case 2: //left - aIndexBig = 7; - aIndexSmall = 3; + case 2: // left + if (swimming) + renderc(xo, yo + 4, 48, + 160 + (((player.p.swimTimer >> 4) & 1) << 3), 16, 8, 0); + else + renderc(xo, yo + 8, 32 + (walk << 4), + 120 + (player.p.isCarrying ? 16 : 0), 16, 8, 1); + renderc(xo, yo, 32 + (walk << 4), 112 + (player.p.isCarrying ? 16 : 0), + 16, 8, 1); break; - case 3: //right - aIndexBig = 4; - aIndexSmall = 2; + case 3: // right + if (swimming) + renderc(xo, yo + 4, 48, + 160 + (((player.p.swimTimer >> 4) & 1) << 3), 16, 8, 0); + else + renderc(xo, yo + 8, 32 + (walk << 4), + 120 + (player.p.isCarrying ? 16 : 0), 16, 8, 0); + renderc(xo, yo, 32 + (walk << 4), 112 + (player.p.isCarrying ? 16 : 0), + 16, 8, 0); 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; + if (player.p.isCarrying) { + renderFurniture(player.p.activeItem->id, xo, yo - 12); } - 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) - if (pd->entity.p.attackTimer > 0) { - switch (pd->entity.p.dir) { + if (player.p.attackTimer > 0) { + switch (player.p.dir) { case 0: - renderc(xo - pd->entity.p.ax, yo - pd->entity.p.ay + 12, 16, 168, 16, 8, 0); - renderItemIcon(pd->activeItem->id, pd->activeItem->countLevel, xo + 4, yo + 12); + renderc(xo - player.p.ax, yo - player.p.ay + 12, 16, 168, 16, 8, 0); + renderItemIcon(player.p.activeItem->id, + player.p.activeItem->countLevel, xo + 4, yo + 12); break; case 2: - renderc(xo - pd->entity.p.ax - 4, yo - pd->entity.p.ay, 32, 160, 8, 16, 0); - renderItemIcon(pd->activeItem->id, pd->activeItem->countLevel, xo - 4, yo + 4); + renderc(xo - player.p.ax - 4, yo - player.p.ay, 32, 160, 8, 16, 0); + renderItemIcon(player.p.activeItem->id, + player.p.activeItem->countLevel, xo - 4, yo + 4); break; case 3: - renderc(xo - pd->entity.p.ax + 12, yo - pd->entity.p.ay, 40, 160, 8, 16, 0); - renderItemIcon(pd->activeItem->id, pd->activeItem->countLevel, xo + 12, yo + 4); + renderc(xo - player.p.ax + 12, yo - player.p.ay, 40, 160, 8, 16, 0); + renderItemIcon(player.p.activeItem->id, + player.p.activeItem->countLevel, xo + 12, yo + 4); break; } } } -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); - } - } - } - } +void renderMenuBackground(int xScroll, int yScroll) { + sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + renderLightsToStencil(); + renderBackground(xScroll, yScroll); + resetStencilStuff(); } -void renderDayNight(PlayerData *pd) { - if(pd->entity.level==1 && (worldData.daytime<6000 || worldData.daytime>18000)) { - int color1 = 0x000C0C0C; - 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; - } else if(worldData.daytime>18000 && worldData.daytime<19000) { - 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 - resetStencilStuff(); - } -} - -void renderBackground(s8 level, int xScroll, int yScroll) { - if(level == 0) { +void renderBackground(int xScroll, int yScroll) { + if(currentLevel > 0) sf2d_draw_rectangle(0, 0, 400, 240, dirtColor[currentLevel]); // dirt color + else { 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) { - sf2d_draw_rectangle(0, 0, 400, 240, dungeonColor[1]); - } else { - sf2d_draw_rectangle(0, 0, 400, 240, dirtColor[level]); // dirt color } int xo = xScroll >> 4; int yo = yScroll >> 4; int x, y; for (x = xo; x <= 13 + xo; ++x) { for (y = yo; y <= 8 + yo; ++y) - renderTile(getTile(level, x, y), getData(level, x, y), level, x << 4, y << 4); + renderTile(getTile(x, y), x << 4, y << 4); } } @@ -1111,15 +858,6 @@ void renderFurniture(int itemID, int x, int y) { case ITEM_LANTERN: render16(x, y, 144, 128, 0); break; - case ITEM_LOOM: - render16(x, y, 224, 128, 0); - break; - case ITEM_ENCHANTER: - render16(x, y, 240, 128, 0); - break; - case ITEM_POTION_MAKER: - render16(x, y, 192, 168, 0); - break; } } @@ -1137,50 +875,24 @@ void renderEntity(Entity* e, int x, int y) { renderFurniture(e->entityFurniture.itemID, x - 8, y - 8); break; case ENTITY_ZOMBIE: - switch (e->hostile.dir) { + switch (e->zombie.dir) { case 0: // down - render16b(x - 8, y - 8, 64, 112, ((e->hostile.walkDist >> 4) & 1) == 0 ? 0 : 1, e->hostile.color); + render16b(x - 8, y - 8, 64, 112, + ((e->zombie.walkDist >> 4) & 1) == 0 ? 0 : 1, + e->zombie.color); break; case 1: // up - render16b(x - 8, y - 8, 80, 112, ((e->hostile.walkDist >> 4) & 1) == 0 ? 0 : 1, e->hostile.color); + render16b(x - 8, y - 8, 80, 112, + ((e->zombie.walkDist >> 4) & 1) == 0 ? 0 : 1, + e->zombie.color); break; case 2: // left - render16b(x - 8, y - 8, 96 + (((e->hostile.walkDist >> 4) & 1) << 4), 112, 1, e->hostile.color); + render16b(x - 8, y - 8, 96 + (((e->zombie.walkDist >> 4) & 1) << 4), + 112, 1, e->zombie.color); break; case 3: // right - render16b(x - 8, y - 8, 96 + (((e->hostile.walkDist >> 4) & 1) << 4), 112, 0, e->hostile.color); - break; - } - break; - case ENTITY_SKELETON: - switch (e->hostile.dir) { - case 0: // down - render16b(x - 8, y - 8, 0, 80, ((e->hostile.walkDist >> 4) & 1) == 0 ? 0 : 1, e->hostile.color); - break; - case 1: // up - render16b(x - 8, y - 8, 16, 80, ((e->hostile.walkDist >> 4) & 1) == 0 ? 0 : 1, e->hostile.color); - break; - case 2: // left - render16b(x - 8, y - 8, 32 + (((e->hostile.walkDist >> 4) & 1) << 4), 80, 1, e->hostile.color); - break; - case 3: // right - render16b(x - 8, y - 8, 32 + (((e->hostile.walkDist >> 4) & 1) << 4), 80, 0, e->hostile.color); - break; - } - break; - case ENTITY_KNIGHT: - switch (e->hostile.dir) { - case 0: // down - render16b(x - 8, y - 8, 64, 80, ((e->hostile.walkDist >> 4) & 1) == 0 ? 0 : 1, e->hostile.color); - break; - case 1: // up - render16b(x - 8, y - 8, 80, 80, ((e->hostile.walkDist >> 4) & 1) == 0 ? 0 : 1, e->hostile.color); - break; - case 2: // left - render16b(x - 8, y - 8, 96 + (((e->hostile.walkDist >> 4) & 1) << 4), 80, 1, e->hostile.color); - break; - case 3: // right - render16b(x - 8, y - 8, 96 + (((e->hostile.walkDist >> 4) & 1) << 4), 80, 0, e->hostile.color); + render16b(x - 8, y - 8, 96 + (((e->zombie.walkDist >> 4) & 1) << 4), + 112, 0, e->zombie.color); break; } break; @@ -1191,10 +903,10 @@ void renderEntity(Entity* e, int x, int y) { case ENTITY_AIRWIZARD: e->wizard.spriteAdjust = 0; if (e->wizard.health < 200) { - if (syncTickCount / 4 % 3 < 2) + if (tickCount / 4 % 3 < 2) e->wizard.spriteAdjust = 16; } else if (e->wizard.health < 1000) { - if (syncTickCount / 5 % 4 < 2) + if (tickCount / 5 % 4 < 2) e->wizard.spriteAdjust = 16; } switch (e->wizard.dir) { @@ -1216,22 +928,6 @@ void renderEntity(Entity* e, int x, int y) { break; } break; - case ENTITY_PASSIVE: - switch (e->passive.dir) { - case 0: // down - render16(x - 8, y - 8, (e->passive.mtype*64) + 0, 96, ((e->passive.walkDist >> 4) & 1) == 0 ? 0 : 1); - break; - case 1: // up - render16(x - 8, y - 8, (e->passive.mtype*64) + 16, 96, ((e->passive.walkDist >> 4) & 1) == 0 ? 0 : 1); - break; - case 2: // left - render16(x - 8, y - 8, (e->passive.mtype*64) + 32 + (((e->passive.walkDist >> 4) & 1) << 4), 96, 1); - break; - case 3: // right - render16(x - 8, y - 8, (e->passive.mtype*64) + 32 + (((e->passive.walkDist >> 4) & 1) << 4), 96, 0); - break; - } - break; case ENTITY_TEXTPARTICLE: x -= offsetX; y -= offsetY; @@ -1249,80 +945,13 @@ void renderEntity(Entity* e, int x, int y) { return; renderr(x, y, 200, 152, 0, e->spark.age * 0.0349); break; - case ENTITY_DRAGON: - switch (e->dragon.dir) { - case 0: // down - render32(x - 16, y - 16, 0+(e->dragon.animTimer/4 * 32), 256, 2); - break; - case 1: // up - render32(x - 16, y - 16, 0+(e->dragon.animTimer/4 * 32), 256, 0); - break; - case 2: // left - render32(x - 16, y - 16, 0+(e->dragon.animTimer/4 * 32), 288, 1); - break; - case 3: // right - render32(x - 16, y - 16, 0+(e->dragon.animTimer/4 * 32), 288, 0); - break; - } - break; - case ENTITY_DRAGONPROJECTILE: - if(e->dragonFire.type==0) { - renderr(x, y, 0, 320, 0, e->dragonFire.age * 0.349); - } else { - render(x, y, 8, 320 + (e->dragonFire.age/10)*8, 0); - } - break; - case ENTITY_MAGIC_PILLAR: - render16(x - 8, y - 8, 16, 320, 0); - break; - case ENTITY_ARROW: - if (e->arrow.age >= 200) - if (e->arrow.age / 6 % 2 == 0) - return; - - int abits = 0; - int ayp = 168; - if(e->arrow.xa<0) { - abits += 1; - } - if(e->arrow.ya<0) { - ayp += 8; - } - if(e->arrow.ya>0) { - ayp += 8; - abits += 2; - } - - switch (e->arrow.itemID) { - case ITEM_ARROW_WOOD: - render(x-2, y-2, 72, ayp, abits); - break; - case ITEM_ARROW_STONE: - render(x-2, y-2, 80, ayp, abits); - break; - case ITEM_ARROW_IRON: - render(x-2, y-2, 88, ayp, abits); - break; - case ITEM_ARROW_GOLD: - render(x-2, y-2, 96, ayp, abits); - break; - case ITEM_ARROW_GEM: - render(x-2, y-2, 104, ayp, abits); - break; - } - break; - case ENTITY_GLOWWORM: - render(x-4, y-4, 224, 112, 0); - break; - case ENTITY_NPC: - render16(x - 8, y - 8, (e->npc.type*16) + 0, 64, 0); } } -void renderEntities(u8 level, int x, int y, EntityManager* em) { +void renderEntities(int x, int y, EntityManager* em) { int i; - for (i = 0; i < em->lastSlot[level]; ++i) { - Entity e = em->entities[level][i]; + for (i = 0; i < em->lastSlot[currentLevel]; ++i) { + Entity e = em->entities[currentLevel][i]; if (e.x > x - 200 && e.y > y - 125 && e.x < x + 200 && e.y < y + 125) renderEntity(&e, e.x, e.y); } @@ -1363,50 +992,8 @@ void renderItemList(Inventory * inv, int xo, int yo, int x1, int y1, } } -void renderArmorList(Inventory * inv, int xo, int yo, int x1, int y1, - int selected) { - // If lastSlot is 0, then there are no items are in the inventory. - bool drawCursor = true; - int w = x1 - xo; - int h = y1 - yo - 2; - int i1 = inv->lastSlot; - if (i1 > h) - i1 = h; - int i; - int io = selected - h / 2; - int armorcount; - for (i = 0; i < i1; ++i) { - if(inv->items[i + io].id > 119 && inv->items[i + io].id < 141) { - armorcount = armorcount + 1; - } - } - if (selected < 0) { - drawCursor = false; - selected = 0; - } - if (io > inv->lastSlot - h) - io = armorcount; - if (io < 0) - io = 1; - for (i = 0; i < i1; ++i) { - if(inv->items[i + io].id > 119 && inv->items[i + io].id < 141) { - renderItemWithText(&inv->items[i + io], (1 + xo) << 4, - (i + 1 + yo) << 4); - } - } - - if (drawCursor) { - int yy = selected + 1 - io + yo; - sf2d_draw_rectangle((xo << 4) - (offsetX << 1), - (yy << 4) - (offsetY << 1), 12, 12, 0xFF); - drawText(">", (xo << 4), yy << 4); - sf2d_draw_rectangle(((xo + w) << 4) - 12 - (offsetX << 1), - (yy << 4) - (offsetY << 1), 12, 12, 0xFF); - drawText("<", ((xo + w) << 4) - 12, yy << 4); - } -} - -void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, int selected) { +void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, + int selected) { int size = r->size; if (size < 1) return; @@ -1426,16 +1013,16 @@ void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, int select int i, col; for (i = 0; i < i1; ++i) { int x = (1 + xo) << 4, y = (i + 1 + yo) << 4; - renderItemIcon(r->recipes[i + io].itemResult, r->recipes[i + io].itemAmountLevel, x >> 1, y >> 1); + renderItemIcon(r->recipes[i + io].itemResult, + r->recipes[i + io].itemAmountLevel, x >> 1, y >> 1); if (r->recipes[i + io].canCraft) col = 0xFFFFFFFF; 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); } int yy = selected + 1 - io + yo; @@ -1463,13 +1050,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 +1065,6 @@ void renderItemWithTextCentered(Item* item, int width, int y) { } void renderItemIcon(int itemID, int countLevel, int x, int y) { - int xd; - int yd; switch (itemID) { case ITEM_NULL: return; @@ -1523,7 +1108,7 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) { render(x, y, 0, 152, 0); break; case ITEM_WOOD: - render(x, y, 160, 168, 0); + render(x, y, 8, 152, 0); break; case ITEM_STONE: renderb(x, y, 16, 152, 0, rockColor[1]); @@ -1558,21 +1143,6 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) { case ITEM_APPLE: render(x, y, 80, 152, 0); break; - case ITEM_GOLD_APPLE: - render(x, y, 144, 168, 0); - break; - case ITEM_STRENGTH_POTION: - render(x, y, 176, 160, 0); - break; - case ITEM_SPEED_POTION: - render(x, y, 184, 160, 0); - break; - case ITEM_REGEN_POTION: - render(x, y, 192, 160, 0); - break; - case ITEM_SWIM_BREATH_POTION: - render(x, y, 200, 160, 0); - break; case ITEM_SLIME: renderb(x, y, 88, 152, 0, 0xFF4DC04D); break; @@ -1580,16 +1150,16 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) { renderb(x, y, 88, 152, 0, 0xFF383838); break; case ITEM_IRONORE: - renderb(x, y, 88, 152, 0, ironColor); + renderb(x, y, 88, 152, 0, 0xFF9999BC); break; case ITEM_GOLDORE: - renderb(x, y, 88, 152, 0, goldColor); + renderb(x, y, 88, 152, 0, 0xFF77CECE); break; case ITEM_IRONINGOT: - renderb(x, y, 96, 152, 0, ironColor); + renderb(x, y, 96, 152, 0, 0xFFC8C8DF); break; case ITEM_GOLDINGOT: - renderb(x, y, 96, 152, 0, goldColor); + renderb(x, y, 96, 152, 0, 0xFFBCEAEA); break; case ITEM_GLASS: render(x, y, 104, 152, 0); @@ -1597,127 +1167,8 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) { case ITEM_GEM: render(x, y, 112, 152, 0); break; - case ITEM_LOOM: - render(x, y, 120, 160, 0); - break; - case ITEM_ENCHANTER: - render(x, y, 144, 160, 0); - break; - case ITEM_POTION_MAKER: - render(x, y, 192, 168, 0); - break; - case ITEM_WALL_WOOD: - renderb(x, y, 224, 144, 0, woodColor); - break; - case ITEM_WALL_STONE: - renderb(x, y, 224, 144, 0, rockColor[1]); - break; - case ITEM_WALL_IRON: - renderb(x, y, 224, 144, 0, ironColor); - break; - case ITEM_WALL_GOLD: - renderb(x, y, 224, 144, 0, goldColor); - break; - case ITEM_WALL_GEM: - renderb(x, y, 224, 144, 0, gemColor); - break; - case ITEM_WOOL: - render(x, y, 64, 160, 0); - break; - case ITEM_STRING: - render(x, y, 72, 160, 0); - break; - case ITEM_PORK_RAW: - render(x, y, 80, 160, 0); - break; - case ITEM_PORK_COOKED: - render(x, y, 88, 160, 0); - break; - case ITEM_BEEF_RAW: - render(x, y, 96, 160, 0); - break; - case ITEM_BEEF_COOKED: - render(x, y, 104, 160, 0); - break; - case ITEM_LEATHER: - render(x, y, 112, 160, 0); - break; - case ITEM_ARROW_WOOD: - render(x, y, 72, 168, 0); - break; - case ITEM_ARROW_STONE: - render(x, y, 80, 168, 0); - break; - case ITEM_ARROW_IRON: - render(x, y, 88, 168, 0); - break; - case ITEM_ARROW_GOLD: - render(x, y, 96, 168, 0); - break; - case ITEM_ARROW_GEM: - render(x, y, 104, 168, 0); - break; - case ITEM_BONE: - render(x, y, 128, 160, 0); - break; - case ITEM_DUNGEON_KEY: - render(x, y, 136, 160, 0); - break; - case ITEM_WIZARD_SUMMON: - render(x, y, 152, 160, 0); - break; - case ITEM_DRAGON_EGG: - render(x, y, 160, 160, 0); - break; - case ITEM_DRAGON_SCALE: - render(x, y, 168, 160, 0); - break; - case ITEM_BOOKSHELVES: - render(x, y, 232, 144, 0); - break; - case ITEM_MAGIC_DUST: - render(x, y, 200, 152, 0); - break; - case ITEM_COIN: - render(x, y, 208, 152, 0); - break; case TOOL_BUCKET: render(x, y, 200 + countLevel * 8, 144, 0); break; - 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); - } - 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; } } diff --git a/source/Render.h b/source/Render.h old mode 100755 new mode 100644 index e967538..237139e --- a/source/Render.h +++ b/source/Render.h @@ -1,7 +1,7 @@ #pragma once #include <3ds.h> #include -#include +#include #include #include #include "Globals.h" @@ -9,42 +9,40 @@ sf2d_texture *playerLightBake; sf2d_texture *lanternLightBake; -sf2d_texture *glowwormLightBake; -sf2d_texture *glowwormBigLightBake; int offsetX, offsetY; -int playerScale; void render(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits); void renderb(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, u32 color); void renderr(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, float rotate); -void renderc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, u8 bits); -void renderbc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, u8 bits, u32 color); +void renderc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, + u8 bits); +void renderbc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, + u8 bits, u32 color); void render16(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits); -void render16c(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, float scaleX, float scaleY); +void render16c(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, float scaleX, + float scaleY); void render16b(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, u32 color); void render16s(s32 xp, s32 yp, u32 tile, u8 bits, u32 color); -void render32(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits); void renderTitle(int x, int y); void renderFrame(int x1, int y1, int x2, int y2, u32 bgColor); -void renderTile(int i, int d, u8 level, int x, int y); -void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile); -void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile); -void renderBackground(s8 level, int xScroll, int yScroll); -void renderWeather(u8 level, int xScroll, int yScroll); -void renderDayNight(PlayerData *pd); +void renderTile(int i, int x, int y); +void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile, u32 color); +void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile, u32 color); +void renderBackground(int xScroll, int yScroll); +void renderMenuBackground(int xScroll, int yScroll); //Renders the darkness void renderButtonIcon(u32 icon, int x, int y, float scale); void bakeLights(); void freeLightBakes(); -void renderLightsToStencil(PlayerData *pd, bool force, bool invert, bool rplayer); +void renderLightsToStencil(); void resetStencilStuff(); void bakeLight(sf2d_texture* texture, int x, int y, int r); void renderLight(int x, int y, sf2d_texture* texture); -void renderGui(PlayerData *pd); -void renderZoomedMap(PlayerData *pd); -void renderPlayer(PlayerData *pd); +void renderGui(); +void renderZoomedMap(); +void renderPlayer(); void drawText(char * msg, u32 x, u32 y); void drawSizedText(char * msg, u32 x, u32 y, float size); @@ -54,11 +52,12 @@ void drawSizedTextColor(char * msg, int x, int y, float size, u32 color); void renderFurniture(int itemID, int x, int y); void renderEntity(Entity* e, int x, int y); -void renderEntities(u8 level, int x, int y, EntityManager* em); +void renderEntities(int x, int y, EntityManager* em); -void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, int selected); -void renderItemList(Inventory * inv, int xo, int yo, int x1, int y1, int selected); -void renderArmorList(Inventory * inv, int xo, int yo, int x1, int y1, int selected); +void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, + int selected); +void renderItemList(Inventory * inv, int xo, int yo, int x1, int y1, + int selected); void renderItemWithText(Item* item, int x, int y); void renderItemStuffWithText(int itemID, int itemCL, bool onlyOne, int x, int y); void renderItemWithTextCentered(Item* item, int width, int y); diff --git a/source/SaveLoad.c b/source/SaveLoad.c old mode 100755 new mode 100644 index ecd1067..37e5536 --- a/source/SaveLoad.c +++ b/source/SaveLoad.c @@ -1,663 +1,251 @@ #include "SaveLoad.h" -#include "ZipHelper.h" +s16 calculateImportantEntites(EntityManager * eManager, int level){ + int i; + s16 count = 0; + for(i = 0; i < eManager->lastSlot[level]; ++i){ + switch(eManager->entities[level][i].type){ + case ENTITY_AIRWIZARD: + case ENTITY_SLIME: + case ENTITY_ZOMBIE: + case ENTITY_ITEM: + case ENTITY_FURNITURE: + count++; + break; + } + } + return count; +} bool entityIsImportant(Entity * e){ - switch(e->type){ - case ENTITY_AIRWIZARD: - case ENTITY_SLIME: - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - case ENTITY_ITEM: - case ENTITY_FURNITURE: - case ENTITY_PASSIVE: - case ENTITY_GLOWWORM: - case ENTITY_DRAGON: - case ENTITY_NPC: - return true; - default: - return false; - } + switch(e->type){ + case ENTITY_AIRWIZARD: + case ENTITY_SLIME: + case ENTITY_ZOMBIE: + case ENTITY_ITEM: + case ENTITY_FURNITURE: + return true; + default: + return false; + } } -s16 calculateImportantEntites(EntityManager * eManager, int level){ - int i; - s16 count = 0; - for(i = 0; i < eManager->lastSlot[level]; ++i){ - if(entityIsImportant(&eManager->entities[level][i])){ - count++; - } - } - return count; +void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData){ + FILE * file = fopen(filename, "wb"); + int i,j; + + // Player Data + fwrite(&player->p.score, sizeof(int), 1, file); + fwrite(&player->p.hasWonSaved, sizeof(bool), 1, file); + fwrite(&player->p.health, sizeof(s16), 1, file); + fwrite(&player->x, sizeof(s16), 1, file); + fwrite(&player->y, sizeof(s16), 1, file); + fwrite(¤tLevel, sizeof(s8), 1, file); + + // Inventory Data + fwrite(&eManager->nextInv, sizeof(s16), 1, file); // write amount of inventories. + for(i = 0; i < eManager->nextInv; ++i) { + fwrite(&eManager->invs[i].lastSlot, sizeof(s16), 1, file); // write amount of items in inventory; + for(j = 0; j < eManager->invs[i].lastSlot; ++j) { + fwrite(&eManager->invs[i].items[j].id, sizeof(s16), 1, file); // write ID of item + fwrite(&eManager->invs[i].items[j].countLevel, sizeof(s16), 1, file); // write count/level of item + fwrite(&eManager->invs[i].items[j].onlyOne, sizeof(bool), 1, file); + if(eManager->invs[i].items[j].id == ITEM_CHEST){ + int invIndex = eManager->invs[i].items[j].chestPtr - eManager->invs; + fwrite(&invIndex, sizeof(int), 1, file); + } + } + } + + // Entity Data + for(i = 0; i < 5; ++i){ + int amount = calculateImportantEntites(eManager,i); + fwrite(&amount, sizeof(s16), 1, file); // read amount of entities in level. + for(j = 0; j < eManager->lastSlot[i]; ++j){ + if(!entityIsImportant(&eManager->entities[i][j])) continue; + fwrite(&eManager->entities[i][j].type, sizeof(s16), 1, file); // write entity's type ID + fwrite(&eManager->entities[i][j].x, sizeof(s16), 1, file); // write entity's x coordinate + fwrite(&eManager->entities[i][j].y, sizeof(s16), 1, file); // write entity's y coordinate + switch(eManager->entities[i][j].type){ + case ENTITY_AIRWIZARD: + fwrite(&eManager->entities[i][j].wizard.health, sizeof(s16), 1, file); + break; + case ENTITY_SLIME: + fwrite(&eManager->entities[i][j].slime.health, sizeof(s16), 1, file); + fwrite(&eManager->entities[i][j].slime.lvl, sizeof(s8), 1, file); + break; + case ENTITY_ZOMBIE: + fwrite(&eManager->entities[i][j].zombie.health, sizeof(s16), 1, file); + fwrite(&eManager->entities[i][j].zombie.lvl, sizeof(s8), 1, file); + break; + case ENTITY_ITEM: + fwrite(&eManager->entities[i][j].entityItem.item.id, sizeof(s16), 1, file); + fwrite(&eManager->entities[i][j].entityItem.item.countLevel, sizeof(s16), 1, file); + fwrite(&eManager->entities[i][j].entityItem.age, sizeof(s16), 1, file); + break; + case ENTITY_FURNITURE: + fwrite(&eManager->entities[i][j].entityFurniture.itemID, sizeof(s16), 1, file); + int invIndex = eManager->entities[i][j].entityFurniture.inv - eManager->invs; + fwrite(&invIndex, sizeof(int), 1, file); + break; + } + } + } + + // Map Data + fwrite(map, sizeof(u8), 128*128*5, file); // Map Tile IDs, 128*128*5 bytes = 80KB + fwrite(mapData, sizeof(u8), 128*128*5, file); // Map Tile Data (Damage done to trees/rocks, age of wheat & saplings, etc). 80KB + + fclose(file); } -//helper methods -char **files; -int fileCount; - -void saveTrackFileReset() { - if(files!=NULL) { - for(int i=0; i0) { - fwrite(buffer, 1, size, out); - } - } while(size>0); - - fclose(in); - fclose(out); - - return true; -} - -//internal save methods -void saveInventory(Inventory *inv, EntityManager *eManager, FILE *file) { - fwrite(&inv->lastSlot, sizeof(s16), 1, file); // write amount of items in inventory; - for(int j = 0; j < inv->lastSlot; ++j) { - fwrite(&(inv->items[j].id), sizeof(s16), 1, file); // write ID of item - fwrite(&(inv->items[j].countLevel), sizeof(s16), 1, file); // write count/level of item - fwrite(&(inv->items[j].onlyOne), sizeof(bool), 1, file); - if(inv->items[j].id == ITEM_CHEST){ - int invIndex = inv->items[j].chestPtr - eManager->invs; - fwrite(&invIndex, sizeof(int), 1, file); - } - } -} - -void saveWorldInternal(char *filename, EntityManager *eManager, WorldData *worldData) { - FILE * file = fopen(filename, "wb"); //TODO: should be checked - - int i, j; - - //write savefile version - int version = SAVE_VERSION; - fwrite(&version, sizeof(int), 1, file); - - // Inventory Data - fwrite(&eManager->nextInv, sizeof(s16), 1, file); // write amount of inventories. - for(i = 0; i < eManager->nextInv; ++i) { - saveInventory(&(eManager->invs[i]), eManager, file); - } - - // Entity Data - for(i = 0; i < 5; ++i) { //for every level (except dungeon of course) - int amount = calculateImportantEntites(eManager,i); - fwrite(&amount, sizeof(s16), 1, file); // read amount of entities in level. - for(j = 0; j < eManager->lastSlot[i]; ++j){ - if(!entityIsImportant(&eManager->entities[i][j])) continue; - - fwrite(&eManager->entities[i][j].type, sizeof(s16), 1, file); // write entity's type ID - fwrite(&eManager->entities[i][j].x, sizeof(s16), 1, file); // write entity's x coordinate - fwrite(&eManager->entities[i][j].y, sizeof(s16), 1, file); // write entity's y coordinate - switch(eManager->entities[i][j].type){ - case ENTITY_AIRWIZARD: - fwrite(&eManager->entities[i][j].wizard.health, sizeof(s16), 1, file); - break; - case ENTITY_SLIME: - fwrite(&eManager->entities[i][j].slime.health, sizeof(s16), 1, file); - fwrite(&eManager->entities[i][j].slime.lvl, sizeof(s8), 1, file); - break; - case ENTITY_ZOMBIE: - case ENTITY_SKELETON: - case ENTITY_KNIGHT: - fwrite(&eManager->entities[i][j].hostile.health, sizeof(s16), 1, file); - fwrite(&eManager->entities[i][j].hostile.lvl, sizeof(s8), 1, file); - break; - case ENTITY_ITEM: - fwrite(&eManager->entities[i][j].entityItem.item.id, sizeof(s16), 1, file); - fwrite(&eManager->entities[i][j].entityItem.item.countLevel, sizeof(s16), 1, file); - fwrite(&eManager->entities[i][j].entityItem.age, sizeof(s16), 1, file); - break; - case ENTITY_FURNITURE: - fwrite(&eManager->entities[i][j].entityFurniture.itemID, sizeof(s16), 1, file); - int invIndex = eManager->entities[i][j].entityFurniture.inv - eManager->invs; - fwrite(&invIndex, sizeof(int), 1, file); - break; - case ENTITY_PASSIVE: - fwrite(&eManager->entities[i][j].passive.health, sizeof(s16), 1, file); - fwrite(&eManager->entities[i][j].passive.mtype, sizeof(u8), 1, file); - break; - case ENTITY_DRAGON: - fwrite(&eManager->entities[i][j].dragon.health, sizeof(s16), 1, file); - break; - case ENTITY_NPC: - fwrite(&eManager->entities[i][j].npc.type, sizeof(u8), 1, file); - break; - } - } - } - - // Day/season Data - fwrite(&worldData->daytime, sizeof(u16), 1, file); - fwrite(&worldData->day, sizeof(int), 1, file); - fwrite(&worldData->season, sizeof(u8), 1, file); - fwrite(&worldData->rain, sizeof(bool), 1, file); - - // Compass Data - fwrite(worldData->compassData, sizeof(u8), 6*3, file); //x,y of choosen stair and count per level - - // Map Data - //Don't write or load dungeon, so only first 5 levels not 6 - fwrite(worldData->map, sizeof(u8), 128*128*5, file); // Map Tile IDs, 128*128*5 bytes = 80KB - fwrite(worldData->data, sizeof(u8), 128*128*5, file); // Map Tile Data (Damage done to trees/rocks, age of wheat & saplings, etc). 80KB - - fclose(file); -} - -void savePlayerInternal(char *filename, PlayerData *player, EntityManager *eManager) { - FILE * file = fopen(filename, "wb"); //TODO: should be checked - - int i; - - //write savefile version - int version = SAVE_VERSION; - fwrite(&version, sizeof(int), 1, file); - - // basic player info - fwrite(&player->score, sizeof(int), 1, file); - fwrite(&player->isSpawned, sizeof(bool), 1, file); - fwrite(&player->entity.p.hasWonSaved, sizeof(bool), 1, file); - fwrite(&player->entity.p.health, sizeof(s16), 1, file); - fwrite(&player->entity.x, sizeof(s16), 1, file); - fwrite(&player->entity.y, sizeof(s16), 1, file); - fwrite(&player->entity.level, sizeof(s8), 1, file); - - saveInventory(&(player->inventory), eManager, file); - - // Sprite info - fwrite(&(player->sprite.choosen), sizeof(bool), 1, file); - fwrite(&(player->sprite.legs), sizeof(u8), 1, file); - fwrite(&(player->sprite.body), sizeof(u8), 1, file); - fwrite(&(player->sprite.arms), sizeof(u8), 1, file); - fwrite(&(player->sprite.head), sizeof(u8), 1, file); - fwrite(&(player->sprite.eyes), sizeof(u8), 1, file); - - // Minimap Data - fwrite(player->minimapData, sizeof(u8), 128*128, file); // Minimap, visibility data 16KB - - // Quest Data - fwrite(&(player->questManager.size), sizeof(int), 1, file); - for(i = 0; i < player->questManager.size; ++i) { - fwrite(&(player->questManager.questlines[i].currentQuest), sizeof(int), 1, file); - fwrite(&(player->questManager.questlines[i].currentQuestDone), sizeof(bool), 1, file); - } - - //Potion Data - fwrite(&UnderStrengthEffect, sizeof(bool), 1, file); - fwrite(&UnderSpeedEffect, sizeof(bool), 1, file); - fwrite(®ening, sizeof(bool), 1, file); - fwrite(&UnderSwimBreathEffect, sizeof(bool), 1, file); - fwrite(&player->entity.p.strengthTimer, sizeof(int), 1, file); - fwrite(&player->entity.p.speedTimer, sizeof(int), 1, file); - fwrite(&player->entity.p.swimBreathTimer, sizeof(int), 1, file); - fwrite(&player->entity.p.regenTimer, sizeof(int), 1, file); - - fclose(file); -} - -//internal load methods -void loadInventory(Inventory *inv, EntityManager *eManager, FILE *file) { - fread(&(inv->lastSlot), sizeof(s16), 1, file); // read amount of items in inventory; - for(int j = 0; j < inv->lastSlot; ++j) { - fread(&(inv->items[j].id), sizeof(s16), 1, file); // write ID of item - fread(&(inv->items[j].countLevel), sizeof(s16), 1, file); // write count/level of item - fread(&(inv->items[j].onlyOne), sizeof(bool), 1, file); - inv->items[j].invPtr = (int*)inv; // setup Inventory pointer - inv->items[j].slotNum = j; // setup slot number - if(inv->items[j].id == ITEM_CHEST){ // for chest item specifically. - int invIndex; - fread(&invIndex, sizeof(int), 1, file); - inv->items[j].chestPtr = (Inventory*)&eManager->invs[invIndex]; // setup chest inventory pointer. - } - } -} - -void loadWorldInternal(char *filename, EntityManager *eManager, WorldData *worldData) { - FILE * file = fopen(filename, "rb"); //TODO: should be checked - - int i, j; - - //read savefile version - int version; - fread(&version, sizeof(int), 1, file); - - // Inventory Data - fread(&eManager->nextInv, sizeof(s16), 1, file); - for(i = 0; i < eManager->nextInv; ++i) { - loadInventory(&(eManager->invs[i]), eManager, file); - } - - // Entity Data - for(i = 0; i < 5; ++i){ - fread(&eManager->lastSlot[i], sizeof(s16), 1, file); // read amount of entities in level. - for(j = 0; j < eManager->lastSlot[i]; ++j){ - fread(&eManager->entities[i][j].type, sizeof(s16), 1, file); // read entity's type ID - fread(&eManager->entities[i][j].x, sizeof(s16), 1, file); // read entity's x coordinate - fread(&eManager->entities[i][j].y, sizeof(s16), 1, file); // read entity's y coordinate - eManager->entities[i][j].slotNum = j; - switch(eManager->entities[i][j].type){ - case ENTITY_SMASHPARTICLE: - eManager->entities[i][j].level = i; - eManager->entities[i][j].smashParticle.age = 300; - eManager->entities[i][j].canPass = true; - break; - case ENTITY_TEXTPARTICLE: - eManager->entities[i][j].level = i; - eManager->entities[i][j].canPass = true; - eManager->entities[i][j].textParticle.age = 59; - eManager->entities[i][j].textParticle.text = NULL; - eManager->entities[i][j].textParticle.xx = eManager->entities[i][j].x; - eManager->entities[i][j].textParticle.yy = eManager->entities[i][j].y; - eManager->entities[i][j].textParticle.zz = 2; - eManager->entities[i][j].textParticle.xa = 0; - eManager->entities[i][j].textParticle.ya = 0; - eManager->entities[i][j].textParticle.za = 0; - break; - case ENTITY_SPARK: - eManager->entities[i][j].level = i; - eManager->entities[i][j].spark.age = 300; - break; - case ENTITY_AIRWIZARD: - fread(&eManager->entities[i][j].wizard.health, sizeof(s16), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].wizard.dir = 0; - eManager->entities[i][j].wizard.attackDelay = 0; - eManager->entities[i][j].wizard.attackTime = 0; - eManager->entities[i][j].wizard.attackType = 0; - eManager->entities[i][j].wizard.xa = 0; - eManager->entities[i][j].wizard.ya = 0; - eManager->entities[i][j].xr = 4; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = true; - break; - case ENTITY_SLIME: - fread(&eManager->entities[i][j].slime.health, sizeof(s16), 1, file); - fread(&eManager->entities[i][j].slime.lvl, sizeof(s8), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].slime.xa = 0; - eManager->entities[i][j].slime.ya = 0; - eManager->entities[i][j].slime.dir = 0; - eManager->entities[i][j].xr = 4; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - switch(eManager->entities[i][j].slime.lvl){ - case 2: eManager->entities[i][j].slime.color = 0xFF8282CC; break; - case 3: eManager->entities[i][j].slime.color = 0xFFEFEFEF; break; - case 4: eManager->entities[i][j].slime.color = 0xFFAA6262; break; - default: eManager->entities[i][j].slime.color = 0xFF95DB95; break; - } - break; - case ENTITY_ZOMBIE: - fread(&eManager->entities[i][j].hostile.health, sizeof(s16), 1, file); - fread(&eManager->entities[i][j].hostile.lvl, sizeof(s8), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].hostile.dir = 0; - eManager->entities[i][j].xr = 4; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - switch(eManager->entities[i][j].hostile.lvl){ - case 2: eManager->entities[i][j].hostile.color = 0xFF8282CC; break; - case 3: eManager->entities[i][j].hostile.color = 0xFFEFEFEF; break; - case 4: eManager->entities[i][j].hostile.color = 0xFFAA6262; break; - default: eManager->entities[i][j].hostile.color = 0xFF95DB95; break; - } - break; - case ENTITY_SKELETON: - fread(&eManager->entities[i][j].hostile.health, sizeof(s16), 1, file); - fread(&eManager->entities[i][j].hostile.lvl, sizeof(s8), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].hostile.dir = 0; - eManager->entities[i][j].hostile.randAttackTime = 0; - eManager->entities[i][j].xr = 4; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - switch(eManager->entities[i][j].hostile.lvl){ - case 2: eManager->entities[i][j].hostile.color = 0xFFC4C4C4; break; - case 3: eManager->entities[i][j].hostile.color = 0xFFA0A0A0; break; - case 4: eManager->entities[i][j].hostile.color = 0xFF7A7A7A; break; - default: eManager->entities[i][j].hostile.color = 0xFFFFFFFF; break; - } - break; - case ENTITY_KNIGHT: - fread(&eManager->entities[i][j].hostile.health, sizeof(s16), 1, file); - fread(&eManager->entities[i][j].hostile.lvl, sizeof(s8), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].hostile.dir = 0; - eManager->entities[i][j].xr = 4; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - switch(eManager->entities[i][j].hostile.lvl){ - case 2: eManager->entities[i][j].hostile.color = 0xFF0000C6; break; - case 3: eManager->entities[i][j].hostile.color = 0xFF00A3C6; break; - case 4: eManager->entities[i][j].hostile.color = 0xFF707070; break; - default: eManager->entities[i][j].hostile.color = 0xFFFFFFFF; break; - } - break; - case ENTITY_ITEM: - //eManager->entities[i][j].entityItem.item = newItem(0,0); - fread(&eManager->entities[i][j].entityItem.item.id, sizeof(s16), 1, file); - fread(&eManager->entities[i][j].entityItem.item.countLevel, sizeof(s16), 1, file); - fread(&eManager->entities[i][j].entityItem.age, sizeof(s16), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].entityItem.age = 0; - eManager->entities[i][j].xr = 3; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - eManager->entities[i][j].entityItem.xx = eManager->entities[i][j].x; - eManager->entities[i][j].entityItem.yy = eManager->entities[i][j].y; - eManager->entities[i][j].entityItem.zz = 2; - eManager->entities[i][j].entityItem.xa = 0; - eManager->entities[i][j].entityItem.ya = 0; - eManager->entities[i][j].entityItem.za = 0; - break; - case ENTITY_FURNITURE: - fread(&eManager->entities[i][j].entityFurniture.itemID, sizeof(s16), 1, file); - int invIndex; - fread(&invIndex, sizeof(int), 1, file); - eManager->entities[i][j].entityFurniture.inv = &eManager->invs[invIndex]; - eManager->entities[i][j].xr = 3; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - if(eManager->entities[i][j].entityFurniture.itemID == ITEM_LANTERN) eManager->entities[i][j].entityFurniture.r = 8; - break; - case ENTITY_PASSIVE: - fread(&eManager->entities[i][j].passive.health, sizeof(s16), 1, file); - fread(&eManager->entities[i][j].passive.mtype, sizeof(u8), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].passive.dir = 0; - eManager->entities[i][j].xr = 4; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - break; - case ENTITY_GLOWWORM: - eManager->entities[i][j].glowworm.xa = 0; - eManager->entities[i][j].glowworm.ya = 0; - eManager->entities[i][j].glowworm.randWalkTime = 0; - eManager->entities[i][j].glowworm.waitTime = 0; - break; - case ENTITY_DRAGON: - fread(&eManager->entities[i][j].dragon.health, sizeof(s16), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].dragon.dir = 0; - eManager->entities[i][j].dragon.attackDelay = 0; - eManager->entities[i][j].dragon.attackTime = 0; - eManager->entities[i][j].dragon.attackType = 0; - eManager->entities[i][j].dragon.animTimer = 0; - eManager->entities[i][j].dragon.xa = 0; - eManager->entities[i][j].dragon.ya = 0; - eManager->entities[i][j].xr = 8; - eManager->entities[i][j].yr = 8; - eManager->entities[i][j].canPass = true; - break; - case ENTITY_NPC: - fread(&eManager->entities[i][j].npc.type, sizeof(u8), 1, file); - eManager->entities[i][j].level = i; - eManager->entities[i][j].hurtTime = 0; - eManager->entities[i][j].xKnockback = 0; - eManager->entities[i][j].yKnockback = 0; - eManager->entities[i][j].xr = 4; - eManager->entities[i][j].yr = 3; - eManager->entities[i][j].canPass = false; - break; - } - } - } - - // Day/season Data - fread(&worldData->daytime, sizeof(u16), 1, file); - fread(&worldData->day, sizeof(int), 1, file); - fread(&worldData->season, sizeof(u8), 1, file); - fread(&worldData->rain, sizeof(bool), 1, file); - - // Compass Data - fread(worldData->compassData, sizeof(u8), 6*3, file); //x,y of choosen stair and count per level - - // Map Data - //Don't write or load dungeon, so only first 5 levels not 6 - fread(worldData->map, sizeof(u8), 128*128*5, file); // Map Tile IDs, 128*128*5 bytes = 80KB - fread(worldData->data, sizeof(u8), 128*128*5, file); // Map Tile Data (Damage done to trees/rocks, age of wheat & saplings, etc). 80KB - - fclose(file); -} - -void loadPlayerInternal(char *filename, PlayerData *player, EntityManager *eManager) { - FILE * file = fopen(filename, "rb"); //TODO: should be checked - - int i; - - //read savefile version - int version; - fread(&version, sizeof(int), 1, file); - - // basic player info - fread(&player->score, sizeof(int), 1, file); - fread(&player->isSpawned, sizeof(bool), 1, file); - fread(&player->entity.p.hasWonSaved, sizeof(bool), 1, file); - fread(&player->entity.p.health, sizeof(s16), 1, file); - fread(&player->entity.x, sizeof(s16), 1, file); - fread(&player->entity.y, sizeof(s16), 1, file); - fread(&player->entity.level, sizeof(s8), 1, file); - - loadInventory(&(player->inventory), eManager, file); - - // Sprite info - fread(&(player->sprite.choosen), sizeof(bool), 1, file); - fread(&(player->sprite.legs), sizeof(u8), 1, file); - fread(&(player->sprite.body), sizeof(u8), 1, file); - fread(&(player->sprite.arms), sizeof(u8), 1, file); - fread(&(player->sprite.head), sizeof(u8), 1, file); - fread(&(player->sprite.eyes), sizeof(u8), 1, file); - - // Minimap Data - fread(player->minimapData, sizeof(u8), 128*128, file); // Minimap, visibility data 16KB - - // Quest Data - fread(&(player->questManager.size), sizeof(int), 1, file); - for(i = 0; i < player->questManager.size; ++i) { - fread(&(player->questManager.questlines[i].currentQuest), sizeof(int), 1, file); - fread(&(player->questManager.questlines[i].currentQuestDone), sizeof(bool), 1, file); - } - - //Potion Data - fread(&UnderStrengthEffect, sizeof(bool), 1, file); - fread(&UnderSpeedEffect, sizeof(bool), 1, file); - fread(®ening, sizeof(bool), 1, file); - fread(&UnderSwimBreathEffect, sizeof(bool), 1, file); - fread(&player->entity.p.strengthTimer, sizeof(int), 1, file); - fread(&player->entity.p.speedTimer, sizeof(int), 1, file); - fread(&player->entity.p.swimBreathTimer, sizeof(int), 1, file); - fread(&player->entity.p.regenTimer, sizeof(int), 1, file); - - fclose(file); -} - - -bool saveWorld(char *filename, EntityManager *eManager, WorldData *worldData, PlayerData *players, int playerCount) { - //check if old save file exists - bool exists = false; - FILE *testFile = fopen(filename, "rb"); - if(testFile) { - fclose(testFile); - exists = true; - } - - saveTrackFileReset(); - - if(exists) { - //create backup copy - char *filenameBackup = malloc(sizeof(filename)+4+1); - if(filenameBackup==NULL) { - return false; - } - strcpy(filenameBackup, filename); - strcat(filenameBackup, ".bak"); - if(!saveFileCopy(filenameBackup, filename)) { - return false; - } - - //extract files and keep track of references - if(unzipAndLoad(filename, &saveTrackFile, SAVE_COMMENT, ZIPHELPER_KEEP_FILES)!=0) { - saveDeleteTrackedFiles(); - return false; - } - - remove(filename); - } - - //save world data - saveWorldInternal("main.wld", eManager, worldData); - saveTrackFile("main.wld"); - - //save player data of active players - for(int i=0; ip.score, sizeof(int), 1, file); + fread(&player->p.hasWonSaved, sizeof(bool), 1, file); + fread(&player->p.health, sizeof(s16), 1, file); + fread(&player->x, sizeof(s16), 1, file); + fread(&player->y, sizeof(s16), 1, file); + fread(¤tLevel, sizeof(s8), 1, file); + + fread(&eManager->nextInv, sizeof(s16), 1, file); + for(i = 0; i < eManager->nextInv; ++i) { + fread(&eManager->invs[i].lastSlot, sizeof(s16), 1, file); // read amount of items in inventory; + for(j = 0; j < eManager->invs[i].lastSlot; ++j) { + fread(&eManager->invs[i].items[j].id, sizeof(s16), 1, file); // write ID of item + fread(&eManager->invs[i].items[j].countLevel, sizeof(s16), 1, file); // write count/level of item + fread(&eManager->invs[i].items[j].onlyOne, sizeof(bool), 1, file); + eManager->invs[i].items[j].invPtr = (int*)&eManager->invs[i]; // setup Inventory pointer + eManager->invs[i].items[j].slotNum = j; // setup slot number + if(eManager->invs[i].items[j].id == ITEM_CHEST){ // for chest item specifically. + int invIndex; + fread(&invIndex, sizeof(int), 1, file); + eManager->invs[i].items[j].chestPtr = (Inventory*)&eManager->invs[invIndex]; // setup chest inventory pointer. + } + } + } + + for(i = 0; i < 5; ++i){ + fread(&eManager->lastSlot[i], sizeof(s16), 1, file); // read amount of entities in level. + for(j = 0; j < eManager->lastSlot[i]; ++j){ + fread(&eManager->entities[i][j].type, sizeof(s16), 1, file); // read entity's type ID + fread(&eManager->entities[i][j].x, sizeof(s16), 1, file); // read entity's x coordinate + fread(&eManager->entities[i][j].y, sizeof(s16), 1, file); // read entity's y coordinate + eManager->entities[i][j].slotNum = j; + switch(eManager->entities[i][j].type){ + case ENTITY_SMASHPARTICLE: + eManager->entities[i][j].level = i; + eManager->entities[i][j].smashParticle.age = 300; + eManager->entities[i][j].canPass = true; + break; + case ENTITY_TEXTPARTICLE: + eManager->entities[i][j].level = i; + eManager->entities[i][j].canPass = true; + eManager->entities[i][j].textParticle.age = 59; + eManager->entities[i][j].textParticle.text = NULL; + eManager->entities[i][j].textParticle.xx = eManager->entities[i][j].x; + eManager->entities[i][j].textParticle.yy = eManager->entities[i][j].y; + eManager->entities[i][j].textParticle.zz = 2; + eManager->entities[i][j].textParticle.xa = 0; + eManager->entities[i][j].textParticle.ya = 0; + eManager->entities[i][j].textParticle.za = 0; + break; + case ENTITY_SPARK: + eManager->entities[i][j].level = i; + eManager->entities[i][j].spark.age = 300; + break; + case ENTITY_AIRWIZARD: + fread(&eManager->entities[i][j].wizard.health, sizeof(s16), 1, file); + eManager->entities[i][j].level = i; + eManager->entities[i][j].hurtTime = 0; + eManager->entities[i][j].xKnockback = 0; + eManager->entities[i][j].yKnockback = 0; + eManager->entities[i][j].wizard.dir = 0; + eManager->entities[i][j].wizard.attackDelay = 0; + eManager->entities[i][j].wizard.attackTime = 0; + eManager->entities[i][j].wizard.attackType = 0; + eManager->entities[i][j].wizard.xa = 0; + eManager->entities[i][j].wizard.ya = 0; + eManager->entities[i][j].xr = 4; + eManager->entities[i][j].yr = 3; + eManager->entities[i][j].canPass = true; + break; + case ENTITY_SLIME: + fread(&eManager->entities[i][j].slime.health, sizeof(s16), 1, file); + fread(&eManager->entities[i][j].slime.lvl, sizeof(s8), 1, file); + eManager->entities[i][j].level = i; + eManager->entities[i][j].hurtTime = 0; + eManager->entities[i][j].xKnockback = 0; + eManager->entities[i][j].yKnockback = 0; + eManager->entities[i][j].slime.xa = 0; + eManager->entities[i][j].slime.ya = 0; + eManager->entities[i][j].slime.dir = 0; + eManager->entities[i][j].xr = 4; + eManager->entities[i][j].yr = 3; + eManager->entities[i][j].canPass = false; + switch(eManager->entities[i][j].slime.lvl){ + case 2: eManager->entities[i][j].slime.color = 0xFF8282CC; break; + case 3: eManager->entities[i][j].slime.color = 0xFFEFEFEF; break; + case 4: eManager->entities[i][j].slime.color = 0xFFAA6262; break; + default: eManager->entities[i][j].slime.color = 0xFF95DB95; break; + } + break; + case ENTITY_ZOMBIE: + fread(&eManager->entities[i][j].zombie.health, sizeof(s16), 1, file); + fread(&eManager->entities[i][j].zombie.lvl, sizeof(s8), 1, file); + eManager->entities[i][j].level = i; + eManager->entities[i][j].hurtTime = 0; + eManager->entities[i][j].xKnockback = 0; + eManager->entities[i][j].yKnockback = 0; + eManager->entities[i][j].zombie.dir = 0; + eManager->entities[i][j].xr = 4; + eManager->entities[i][j].yr = 3; + eManager->entities[i][j].canPass = false; + switch(eManager->entities[i][j].zombie.lvl){ + case 2: eManager->entities[i][j].zombie.color = 0xFF8282CC; break; + case 3: eManager->entities[i][j].zombie.color = 0xFFEFEFEF; break; + case 4: eManager->entities[i][j].zombie.color = 0xFFAA6262; break; + default: eManager->entities[i][j].zombie.color = 0xFF95DB95; break; + } + break; + case ENTITY_ITEM: + //eManager->entities[i][j].entityItem.item = newItem(0,0); + fread(&eManager->entities[i][j].entityItem.item.id, sizeof(s16), 1, file); + fread(&eManager->entities[i][j].entityItem.item.countLevel, sizeof(s16), 1, file); + fread(&eManager->entities[i][j].entityItem.age, sizeof(s16), 1, file); + eManager->entities[i][j].level = i; + eManager->entities[i][j].entityItem.age = 0; + eManager->entities[i][j].xr = 3; + eManager->entities[i][j].yr = 3; + eManager->entities[i][j].canPass = false; + eManager->entities[i][j].entityItem.xx = eManager->entities[i][j].x; + eManager->entities[i][j].entityItem.yy = eManager->entities[i][j].y; + eManager->entities[i][j].entityItem.zz = 2; + eManager->entities[i][j].entityItem.xa = 0; + eManager->entities[i][j].entityItem.ya = 0; + eManager->entities[i][j].entityItem.za = 0; + break; + case ENTITY_FURNITURE: + fread(&eManager->entities[i][j].entityFurniture.itemID, sizeof(s16), 1, file); + int invIndex; + fread(&invIndex, sizeof(int), 1, file); + eManager->entities[i][j].entityFurniture.inv = &eManager->invs[invIndex]; + eManager->entities[i][j].xr = 3; + eManager->entities[i][j].yr = 3; + eManager->entities[i][j].canPass = false; + if(eManager->entities[i][j].entityFurniture.itemID == ITEM_LANTERN) eManager->entities[i][j].entityFurniture.r = 8; + break; + } + } + } + fread(map, sizeof(u8), 128*128*5, file); + fread(mapData, sizeof(u8), 128*128*5, file); + fclose(file); + return 0; + } + return 1; } diff --git a/source/SaveLoad.h b/source/SaveLoad.h old mode 100755 new mode 100644 index 513ba22..0468bf5 --- a/source/SaveLoad.h +++ b/source/SaveLoad.h @@ -2,16 +2,6 @@ #include #include #include "Entity.h" -#include "Player.h" -#include "Globals.h" -#define SAVE_VERSION 1 - -#define SAVE_COMMENT "Minicraft3DSSave" -#define SAVE_COPYBUFFER_SIZE 4096 - -//void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData, WorldData *worldData); -//int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData, WorldData *worldData); - -bool saveWorld(char *filename, EntityManager *eManager, WorldData *worldData, PlayerData *players, int playerCount); -bool loadWorld(char *filename, EntityManager *eManager, WorldData *worldData, PlayerData *players, int playerCount); +void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData); +int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * map, u8 * mapData); diff --git a/source/Sound.c b/source/Sound.c old mode 100755 new mode 100644 index 3529237..70f7d64 --- a/source/Sound.c +++ b/source/Sound.c @@ -1,104 +1,71 @@ #include "Sound.h" -u8 soundListenerLevel; -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)/2; - fseek(file, 0, SEEK_SET); - snd->buffer = linearAlloc(snd->size*sizeof(u16)); - 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); + fseek(file, 0, SEEK_SET); + snd->buffer = linearAlloc(snd->size); + 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); +void playMusic(Sound snd){ + csndPlaySound(10, SOUND_FORMAT_16BIT | SOUND_REPEAT, 44100, 1, 0, snd.buffer, snd.buffer, snd.size); } -void setListenerPosition(s8 level, int x, int 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); -} - -void stopMusic() { - CSND_SetPlayState(8, 0); - CSND_SetPlayState(10, 0); - csndExecCmds(true); -} - -void updateMusic(int lvl, int time) { +void updateMusic(int lvl) { switch(lvl) { case 0: - playMusic(&music_floor0); + playMusic(music_floor0); break; case 1: - if(time>6000 && time<19000) playMusic(&music_floor1); - else playMusic(&music_floor1_night); + playMusic(music_floor1); break; case 2: case 3: - playMusic(&music_floor23); + playMusic(music_floor23); break; case 4: - case 5: //TODO - dungeon needs own music - playMusic(&music_floor4); + playMusic(music_floor4); break; } } void loadSounds() { - loadSound(&snd_playerHurt, "romfs:/resources/playerhurt.raw"); - loadSound(&snd_playerDeath, "romfs:/resources/death.raw"); - loadSound(&snd_monsterHurt, "romfs:/resources/monsterhurt.raw"); - loadSound(&snd_test, "romfs:/resources/test.raw"); - 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"); - loadSound(&music_floor1_night, "romfs:/resources/music/floor1_night.raw"); - loadSound(&music_floor23, "romfs:/resources/music/floor2_3.raw"); - loadSound(&music_floor4, "romfs:/resources/music/floor4.raw"); + loadSound(&snd_playerHurt, "resources/playerhurt.raw"); + loadSound(&snd_playerDeath, "resources/playerdeath.raw"); + loadSound(&snd_monsterHurt, "resources/monsterhurt.raw"); + loadSound(&snd_test, "resources/test.raw"); + loadSound(&snd_pickup, "resources/pickup.raw"); + loadSound(&snd_bossdeath, "resources/bossdeath.raw"); + loadSound(&snd_craft, "resources/craft.raw"); + + loadSound(&music_menu, "resources/music/menu.raw"); + loadSound(&music_floor0, "resources/music/floor0.raw"); + loadSound(&music_floor1, "resources/music/floor1.raw"); + loadSound(&music_floor23, "resources/music/floor2_3.raw"); + loadSound(&music_floor4, "resources/music/floor4.raw"); } 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); } diff --git a/source/Sound.h b/source/Sound.h old mode 100755 new mode 100644 index b85193b..2e36791 --- a/source/Sound.h +++ b/source/Sound.h @@ -6,19 +6,15 @@ typedef struct { - u32 size; - u8 * buffer; + u32 size; + u8 * buffer; } Sound; void loadSound(Sound * snd, char * filename); void playSound(Sound snd); -void playSoundPositioned(Sound snd, s8 level, int x, int y); -void setListenerPosition(s8 level, int x, int y); - -void playMusic(Sound *snd); -void updateMusic(int lvl, int time); -void stopMusic(); +void playMusic(Sound snd); +void updateMusic(int lvl); void loadSounds(); void freeSounds(); @@ -34,6 +30,5 @@ Sound snd_craft; Sound music_menu; Sound music_floor0; Sound music_floor1; -Sound music_floor1_night; Sound music_floor23; -Sound music_floor4; +Sound music_floor4; \ No newline at end of file diff --git a/source/Synchronizer.c b/source/Synchronizer.c deleted file mode 100644 index 546a4d2..0000000 --- a/source/Synchronizer.c +++ /dev/null @@ -1,250 +0,0 @@ -#include "Synchronizer.h" - -#include "Globals.h" -#include "Player.h" -#include "Input.h" -#include "Network.h" -#include "PacketHandler.h" -#include "Ingame.h" - -u32 synchronizerLocalTurn; -unsigned int synchronizerNextSeed; -bool synchronizerRunning; - -int synchronizerCurrentTicks; - -bool synchronizerTurnReady(); -void synchronizerNextTurn(); - -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 send to server - sendStartReadyPacket(playerLocalID); -} - -void synchronizerSetPlayerReady(int playerID) { - players[playerID].ready = true; -} - -bool synchronizerAllReady() { - for(int i=0; i1) { - 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 - -//2-3 seem be optimal (at least for 2 players) -#define SYNCHRONIZER_TICKS_PER_TURN 2 - -void synchronizerInit(int seed, int initPlayerCount, int initPlayerLocalID); - -void synchronizerSendUID(); -void synchronizerSetPlayerUID(int playerID, u32 uid); -void synchronizerSendIfReady(); -void synchronizerSetPlayerReady(int playerID); -bool synchronizerAllReady(); -bool synchronizerIsRunning(); - -void synchronizerStart(); - -void synchronizerTick(void (*gtick)(void)); - -void synchronizerReset(); - -void synchronizerOnInputPacket(u8 playerID, u32 turnNumber, void *data, size_t dataSize); - -// values used ingame -u32 syncTickCount; - -// helpers for random numbers -double gaussrand(bool reset); diff --git a/source/ZipHelper.c b/source/ZipHelper.c deleted file mode 100644 index 2868587..0000000 --- a/source/ZipHelper.c +++ /dev/null @@ -1,213 +0,0 @@ -#include "ZipHelper.h" - -#include -#include -#include -#include "minizip/zip.h" -#include "minizip/unzip.h" - -#define dir_delimter '/' -#define MAX_FILENAME 256 -#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; - } - - // 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 - } - - // 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; - } - - size_t size; - do - { - size = fread(read_buffer, 1, READ_SIZE, in); - - - if(size0) { - //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; -} diff --git a/source/ZipHelper.h b/source/ZipHelper.h deleted file mode 100644 index 3d71d01..0000000 --- a/source/ZipHelper.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#define ZIPHELPER_REPLACE 0 -#define ZIPHELPER_ADD 1 - -#define ZIPHELPER_KEEP_FILES 0 -#define ZIPHELPER_CLEANUP_FILES 1 - -int unzipAndLoad(char *filename, int (*fileCallback)(char *filename), char *expectedComment, int keepFiles); -int zipFiles(char *filename, char **files, int fileCount, int mode, char *comment); diff --git a/source/main.c b/source/main.c old mode 100755 new mode 100644 index a253153..fcf2853 --- a/source/main.c +++ b/source/main.c @@ -1,7 +1,7 @@ #include <3ds.h> #include #include -#include +#include #include #include #include @@ -12,215 +12,268 @@ #include "MapGen.h" #include "Menu.h" #include "texturepack.h" -#include "Network.h" -#include "SaveLoad.h" -#include "Ingame.h" -#include "Player.h" -#include "Synchronizer.h" -#include "PacketHandler.h" -// TODO: Dungeon is way to difficult -// -> Skeleton arrows are slower, do a little less damage -// -> Or instead of less damage, implement a simple armor system +void initMiniMap(bool loadUpWorld) { + int i, x, y; + for (i = 0; i < 5; ++i) { + for (x = 0; x < 128; ++x) { + for (y = 0; y < 128; ++y) { -//TODO: Something still causes desyncs very rarely + if (!loadUpWorld) { // generate stairs up when making a new world. + switch (map[i][x + y * 128]) { + case TILE_STAIRS_DOWN: + map[i + 1][x + y * 128] = TILE_STAIRS_UP; + if (i == 0) { + map[i + 1][(x + 1) + y * 128] = TILE_HARDROCK; + map[i + 1][x + (y + 1) * 128] = TILE_HARDROCK; + map[i + 1][(x - 1) + y * 128] = TILE_HARDROCK; + map[i + 1][x + (y - 1) * 128] = TILE_HARDROCK; + map[i + 1][(x + 1) + (y + 1) * 128] = TILE_HARDROCK; + map[i + 1][(x - 1) + (y - 1) * 128] = TILE_HARDROCK; + map[i + 1][(x - 1) + (y + 1) * 128] = TILE_HARDROCK; + map[i + 1][(x + 1) + (y - 1) * 128] = TILE_HARDROCK; + } else { + map[i + 1][(x + 1) + y * 128] = TILE_DIRT; + map[i + 1][x + (y + 1) * 128] = TILE_DIRT; + map[i + 1][(x - 1) + y * 128] = TILE_DIRT; + map[i + 1][x + (y - 1) * 128] = TILE_DIRT; + map[i + 1][(x + 1) + (y + 1) * 128] = TILE_DIRT; + map[i + 1][(x - 1) + (y - 1) * 128] = TILE_DIRT; + map[i + 1][(x - 1) + (y + 1) * 128] = TILE_DIRT; + map[i + 1][(x + 1) + (y - 1) * 128] = TILE_DIRT; + } + } + } -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) { - sendFile(file, 0, 0); - networkSendWaitFlush(); - fclose(file); - } - - //send start command - size = writeStartRequestPacket(networkWriteBuffer); - networkSend(networkWriteBuffer, size); - processPacket(networkWriteBuffer, size); - - initMPGame = 0; -} - -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; + /* Minimaps */ + sf2d_set_pixel(minimap[i], x, y, getTileColor(map[i][x + y * 128])); + } + } } } +void initNewMap() { + newSeed(); + createAndValidateSkyMap(128, 128, map[0], data[0]); + createAndValidateTopMap(128, 128, map[1], data[1]); + createAndValidateUndergroundMap(128, 128, 1, map[2], data[2]); + createAndValidateUndergroundMap(128, 128, 2, map[3], data[3]); + createAndValidateUndergroundMap(128, 128, 3, map[4], data[4]); +} -//for rendering -> move to a better place -extern int xscr, yscr; +void setupGame(bool loadUpWorld) { + currentLevel = 1; + + // Reset entity manager. + memset(&eManager, 0, sizeof(eManager)); + sf2d_set_clear_color(0xFF6C6D82); //sf2d_set_clear_color(RGBA8(0x82, 0x6D, 0x6C, 0xFF)); + + if (!loadUpWorld) { + initNewMap(); + initPlayer(); + airWizardHealthDisplay = 2000; + int i; + for (i = 0; i < 5; ++i) { + trySpawn(500, i); + } + addEntityToList(newAirWizardEntity(630, 820, 0), &eManager); + } else { + initPlayer(); + loadWorld(currentFileName, &eManager, &player, (u8*) map, (u8*) data); + } + + updateMusic(currentLevel); + + initMiniMap(loadUpWorld); + shouldRenderMap = false; + mScrollX = 0; + mScrollY = 0; + zoomLevel = 2; + sprintf(mapText,"x%d",zoomLevel); + initGame = 0; +} + +int xscr = 0, yscr = 0; +void tick() { + if (player.p.isDead) { + if (player.p.endTimer < 1) { + currentMenu = MENU_LOSE; + } + --player.p.endTimer; + return; + } else if (player.p.hasWon) { + if (player.p.endTimer < 1) { + currentMenu = MENU_WIN; + } + --player.p.endTimer; + return; + } + + tickTouchMap(); + tickTouchQuickSelect(); + + int i; + for (i = 0; i < 324; ++i) { + int xx = rand() & 127; + int yy = rand() & 127; + tickTile(xx, yy); + } + tickPlayer(); + xscr = player.x - 100; + yscr = player.y - 56; + if (xscr < 16) + xscr = 16; + else if (xscr > 1832) + xscr = 1832; + if (yscr < 16) + yscr = 16; + else if (yscr > 1912) + yscr = 1912; + + for (i = 0; i < eManager.lastSlot[currentLevel]; ++i) { + Entity * e = &eManager.entities[currentLevel][i]; + if ((e->type != ENTITY_ZOMBIE && e->type != ENTITY_SLIME) + || (e->x > player.x - 160 && e->y > player.y - 125 + && e->x < player.x + 160 && e->y < player.y + 125)) + tickEntity(e); + } + +} + +void clearScreen(int* data, u8 fill, int size) { + int i; + for (i = 0; i < size / 4; ++i) + data[i] = 0xFF000000; +} char debugText[34]; char bossHealthText[34]; int main() { - romfsInit(); cfguInit(); CFGU_GetSystemModel(&MODEL_3DS); FILE * file; - shouldRenderDebug = false; + shouldRenderDebug = true; if ((file = fopen("settings.bin", "r"))) { fread(&shouldRenderDebug,sizeof(bool),1,file); fread(&shouldSpeedup,sizeof(bool),1,file); osSetSpeedupEnable(shouldSpeedup); fclose(file); } - sf2d_init(); + + 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(icons_png, SF2D_PLACE_RAM); - playerSprites = sfil_load_PNG_buffer(player_png, SF2D_PLACE_RAM); + icons = sfil_load_PNG_buffer(icons2_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); - + playMusic(music_menu); + bakeLights(); - + int i; - for (i = 0; i < 6; ++i) { - minimap[i] = sf2d_create_texture(128, 128, TEXFMT_RGBA8, SF2D_PLACE_RAM); + for (i = 0; i < 5; ++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); /* Default inputs */ - localInputs.k_up.input = KEY_DUP | KEY_CPAD_UP | KEY_CSTICK_UP; - 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; - 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 | KEY_ZR; - localInputs.k_menuPrev.input = KEY_L | KEY_ZL; + k_up.input = KEY_DUP | KEY_CPAD_UP | KEY_CSTICK_UP; + k_down.input = KEY_DDOWN | KEY_CPAD_DOWN | KEY_CSTICK_DOWN; + k_left.input = KEY_DLEFT | KEY_CPAD_LEFT | KEY_CSTICK_LEFT; + k_right.input = KEY_DRIGHT | KEY_CPAD_RIGHT | KEY_CSTICK_RIGHT; + k_attack.input = KEY_A | KEY_B | KEY_L | KEY_ZR; + k_menu.input = KEY_X | KEY_Y | KEY_R | KEY_ZL; + k_pause.input = KEY_START; + k_accept.input = KEY_A; + k_decline.input = KEY_B; + k_delete.input = KEY_X; + k_menuNext.input = KEY_R; + k_menuPrev.input = KEY_L; /* If btnSave exists, then use that. */ if ((file = fopen("btnSave.bin", "rb"))) { - 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); - fread(&(localInputs.k_decline.input), sizeof(int), 1, file); - fread(&(localInputs.k_delete.input), sizeof(int), 1, file); - fread(&(localInputs.k_menuNext.input), sizeof(int), 1, file); - fread(&(localInputs.k_menuPrev.input), sizeof(int), 1, file); + fread(&k_up.input, sizeof(int), 1, file); + fread(&k_down.input, sizeof(int), 1, file); + fread(&k_left.input, sizeof(int), 1, file); + fread(&k_right.input, sizeof(int), 1, file); + fread(&k_attack.input, sizeof(int), 1, file); + fread(&k_menu.input, sizeof(int), 1, file); + fread(&k_pause.input, sizeof(int), 1, file); + fread(&k_accept.input, sizeof(int), 1, file); + fread(&k_decline.input, sizeof(int), 1, file); + fread(&k_delete.input, sizeof(int), 1, file); + fread(&k_menuNext.input, sizeof(int), 1, file); + fread(&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(); + tickCount = 0; initRecipes(); - initTrades(); - aptHook(&cookie, task_apt_hook, NULL); while (aptMainLoop()) { - if (paused == true) playMusic(&music_menu); + ++tickCount; + hidScanInput(); + tickKeys(hidKeysHeld(), hidKeysDown()); + if (quitGame) break; - if (initGame > 0 && --initGame==0) setupGame(); - if (initMPGame > 0 && --initMPGame==0) setupGameServer(); - if (initBGMap > 0 && --initBGMap==0) setupBGMap(); + if (initGame > 0) setupGame(initGame == 1 ? true : false); - if (currentMenu == MENU_NONE) { - tickGame(); - renderGame(); + if (currentMenu == 0) { + tick(); + sf2d_start_frame(GFX_TOP, GFX_LEFT); + + 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(); + + renderBackground(xscr, yscr); + renderEntities(player.x, player.y, &eManager); + renderPlayer(); + + resetStencilStuff(); + offsetX = 0; + offsetY = 0; + + if(shouldRenderDebug){ + sprintf(fpsstr, " FPS: %.0f, X:%d, Y:%d, E:%d", sf2d_get_fps(), player.x, player.y, eManager.lastSlot[currentLevel]); + drawText(fpsstr, 2, 225); + } + + sf2d_end_frame(); + + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + if(!shouldRenderMap){ + sf2d_draw_texture(bottombg, 0, 0); + renderGui(); + } else { + renderZoomedMap(); + } + sf2d_end_frame(); } else { - //input scanning ingame is handled by the synchronizer - hidScanInput(); - tickKeys(&localInputs, hidKeysHeld(), hidKeysDown()); - tickMenu(currentMenu); renderMenu(currentMenu, xscr, yscr); } @@ -228,11 +281,7 @@ int main() { sf2d_swapbuffers(); } - stopMusic(); - - freeTrades(); freeRecipes(); - freePlayers(); freeLightBakes(); sf2d_free_texture(icons); @@ -241,12 +290,9 @@ int main() { sf2d_free_texture(minimap[2]); sf2d_free_texture(minimap[3]); sf2d_free_texture(minimap[4]); - sf2d_free_texture(minimap[5]); freeSounds(); - networkExit(); csndExit(); cfguExit(); - romfsExit(); sf2d_fini(); return 0; } diff --git a/source/minizip/crypt.h b/source/minizip/crypt.h old mode 100755 new mode 100644 index 622f4bc..2d69da4 --- a/source/minizip/crypt.h +++ b/source/minizip/crypt.h @@ -1,9 +1,9 @@ /* crypt.h -- base code for crypt/uncrypt ZIPfile - Version 1.01e, February 12th, 2005 + Version 1.01h, December 28th, 2009 - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2009 Gilles Vollant This code is a modified version of crypting code in Infozip distribution diff --git a/source/minizip/ioapi.c b/source/minizip/ioapi.c old mode 100755 new mode 100644 index f1bee23..51a9058 --- a/source/minizip/ioapi.c +++ b/source/minizip/ioapi.c @@ -1,9 +1,9 @@ /* ioapi.c -- IO base function header for compress/uncompress .zip files using zlib + zip or unzip API - Version 1.01e, February 12th, 2005 + Version 1.01h, December 28th, 2009 - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2009 Gilles Vollant */ #include @@ -141,7 +141,8 @@ long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) default: return -1; } ret = 0; - fseek((FILE *)stream, offset, fseek_origin); + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; return ret; } diff --git a/source/minizip/ioapi.h b/source/minizip/ioapi.h old mode 100755 new mode 100644 index 7d457ba..1dba776 --- a/source/minizip/ioapi.h +++ b/source/minizip/ioapi.h @@ -1,9 +1,9 @@ /* ioapi.h -- IO base function header for compress/uncompress .zip files using zlib + zip or unzip API - Version 1.01e, February 12th, 2005 + Version 1.01h, December 28th, 2009 - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2009 Gilles Vollant */ #ifndef _ZLIBIOAPI_H diff --git a/source/minizip/unzip.c b/source/minizip/unzip.c old mode 100755 new mode 100644 index 9ad4766..17d730d --- a/source/minizip/unzip.c +++ b/source/minizip/unzip.c @@ -1,7 +1,7 @@ /* unzip.c -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 + Version 1.01h, December 28th, 2009 - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2009 Gilles Vollant Read unzip.h for more info */ @@ -103,6 +103,9 @@ typedef struct { char *read_buffer; /* internal buffer for compressed data */ z_stream stream; /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ uLong stream_initialised; /* flag set if stream structure is initialised*/ @@ -204,7 +207,7 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); @@ -232,7 +235,7 @@ local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); @@ -491,8 +494,11 @@ extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) s=(unz_s*)ALLOC(sizeof(unz_s)); - *s=us; - unzGoToFirstFile((unzFile)s); + if (s!=NULL) + { + *s=us; + unzGoToFirstFile((unzFile)s); + } return (unzFile)s; } @@ -608,10 +614,12 @@ local int unzlocal_GetCurrentFileInfoInternal (file, /* we check the magic */ if (err==UNZ_OK) + { if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x02014b50) err=UNZ_BADZIPFILE; + } if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) err=UNZ_ERRNO; @@ -688,10 +696,13 @@ local int unzlocal_GetCurrentFileInfoInternal (file, uSizeRead = extraFieldBufferSize; if (lSeek!=0) + { if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; + } + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; @@ -713,10 +724,13 @@ local int unzlocal_GetCurrentFileInfoInternal (file, uSizeRead = commentBufferSize; if (lSeek!=0) + { if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; + } + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; @@ -977,10 +991,12 @@ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, if (err==UNZ_OK) + { if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x04034b50) err=UNZ_BADZIPFILE; + } if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; @@ -997,6 +1013,9 @@ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, err=UNZ_BADZIPFILE; if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; @@ -1111,6 +1130,9 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) } if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; @@ -1124,6 +1146,34 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) pfile_in_zip_read_info->stream.total_out = 0; + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && + (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) { @@ -1135,7 +1185,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; else { TRYFREE(pfile_in_zip_read_info); @@ -1163,6 +1213,8 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + # ifndef NOUNCRYPT if (password != NULL) { @@ -1334,6 +1386,53 @@ extern int ZEXPORT unzReadCurrentFile (file, buf, len) iRead += uDoCopy; } else + if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } + else { uLong uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; @@ -1512,8 +1611,12 @@ extern int ZEXPORT unzCloseCurrentFile (file) TRYFREE(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif pfile_in_zip_read_info->stream_initialised = 0; TRYFREE(pfile_in_zip_read_info); @@ -1534,7 +1637,6 @@ extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) char *szComment; uLong uSizeBuf; { - int err=UNZ_OK; unz_s* s; uLong uReadThis ; if (file==NULL) @@ -1567,7 +1669,7 @@ extern uLong ZEXPORT unzGetOffset (file) unz_s* s; if (file==NULL) - return UNZ_PARAMERROR; + return 0; s=(unz_s*)file; if (!s->current_file_ok) return 0; diff --git a/source/minizip/unzip.h b/source/minizip/unzip.h old mode 100755 new mode 100644 index b247937..94c1b69 --- a/source/minizip/unzip.h +++ b/source/minizip/unzip.h @@ -1,7 +1,7 @@ /* unzip.h -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 + Version 1.01h, December 28th, 2009 - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2009 Gilles Vollant This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible. @@ -57,6 +57,12 @@ extern "C" { #include "ioapi.h" #endif +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ diff --git a/source/minizip/zip.c b/source/minizip/zip.c old mode 100755 new mode 100644 index 7fbe002..1451d61 --- a/source/minizip/zip.c +++ b/source/minizip/zip.c @@ -1,10 +1,10 @@ /* zip.c -- IO on .zip files using zlib - Version 1.01e, February 12th, 2005 + Version 1.01h, December 28th, 2009 27 Dec 2004 Rolf Kalbermatter Modification to zipOpen2 to support globalComment retrieval. - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2009 Gilles Vollant Read zip.h for more info */ @@ -320,9 +320,9 @@ local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) uLong dosDate; { uLong year = (uLong)ptm->tm_year; - if (year>1980) + if (year>=1980) year-=1980; - else if (year>80) + else if (year>=80) year-=80; return (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | @@ -373,7 +373,7 @@ local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); @@ -401,7 +401,7 @@ local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); @@ -432,67 +432,69 @@ local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) /* Locate the Central directory of a zipfile (at the end, just before the global comment) + Fix from Riccardo Cohen */ local uLong ziplocal_SearchCentralDir OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream)); local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; { - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; - if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; - uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; - if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; } + #endif /* !NO_ADDFILEINEXISTINGZIP*/ /************************************************************/ @@ -521,6 +523,8 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc if (ziinit.filestream == NULL) return NULL; + if (append == APPEND_STATUS_CREATEAFTER) + ZSEEK(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; @@ -558,9 +562,10 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc uLong size_comment; central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); +/* disable to allow appending to empty ZIP archive if (central_pos==0) err=ZIP_ERRNO; - +*/ if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=ZIP_ERRNO; @@ -615,7 +620,7 @@ extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc if (size_comment>0) { - ziinit.globalcomment = ALLOC(size_comment+1); + ziinit.globalcomment = (char*)ALLOC(size_comment+1); if (ziinit.globalcomment) { size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); @@ -687,12 +692,12 @@ extern zipFile ZEXPORT zipOpen (pathname, append) return zipOpen2(pathname,append,NULL,NULL); } -extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, +extern int ZEXPORT zipOpenNewFileInZip4 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy, - password, crcForCrypting) + password, crcForCrypting, versionMadeBy, flagBase) zipFile file; const char* filename; const zip_fileinfo* zipfi; @@ -709,6 +714,8 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, int strategy; const char* password; uLong crcForCrypting; + uLong versionMadeBy; + uLong flagBase; { zip_internal* zi; uInt size_filename; @@ -755,7 +762,7 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); } - zi->ci.flag = 0; + zi->ci.flag = flagBase; if ((level==8) || (level==9)) zi->ci.flag |= 2; if ((level==2)) @@ -778,7 +785,7 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); /* version info */ - ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); + ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); @@ -857,6 +864,7 @@ extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, zi->ci.stream.next_out = zi->ci.buffered_data; zi->ci.stream.total_in = 0; zi->ci.stream.total_out = 0; + zi->ci.stream.data_type = Z_BINARY; if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { @@ -912,14 +920,46 @@ extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi, int level; int raw; { - return zipOpenNewFileInZip3 (file, filename, zipfi, + return zipOpenNewFileInZip4 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0); + NULL, 0, VERSIONMADEBY, 0); } +extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; + int raw; + int windowBits; + int memLevel; + int strategy; + const char* password; + uLong crcForCrypting; +{ + return zipOpenNewFileInZip4 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0); +} + + extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, @@ -935,10 +975,12 @@ extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, int method; int level; { - return zipOpenNewFileInZip2 (file, filename, zipfi, + return zipOpenNewFileInZip4 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, - comment, method, level, 0); + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0); } local int zipFlushWriteBuffer(zi) @@ -978,9 +1020,9 @@ extern int ZEXPORT zipWriteInFileInZip (file, buf, len) if (zi->in_opened_file_inzip == 0) return ZIP_PARAMERROR; - zi->ci.stream.next_in = (void*)buf; + zi->ci.stream.next_in = (Bytef*)buf; zi->ci.stream.avail_in = len; - zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); + zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) { @@ -1070,7 +1112,9 @@ extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) { - err=deflateEnd(&zi->ci.stream); + int tmp_err=deflateEnd(&zi->ci.stream); + if (err == ZIP_OK) + err = tmp_err; zi->ci.stream_initialised = 0; } @@ -1173,7 +1217,7 @@ extern int ZEXPORT zipClose (file, global_comment) ldi = ldi->next_datablock; } } - free_datablock(zi->central_dir.first_block); + free_linkedlist(&(zi->central_dir)); if (err==ZIP_OK) /* Magic End */ err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); diff --git a/source/minizip/zip.h b/source/minizip/zip.h old mode 100755 new mode 100644 index acacce8..39215ca --- a/source/minizip/zip.h +++ b/source/minizip/zip.h @@ -1,7 +1,7 @@ /* zip.h -- IO for compress .zip files using zlib - Version 1.01e, February 12th, 2005 + Version 1.01h, December 28th, 2009 - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2009 Gilles Vollant This unzip package allow creates .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible. @@ -191,8 +191,7 @@ extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, int memLevel, int strategy, const char* password, - uLong crcForCtypting)); - + uLong crcForCrypting)); /* Same than zipOpenNewFileInZip2, except windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 @@ -200,6 +199,29 @@ extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, crcForCtypting : crc of file to compress (needed for crypting) */ +extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase)); +/* + Same than zipOpenNewFileInZip4, except + versionMadeBy : value for Version made by field + flag : value for flag field (compression level info will be added) + */ extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, const void* buf, diff --git a/source/texturepack.c b/source/texturepack.c old mode 100755 new mode 100644 index 9398c10..a79f47b --- a/source/texturepack.c +++ b/source/texturepack.c @@ -1,100 +1,166 @@ #include "texturepack.h" -#include "ZipHelper.h" - +#define dir_delimter '/' #define MAX_FILENAME 256 +#define READ_SIZE 9216 -bool texturepackUseDefaultIcons = true; -bool texturepackUseDefaultPlayer = true; -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. + // 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); - // 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 - } + unzClose( zipfile ); - unzGetGlobalComment(zipfile, cmmtBuf, 58); - - unzClose( zipfile ); - - return 0; + return 0; } -int loadTexture(char * filename) { - char lowerFilename[MAX_FILENAME]; - strcpy(lowerFilename,filename); - toLowerString(lowerFilename); +int loadTexturePack(char * filename){ + + bool useDefaultIcons = true; + bool useDefaultFont = true; + bool useDefaultBottom = true; - if(strcmp(lowerFilename, "icons.png") == 0){ - if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ - return 0; - } + // 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 + } - icons = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); - reloadColors(); + // Buffer to hold data read from the zip file. + char read_buffer[ READ_SIZE ]; - texturepackUseDefaultIcons = false; - } else if(strcmp(lowerFilename, "player.png") == 0){ - if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ - return 0; - } + // 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 ){ + unzClose( zipfile ); + return 3; // Error: Could not read file info + } - playerSprites = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); + // 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 ) + { + unzClose( zipfile ); + return 4; + } - texturepackUseDefaultPlayer = false; - } else if(strcmp(lowerFilename, "font.png") == 0){ - if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ - return 0; - } + // Open a file to write out the data. + FILE * out = fopen(filename, "wb" ); + if ( out == NULL ) + { + unzCloseCurrentFile( zipfile ); + unzClose( zipfile ); + return 5; + } - font = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); + int error = UNZ_OK; + do + { + error = unzReadCurrentFile( zipfile, read_buffer, READ_SIZE ); + if ( error < 0 ) + { + //printf( "error %d\n", error ); + unzCloseCurrentFile( zipfile ); + unzClose( zipfile ); + return 6; + } - texturepackUseDefaultFont = false; - } else if(strcmp(lowerFilename, "bottombg.png") == 0){ - if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ - return 0; - } + // Write data to file. + if ( error > 0 ) + { + fwrite( read_buffer, error, 1, out ); // You should check return of fwrite... + } + } while ( error > 0 ); - bottombg = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); + fclose(out); + + 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){ + unzCloseCurrentFile( zipfile ); + unzClose( zipfile ); + return 7; + } + icons = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); + + reloadColors(); + + useDefaultIcons = false; - texturepackUseDefaultBottom = false; - } + } else if(strcmp(lowerFilename,"font.png") == 0){ + if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ + unzCloseCurrentFile( zipfile ); + unzClose( zipfile ); + return 7; + } + font = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); + useDefaultFont = false; + } else if(strcmp(lowerFilename,"bottombg.png") == 0){ + if(sfil_load_PNG_file(filename, SF2D_PLACE_RAM) == NULL){ + unzCloseCurrentFile( zipfile ); + unzClose( zipfile ); + return 7; + } + bottombg = sfil_load_PNG_file(filename, SF2D_PLACE_RAM); + useDefaultBottom = false; + } + + remove(filename); + } - return 0; -} - -int loadTexturePack(char * filename) { - 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(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; + unzCloseCurrentFile( zipfile ); + + // Go the the next entry listed in the zip file. + if ( ( i+1 ) < global_info.number_entry ) + { + if ( unzGoToNextFile( zipfile ) != UNZ_OK ) + { + unzClose( zipfile ); + return 7; + } + } + } + + if(useDefaultIcons){ + icons = sfil_load_PNG_buffer(icons2_png, SF2D_PLACE_RAM); + reloadColors(); + } + if(useDefaultFont) font = sfil_load_PNG_buffer(Font_png, SF2D_PLACE_RAM); + if(useDefaultBottom) bottombg = sfil_load_PNG_buffer(bottombg_png, SF2D_PLACE_RAM); + + unzClose( zipfile ); + + return 0; } diff --git a/source/texturepack.h b/source/texturepack.h old mode 100755 new mode 100644 index b0f61ce..565d1cc --- a/source/texturepack.h +++ b/source/texturepack.h @@ -1,5 +1,6 @@ #pragma once - +#include +#include #include #include #include