Started work on new update
Added some small new map generation features Added "NPCs" and "Quests" (atleast a first experiment for them) Added magic compass to make search for stairs leass annoying Added mostly visual season and weather effects
This commit is contained in:
parent
f6e2d30ab6
commit
3699414dcd
19 changed files with 1324 additions and 253 deletions
BIN
data/icons2.png
BIN
data/icons2.png
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 32 KiB |
|
@ -104,7 +104,7 @@ void initRecipes(){
|
|||
workbenchRecipes.recipes[20] = defineRecipe(ITEM_WALL_WOOD,1,1,ITEM_WOOD,4);
|
||||
workbenchRecipes.recipes[21] = defineRecipe(ITEM_WALL_STONE,1,1,ITEM_STONE,4);
|
||||
|
||||
anvilRecipes.size = 16;
|
||||
anvilRecipes.size = 17;
|
||||
anvilRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (anvilRecipes.size));
|
||||
anvilRecipes.recipes[0] = defineRecipe(TOOL_SWORD,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
|
||||
anvilRecipes.recipes[1] = defineRecipe(TOOL_AXE,2,2,ITEM_WOOD,5,ITEM_IRONINGOT,5);
|
||||
|
@ -122,6 +122,7 @@ void initRecipes(){
|
|||
anvilRecipes.recipes[13] = defineRecipe(ITEM_ENCHANTER,1,3,ITEM_WOOD,10,ITEM_GOLDINGOT,10,ITEM_GEM,20);
|
||||
anvilRecipes.recipes[14] = defineRecipe(ITEM_WALL_IRON,1,1,ITEM_IRONINGOT,2);
|
||||
anvilRecipes.recipes[15] = defineRecipe(ITEM_WALL_GOLD,1,1,ITEM_GOLDINGOT,2);
|
||||
anvilRecipes.recipes[16] = defineRecipe(ITEM_COIN,3,1,ITEM_IRONINGOT,1);
|
||||
|
||||
furnaceRecipes.size = 3;
|
||||
furnaceRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (furnaceRecipes.size));
|
||||
|
@ -139,7 +140,7 @@ void initRecipes(){
|
|||
loomRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (loomRecipes.size));
|
||||
loomRecipes.recipes[0] = defineRecipe(ITEM_STRING,1,1,ITEM_WOOL,1);
|
||||
|
||||
enchanterRecipes.size = 8;
|
||||
enchanterRecipes.size = 7;
|
||||
enchanterRecipes.recipes = (Recipe*)malloc(sizeof(Recipe) * (enchanterRecipes.size));
|
||||
enchanterRecipes.recipes[0] = defineRecipe(TOOL_SWORD,4,2,ITEM_WOOD,5,ITEM_GEM,50);
|
||||
enchanterRecipes.recipes[1] = defineRecipe(TOOL_AXE,4,2,ITEM_WOOD,5,ITEM_GEM,50);
|
||||
|
@ -148,7 +149,6 @@ void initRecipes(){
|
|||
enchanterRecipes.recipes[4] = defineRecipe(TOOL_SHOVEL,4,2,ITEM_WOOD,5,ITEM_GEM,50);
|
||||
enchanterRecipes.recipes[5] = defineRecipe(ITEM_ARROW_GEM,1,3,ITEM_WOOD,1,ITEM_GEM,3,ITEM_STRING,1);
|
||||
enchanterRecipes.recipes[6] = defineRecipe(ITEM_WALL_GEM,1,1,ITEM_GEM,10);
|
||||
enchanterRecipes.recipes[7] = defineRecipe(ITEM_WIZARD_SUMMON,1,4,ITEM_CLOUD,100,ITEM_IRONINGOT,10,ITEM_BONE,10,ITEM_LEATHER,10);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ RecipeManager anvilRecipes;
|
|||
RecipeManager loomRecipes;
|
||||
RecipeManager enchanterRecipes;
|
||||
|
||||
Recipe defineRecipe(int item, int amountOrLevel, int numArgs, ...);
|
||||
|
||||
void checkCanCraftRecipes(RecipeManager * rm, Inventory * inv);
|
||||
void sortRecipes(RecipeManager * rm);
|
||||
bool craftItem(RecipeManager * rm, Recipe* r, Inventory* inv);
|
||||
|
|
|
@ -346,6 +346,22 @@ Entity newGlowwormEntity(int x, int y, int level){
|
|||
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;
|
||||
}
|
||||
|
||||
void addEntityToList(Entity e, EntityManager* em){
|
||||
e.slotNum = em->lastSlot[e.level];
|
||||
em->entities[e.level][em->lastSlot[e.level]] = e;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#define ENTITY_DRAGONPROJECTILE 16
|
||||
#define ENTITY_MAGIC_PILLAR 17
|
||||
|
||||
#define ENTITY_NPC 18
|
||||
|
||||
typedef struct Entity Entity;
|
||||
|
||||
typedef struct {
|
||||
|
@ -160,6 +162,10 @@ typedef struct {
|
|||
s8 waitTime;
|
||||
} Glowworm;
|
||||
|
||||
typedef struct {
|
||||
u8 type;
|
||||
} NPC;
|
||||
|
||||
typedef struct {
|
||||
float xa;
|
||||
float ya;
|
||||
|
@ -200,6 +206,7 @@ struct Entity {
|
|||
Glowworm glowworm;
|
||||
Dragon dragon;
|
||||
DragonFire dragonFire;
|
||||
NPC npc;
|
||||
TextParticleEntity textParticle;
|
||||
SmashParticleEntity smashParticle;
|
||||
};
|
||||
|
@ -234,6 +241,7 @@ 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);
|
||||
|
||||
|
|
133
source/Globals.c
133
source/Globals.c
|
@ -1,6 +1,6 @@
|
|||
#include "Globals.h"
|
||||
|
||||
char versionText[34] = "Version 1.2.2";
|
||||
char versionText[34] = "Version 1.3.0";
|
||||
char fpsstr[34];
|
||||
u8 currentMenu = 0;
|
||||
|
||||
|
@ -217,6 +217,7 @@ void tickTouchQuickSelect() {
|
|||
}
|
||||
|
||||
void hurtEntity(Entity* e, int damage, int dir, u32 hurtColor){
|
||||
if (TESTGODMODE && e->type==ENTITY_PLAYER) return;
|
||||
if (e->hurtTime > 0) return;
|
||||
int xd = player.x - e->x;
|
||||
int yd = player.y - e->y;
|
||||
|
@ -252,7 +253,7 @@ void hurtEntity(Entity* e, int damage, int dir, u32 hurtColor){
|
|||
}
|
||||
player.p.score += 50 * (e->hostile.lvl + 1);
|
||||
removeEntityFromList(e,e->level,&eManager);
|
||||
trySpawn(3, currentLevel);
|
||||
if(currentLevel != 5) trySpawn(3, currentLevel);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -262,7 +263,7 @@ void hurtEntity(Entity* e, int damage, int dir, u32 hurtColor){
|
|||
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);
|
||||
if(currentLevel != 5) trySpawn(3, currentLevel);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -270,7 +271,7 @@ void hurtEntity(Entity* e, int damage, int dir, u32 hurtColor){
|
|||
e->wizard.health -= damage;
|
||||
airWizardHealthDisplay = e->wizard.health;
|
||||
if(e->wizard.health < 1){
|
||||
addItemsToWorld(newItem(ITEM_DUNGEON_KEY,1),e->x+8, e->y+8, (rand()%2) + 1);
|
||||
addItemsToWorld(newItem(ITEM_MAGIC_DUST,1),e->x+8, e->y+8, (rand()%2) + 2);
|
||||
removeEntityFromList(e,e->level,&eManager);
|
||||
playSound(snd_bossdeath);
|
||||
player.p.score += 1000;
|
||||
|
@ -295,7 +296,7 @@ void hurtEntity(Entity* e, int damage, int dir, u32 hurtColor){
|
|||
}
|
||||
player.p.score += 10;
|
||||
removeEntityFromList(e,e->level,&eManager);
|
||||
trySpawn(3, currentLevel);
|
||||
if(currentLevel != 5) trySpawn(3, currentLevel);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -546,16 +547,16 @@ void EntityVsEntity(Entity* e1, Entity* e2){
|
|||
damage = 1 + (rand()%3);
|
||||
break;
|
||||
case ITEM_ARROW_STONE:
|
||||
damage = 2 + (rand()%5);
|
||||
damage = 2 + (rand()%4);
|
||||
break;
|
||||
case ITEM_ARROW_IRON:
|
||||
damage = 8 + (rand()%9);
|
||||
break;
|
||||
case ITEM_ARROW_GOLD:
|
||||
damage = 16 + (rand()%17);
|
||||
damage = 16 + (rand()%9);
|
||||
break;
|
||||
case ITEM_ARROW_GEM:
|
||||
damage = 24 + (rand()%17);
|
||||
damage = 24 + (rand()%9);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -589,6 +590,7 @@ bool EntityBlocksEntity(Entity* e1, Entity* e2){
|
|||
case ENTITY_PLAYER:
|
||||
case ENTITY_PASSIVE:
|
||||
case ENTITY_MAGIC_PILLAR:
|
||||
case ENTITY_NPC:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
@ -599,9 +601,12 @@ bool EntityBlocksEntity(Entity* e1, Entity* e2){
|
|||
|
||||
bool tileIsSolid(int tile, Entity * e){
|
||||
switch(tile){
|
||||
case TILE_TREE:
|
||||
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:
|
||||
|
@ -612,9 +617,10 @@ bool tileIsSolid(int tile, Entity * e){
|
|||
case TILE_IRON_WALL:
|
||||
case TILE_GOLD_WALL:
|
||||
case TILE_GEM_WALL:
|
||||
case TILE_DUNGEON_WALL:
|
||||
case TILE_MAGIC_BARRIER:
|
||||
return true;
|
||||
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;
|
||||
|
@ -655,6 +661,12 @@ u32 getTileColor(int tile){
|
|||
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;
|
||||
}
|
||||
|
@ -806,6 +818,11 @@ s8 itemTileInteract(int tile, Item* item, int x, int y, int px, int py, int dir)
|
|||
setTile(TILE_GEM_WALL,x,y); --item->countLevel;
|
||||
return 1;
|
||||
}
|
||||
else if(item->id == ITEM_BOOKSHELVES){
|
||||
setTile(TILE_BOOKSHELVES,x,y); --item->countLevel;
|
||||
data[currentLevel][x+y*128] = rand()%3;
|
||||
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);
|
||||
|
@ -846,6 +863,15 @@ s8 itemTileInteract(int tile, Item* item, int x, int y, int px, int py, int dir)
|
|||
else if(item->id == ITEM_WALL_GEM){
|
||||
setTile(TILE_GEM_WALL,x,y); --item->countLevel;
|
||||
return 1;
|
||||
}
|
||||
else if(item->id == ITEM_BOOKSHELVES){
|
||||
setTile(TILE_BOOKSHELVES,x,y); --item->countLevel;
|
||||
data[currentLevel][x+y*128] = rand()%3;
|
||||
return 1;
|
||||
}
|
||||
else if(item->id == ITEM_WOOD) {
|
||||
setTile(TILE_WOOD_FLOOR,x,y); --item->countLevel;
|
||||
return 1;
|
||||
}
|
||||
else if(item->id == ITEM_SAND){
|
||||
setTile(TILE_SAND,x,y); --item->countLevel;
|
||||
|
@ -942,6 +968,16 @@ s8 itemTileInteract(int tile, Item* item, int x, int y, int px, int py, int dir)
|
|||
playerHurtTile(tile, x, y, (rand()%10) + (item->countLevel) * 5 + 10, player.p.dir);
|
||||
return 1;
|
||||
} break;
|
||||
case TILE_BOOKSHELVES:
|
||||
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_WOOD_FLOOR:
|
||||
if(item->id == TOOL_AXE && playerUseEnergy(4-item->countLevel)){
|
||||
addEntityToList(newItemEntity(newItem(ITEM_WOOD,1), (x<<4)+8, (y<<4)+8, currentLevel), &eManager);
|
||||
setTile(TILE_DIRT,x,y);
|
||||
} break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -952,7 +988,7 @@ void tickTile(int x, int y){
|
|||
|
||||
switch(tile){
|
||||
case TILE_SAPLING_TREE:
|
||||
setData(++data,x,y); if(data>100){setData(0,x,y); setTile(TILE_TREE,x,y);}
|
||||
if(season!=3) setData(++data,x,y); if(data>100){setData(0,x,y); setTile(TILE_TREE,x,y);}
|
||||
break;
|
||||
case TILE_TREE:
|
||||
if(eManager.lastSlot[currentLevel]<800 && (daytime>18000 || daytime<5000) && rand()%800==0) {
|
||||
|
@ -966,16 +1002,22 @@ void tickTile(int x, int y){
|
|||
}
|
||||
break;
|
||||
case TILE_SAPLING_CACTUS:
|
||||
setData(++data,x,y); if(data>100){setData(0,x,y); setTile(TILE_CACTUS,x,y);}
|
||||
if(season!=3) 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);
|
||||
if(data<100 && season!=3) 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);
|
||||
if(currentLevel==1 && season==3 && rand()%12==0) {
|
||||
if(getTile(x+1,y)!=TILE_WATER) setTile(TILE_ICE,x,y);
|
||||
if(getTile(x-1,y)!=TILE_WATER) setTile(TILE_ICE,x,y);
|
||||
if(getTile(x,y+1)!=TILE_WATER) setTile(TILE_ICE,x,y);
|
||||
if(getTile(x,y-1)!=TILE_WATER) setTile(TILE_ICE,x,y);
|
||||
}
|
||||
break;
|
||||
case TILE_LAVA:
|
||||
if(getTile(x+1,y)==TILE_HOLE) setTile(TILE_LAVA,x+1,y);
|
||||
|
@ -1016,6 +1058,12 @@ void tickTile(int x, int y){
|
|||
}
|
||||
}
|
||||
if(data==0) setTile(TILE_DUNGEON_FLOOR,x,y);
|
||||
setData(rand()%2,x,y);
|
||||
break;
|
||||
case TILE_ICE:
|
||||
if(season!=3) {
|
||||
setTile(TILE_WATER,x,y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1109,7 +1157,7 @@ void tickEntity(Entity* e){
|
|||
if(e->type == ENTITY_SKELETON) {
|
||||
--(e->hostile.randAttackTime);
|
||||
if(e->hostile.randAttackTime <= 0) {
|
||||
e->hostile.randAttackTime = 70 - (e->hostile.lvl * 10);
|
||||
e->hostile.randAttackTime = 80 - (e->hostile.lvl * 5);
|
||||
|
||||
int aitemID = ITEM_ARROW_WOOD;
|
||||
if(e->hostile.lvl >= 2) aitemID = ITEM_ARROW_STONE;
|
||||
|
@ -1617,6 +1665,8 @@ void initPlayer(){
|
|||
}
|
||||
|
||||
void playerHurtTile(int tile, int xt, int yt, int damage, int dir){
|
||||
if(TESTGODMODE) damage = 99;
|
||||
|
||||
char hurtText[11];
|
||||
switch(tile){
|
||||
case TILE_TREE:
|
||||
|
@ -1798,11 +1848,21 @@ void playerHurtTile(int tile, int xt, int yt, int damage, int dir){
|
|||
addItemsToWorld(newItem(ITEM_WALL_GEM,1),(xt<<4)+8,(yt<<4)+8,1);
|
||||
}
|
||||
break;
|
||||
case TILE_BOOKSHELVES:
|
||||
sprintf(hurtText, "%d", damage);
|
||||
addEntityToList(newTextParticleEntity(hurtText,0xFF0000FF,xt<<4,yt<<4,currentLevel), &eManager);
|
||||
addEntityToList(newSmashParticleEntity(xt<<4,yt<<4,currentLevel), &eManager);
|
||||
|
||||
if(currentLevel!=5) setTile(TILE_DIRT,xt,yt);
|
||||
else setTile(TILE_DUNGEON_FLOOR,xt,yt);
|
||||
addItemsToWorld(newItem(ITEM_BOOKSHELVES,1),(xt<<4)+8,(yt<<4)+8,1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool playerUseEnergy(int amount){
|
||||
if(TESTGODMODE) return true;
|
||||
if(amount > player.p.stamina) return false;
|
||||
player.p.stamina -= amount;
|
||||
return true;
|
||||
|
@ -1974,24 +2034,28 @@ bool useEntity(Entity* e) {
|
|||
switch(e->entityFurniture.itemID){
|
||||
case ITEM_WORKBENCH:
|
||||
currentRecipes = &workbenchRecipes;
|
||||
currentCraftTitle = "Crafting";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
return true;
|
||||
case ITEM_FURNACE:
|
||||
currentRecipes = &furnaceRecipes;
|
||||
currentCraftTitle = "Crafting";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
return true;
|
||||
case ITEM_OVEN:
|
||||
currentRecipes = &ovenRecipes;
|
||||
currentCraftTitle = "Crafting";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
return true;
|
||||
case ITEM_ANVIL:
|
||||
currentRecipes = &anvilRecipes;
|
||||
currentCraftTitle = "Crafting";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
|
@ -2005,17 +2069,22 @@ bool useEntity(Entity* e) {
|
|||
return true;
|
||||
case ITEM_LOOM:
|
||||
currentRecipes = &loomRecipes;
|
||||
currentCraftTitle = "Crafting";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
return true;
|
||||
case ITEM_ENCHANTER:
|
||||
currentRecipes = &enchanterRecipes;
|
||||
currentCraftTitle = "Crafting";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
return true;
|
||||
}
|
||||
} else if(e->type == ENTITY_NPC) {
|
||||
openNPCMenu(e->npc.type);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -2088,7 +2157,7 @@ void tickPlayer(){
|
|||
|
||||
if (swimming && player.p.swimTimer % 60 == 0) {
|
||||
if (player.p.stamina > 0) {
|
||||
--player.p.stamina;
|
||||
if(!TESTGODMODE) --player.p.stamina;
|
||||
} else {
|
||||
hurtEntity(&player,1,-1,0xFFAF00FF);
|
||||
}
|
||||
|
@ -2101,7 +2170,7 @@ void tickPlayer(){
|
|||
|
||||
if(k_attack.clicked){
|
||||
if (player.p.stamina != 0) {
|
||||
player.p.stamina--;
|
||||
if(!TESTGODMODE) player.p.stamina--;
|
||||
player.p.staminaRecharge = 0;
|
||||
playerAttack();
|
||||
//addEntityToList(newSlimeEntity(1,200,600,1), &eManager);
|
||||
|
@ -2148,7 +2217,7 @@ void enterDungeon() {
|
|||
|
||||
//create map
|
||||
currentLevel = 5;
|
||||
createDungeonMap(128, 128, map[5], data[5]);
|
||||
createAndValidateDungeonMap(128, 128, 5, map[5], data[5]);
|
||||
|
||||
//reset minimap clear state
|
||||
int xd,yd;
|
||||
|
@ -2160,12 +2229,12 @@ void enterDungeon() {
|
|||
initMinimapLevel(5, false);
|
||||
newSeed();
|
||||
|
||||
//spawn new entities
|
||||
trySpawn(500, 5);
|
||||
|
||||
player.x = ((128/2) << 4) + 8;
|
||||
player.y = ((128/2) << 4) + 8;
|
||||
|
||||
//spawn new entities
|
||||
trySpawn(500, 5);
|
||||
|
||||
updateMusic(currentLevel, daytime);
|
||||
}
|
||||
|
||||
|
@ -2203,6 +2272,9 @@ u32 getMinimapColor(int level, int x, int y) {
|
|||
void initMinimapLevel(int level, bool loadUpWorld) {
|
||||
int x;
|
||||
int y;
|
||||
bool calculateCompass;
|
||||
|
||||
calculateCompass = ((!loadUpWorld) || (compassData[level][2] = 0)) && level<5;
|
||||
|
||||
//Create Dungeon entrance(not located in mapgen, so it can also be created in old worlds)
|
||||
if(level==4) {
|
||||
|
@ -2249,6 +2321,18 @@ void initMinimapLevel(int level, bool loadUpWorld) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if(calculateCompass) {
|
||||
//choose one stair down and store for magic compass
|
||||
switch (map[level][x + y * 128]) {
|
||||
case TILE_STAIRS_DOWN:
|
||||
case TILE_DUNGEON_ENTRANCE:
|
||||
compassData[level][2] = compassData[level][2] + 1;
|
||||
if((compassData[level][2]==1) || (rand()%(compassData[level][2])==0)) {
|
||||
compassData[level][0] = x;
|
||||
compassData[level][1] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Minimaps */
|
||||
sf2d_set_pixel(minimap[level], x, y, getMinimapColor(level, x, y));
|
||||
|
@ -2276,6 +2360,8 @@ void reloadColors() {
|
|||
dirtColor[4] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 4));
|
||||
|
||||
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));
|
||||
|
||||
|
@ -2298,4 +2384,7 @@ void reloadColors() {
|
|||
|
||||
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));
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include "SaveLoad.h"
|
||||
#include "Input.h"
|
||||
#include "MapGen.h"
|
||||
#include "Quests.h"
|
||||
|
||||
#include "icons2_png.h"
|
||||
#include "Font_png.h"
|
||||
|
@ -26,6 +27,13 @@
|
|||
#define MENU_SETTINGS_REBIND 12
|
||||
#define MENU_SETTINGS_TP 13
|
||||
#define MENU_DUNGEON 14
|
||||
#define MENU_NPC 15
|
||||
|
||||
#define NPC_GIRL 0
|
||||
#define NPC_PRIEST 1
|
||||
#define NPC_FARMER 2
|
||||
#define NPC_LIBRARIAN 3
|
||||
#define NPC_DWARF 4
|
||||
|
||||
#define TILE_NULL 255
|
||||
#define TILE_GRASS 0
|
||||
|
@ -60,9 +68,18 @@
|
|||
#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))
|
||||
|
||||
//TODO: Dont forget to change back
|
||||
#define TESTGODMODE true
|
||||
|
||||
bool screenShot;
|
||||
int loadedtp;
|
||||
|
||||
|
@ -86,6 +103,7 @@ sf2d_texture * minimap[6];
|
|||
u8 map[6][128*128];
|
||||
u8 data[6][128*128];
|
||||
u8 minimapData[128*128];
|
||||
u8 compassData[6][3];
|
||||
|
||||
u32 dirtColor[5];
|
||||
u32 grassColor;
|
||||
|
@ -98,6 +116,10 @@ u32 ironColor;
|
|||
u32 goldColor;
|
||||
u32 gemColor;
|
||||
u32 dungeonColor[2];
|
||||
u32 myceliumColor;
|
||||
u32 mushroomColor;
|
||||
u32 snowColor;
|
||||
u32 iceColor;
|
||||
|
||||
char currentFileName[256];
|
||||
extern u8 currentMenu;
|
||||
|
@ -110,11 +132,15 @@ s16 awX, awY;
|
|||
u32 tickCount;
|
||||
RecipeManager* currentRecipes;
|
||||
Entity* curChestEntity;
|
||||
char* currentCraftTitle;
|
||||
s16 curInvSel;
|
||||
bool quitGame;
|
||||
s8 currentSelection;
|
||||
|
||||
u16 daytime;
|
||||
int day;
|
||||
u8 season;
|
||||
bool rain;
|
||||
|
||||
void tickTile(int x, int y);
|
||||
bool tileIsSolid(int tile, Entity * e);
|
||||
|
|
|
@ -183,6 +183,9 @@ char* getItemName(int itemID, int countLevel){
|
|||
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;
|
||||
case TOOL_BUCKET:
|
||||
switch(countLevel){
|
||||
case 1: return "Water Bucket";
|
||||
|
@ -190,6 +193,7 @@ char* getItemName(int itemID, int countLevel){
|
|||
default: return "Empty Bucket";
|
||||
}
|
||||
case TOOL_BOW: return "Bow";
|
||||
case TOOL_MAGIC_COMPASS: return "Magic Compass";
|
||||
default: return ""; // null
|
||||
}
|
||||
}
|
||||
|
@ -287,8 +291,11 @@ char* getBasicItemName(int itemID, int countLevel){
|
|||
case ITEM_BONE: return "Bone";
|
||||
case ITEM_DUNGEON_KEY: return "Dungeon Key";
|
||||
case ITEM_WIZARD_SUMMON: return "Wizard Summon";
|
||||
case ITEM_DRAGON_EGG: return "%d Dragon Egg";
|
||||
case ITEM_DRAGON_SCALE: return "%d Dragon Scale";
|
||||
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 TOOL_BUCKET:
|
||||
switch(countLevel){
|
||||
case 1: return "Water Bucket";
|
||||
|
@ -296,6 +303,7 @@ char* getBasicItemName(int itemID, int countLevel){
|
|||
default: return "Empty Bucket";
|
||||
}
|
||||
case TOOL_BOW: return "Bow";
|
||||
case TOOL_MAGIC_COMPASS: return "Magic Compass";
|
||||
default: return ""; // null
|
||||
}
|
||||
|
||||
|
|
|
@ -68,9 +68,13 @@
|
|||
#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 TOOL_BUCKET 101
|
||||
#define TOOL_BOW 102
|
||||
#define TOOL_MAGIC_COMPASS 103
|
||||
|
||||
typedef struct Inventory Inventory;
|
||||
|
||||
|
|
566
source/MapGen.c
566
source/MapGen.c
|
@ -3,6 +3,9 @@
|
|||
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;
|
||||
}
|
||||
|
@ -64,9 +67,14 @@ void newSeed(){
|
|||
srand(time(NULL));
|
||||
}
|
||||
|
||||
void createAndValidateTopMap(int w, int h, u8 * map, u8 * data) {
|
||||
//TODO: Will need to reset entity manager if generation is retried
|
||||
void createAndValidateTopMap(int w, int h, int level, u8 * map, u8 * data) {
|
||||
do {
|
||||
createTopMap(w, h, map, data);
|
||||
//reset Entities
|
||||
(&eManager)->lastSlot[level] = 0;
|
||||
(&eManager)->entities[level][0] = nullEntity;
|
||||
|
||||
createTopMap(w, h, level, map, data);
|
||||
|
||||
int count[256]={[0 ... 255] = 0};
|
||||
int i;
|
||||
|
@ -81,9 +89,13 @@ void createAndValidateTopMap(int w, int h, u8 * map, u8 * data) {
|
|||
} while (true);
|
||||
}
|
||||
|
||||
void createAndValidateUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) {
|
||||
void createAndValidateUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) {
|
||||
do {
|
||||
createUndergroundMap(w, h, depthLevel, map, data);
|
||||
//reset Entities
|
||||
(&eManager)->lastSlot[level] = 0;
|
||||
(&eManager)->entities[level][0] = nullEntity;
|
||||
|
||||
createUndergroundMap(w, h, depthLevel, level, map, data);
|
||||
|
||||
int count[256]={[0 ... 255] = 0};
|
||||
int i = 0;
|
||||
|
@ -92,7 +104,7 @@ void createAndValidateUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 *
|
|||
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) 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;
|
||||
}
|
||||
if (depthLevel < 3) if (count[TILE_STAIRS_DOWN & 0xff] < 2) continue;
|
||||
|
@ -101,9 +113,13 @@ void createAndValidateUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 *
|
|||
} while (true);
|
||||
}
|
||||
|
||||
void createAndValidateDungeonMap(int w, int h, u8 * map, u8 * data) {
|
||||
void createAndValidateDungeonMap(int w, int h, int level, u8 * map, u8 * data) {
|
||||
do {
|
||||
createDungeonMap(w, h, map, data);
|
||||
//reset Entities
|
||||
(&eManager)->lastSlot[level] = 0;
|
||||
(&eManager)->entities[level][0] = nullEntity;
|
||||
|
||||
createDungeonMap(w, h, level, map, data);
|
||||
|
||||
int count[256]={[0 ... 255] = 0};
|
||||
int i = 0;
|
||||
|
@ -115,9 +131,13 @@ void createAndValidateDungeonMap(int w, int h, u8 * map, u8 * data) {
|
|||
} while (true);
|
||||
}
|
||||
|
||||
void createAndValidateSkyMap(int w, int h, u8 * map, u8 * data) {
|
||||
void createAndValidateSkyMap(int w, int h, int level, u8 * map, u8 * data) {
|
||||
do {
|
||||
createSkyMap(w, h, map, data);
|
||||
//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;
|
||||
|
@ -131,7 +151,7 @@ void createAndValidateSkyMap(int w, int h, u8 * map, u8 * data) {
|
|||
|
||||
|
||||
|
||||
void createTopMap(int w, int h, u8 * map, u8 * data) {
|
||||
void createTopMap(int w, int h, int level, u8 * map, u8 * data) {
|
||||
double* mnoise1 = Noise(w, h, 16);
|
||||
double* mnoise2 = Noise(w, h, 16);
|
||||
double* mnoise3 = Noise(w, h, 16);
|
||||
|
@ -185,6 +205,8 @@ void createTopMap(int w, int h, u8 * map, u8 * data) {
|
|||
}
|
||||
}
|
||||
|
||||
createVillage(w, h, level, map, data);
|
||||
|
||||
for (i = 0; i < w * h / 400; ++i) {
|
||||
x = rand()%w;
|
||||
y = rand()%h;
|
||||
|
@ -254,7 +276,7 @@ void createTopMap(int w, int h, u8 * map, u8 * data) {
|
|||
return;
|
||||
}
|
||||
|
||||
void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) {
|
||||
void createUndergroundMap(int w, int h, int depthLevel, int level, u8 * map, u8 * data) {
|
||||
double* mnoise1 = Noise(w, h, 16);
|
||||
double* mnoise2 = Noise(w, h, 16);
|
||||
double* mnoise3 = Noise(w, h, 16);
|
||||
|
@ -270,7 +292,8 @@ void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) {
|
|||
double* noise1 = Noise(w, h, 32);
|
||||
double* noise2 = Noise(w, h, 32);
|
||||
|
||||
int x, y;
|
||||
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;
|
||||
|
@ -307,7 +330,37 @@ void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) {
|
|||
}
|
||||
}
|
||||
}
|
||||
int i,j;
|
||||
|
||||
if(depthLevel==3) {
|
||||
createDwarfHouse(w, h, level, map, data);
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < w * h / 400; ++i) {
|
||||
int x = rand()%w;
|
||||
int y = rand()%h;
|
||||
|
@ -357,145 +410,9 @@ void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) {
|
|||
|
||||
}
|
||||
|
||||
void createDungeonRoom(int w, int h, bool dragon, u8 * map, u8 * data) {
|
||||
int tries;
|
||||
void createDungeonMap(int w, int h, int level, u8 * map, u8 * data) {
|
||||
hasNPC = false;
|
||||
|
||||
for(tries=0; tries<100; ++tries) {
|
||||
int x = 5+(rand()%(w-10 -10));
|
||||
int y = 5+(rand()%(h-10 -10));
|
||||
int xr;
|
||||
int yr;
|
||||
int wr = 10+(rand()%11);
|
||||
int hr = 10+(rand()&11);
|
||||
int xp;
|
||||
int yp;
|
||||
int i;
|
||||
|
||||
//create Dragonroom
|
||||
if(dragon) {
|
||||
wr = 20;
|
||||
hr = 20;
|
||||
x = 5 + (rand()%2)*(w-5*2-wr);
|
||||
y = 5 + (rand()%2)*(h-5*2-hr);
|
||||
}
|
||||
|
||||
if(x+wr > 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;
|
||||
}
|
||||
}
|
||||
|
||||
//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, 5), &eManager);
|
||||
break;
|
||||
}
|
||||
|
||||
//dekorate room
|
||||
bool lava = (rand()%4)==0;
|
||||
bool pillars = (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;
|
||||
} 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;
|
||||
} 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, 5), &eManager);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(rand()%50==0) map[i] = TILE_IRONORE + (rand()%3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void createDungeonMap(int w, int h, u8 * map, u8 * data) {
|
||||
int i, x, y;
|
||||
for(x = 0; x < w; ++x){
|
||||
for(y = 0; y < w; ++y){
|
||||
|
@ -504,18 +421,19 @@ void createDungeonMap(int w, int h, u8 * map, u8 * data) {
|
|||
//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, map, data);
|
||||
createDungeonRoom(w, h, true, level, map, data);
|
||||
|
||||
for(i = 0; i < 40; ++i) {
|
||||
createDungeonRoom(w, h, false, map, data);
|
||||
createDungeonRoom(w, h, false, level, map, data);
|
||||
}
|
||||
|
||||
//replace paths with actual dungeon floor
|
||||
|
@ -525,6 +443,7 @@ void createDungeonMap(int w, int h, u8 * map, u8 * data) {
|
|||
|
||||
if (map[i]==255) {
|
||||
map[i] = TILE_DUNGEON_FLOOR;
|
||||
data[i] = randomTile[rand()%randomTileSize];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -543,7 +462,7 @@ void createDungeonMap(int w, int h, u8 * map, u8 * data) {
|
|||
map[w/2-1 + (h/2-1) * w] = TILE_DUNGEON_WALL;
|
||||
}
|
||||
|
||||
void createSkyMap(int w, int h, u8 * map, u8 * data) {
|
||||
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;
|
||||
|
@ -603,3 +522,340 @@ void createSkyMap(int w, int h, u8 * map, u8 * data) {
|
|||
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; tries<maxTries; ++tries) {
|
||||
int x = rand()%(w-fw);
|
||||
int y = rand()%(h-fh);
|
||||
int nonFitting = 0;
|
||||
int xp;
|
||||
int yp;
|
||||
int i;
|
||||
int a;
|
||||
bool fits;
|
||||
|
||||
for(xp=x; xp<x+fw; ++xp) {
|
||||
for(yp=y; yp<y+fh; ++yp) {
|
||||
i = xp + yp * w;
|
||||
|
||||
fits = false;
|
||||
for(a=0; a<aLength; ++a) {
|
||||
if(map[i]==accepted[a]) {
|
||||
fits = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!fits) {
|
||||
nonFitting++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(nonFitting<leastNonFitting) {
|
||||
featureX = x;
|
||||
featureY = y;
|
||||
leastNonFitting = nonFitting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createVillageHouse(int hid, int x, int y, int hw, int hh, int ex, int ey, int w, int h, int level, u8 * map, u8 * data) {
|
||||
//create wall and floor
|
||||
int xp = x;
|
||||
int yp = y;
|
||||
for(xp=x; xp<x+hw; ++xp) {
|
||||
for(yp=y; yp<y+hh; ++yp) {
|
||||
if(xp==x || xp==x+hw-1 || yp==y || yp==y+hh-1) map[xp + yp * w] = TILE_WOOD_WALL;
|
||||
else map[xp + yp * w] = TILE_WOOD_FLOOR;
|
||||
}
|
||||
}
|
||||
|
||||
//recreate entrance
|
||||
map[ex + ey * w] = TILE_WOOD_FLOOR;
|
||||
|
||||
//create npcs
|
||||
if(hid==0) {
|
||||
addEntityToList(newNPCEntity(NPC_GIRL, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager);
|
||||
} else if(hid==1) {
|
||||
addEntityToList(newNPCEntity(NPC_PRIEST, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager);
|
||||
} else if(hid==2) {
|
||||
addEntityToList(newNPCEntity(NPC_FARMER, (x+hw/2) << 4, (y+hh/2) << 4, level), &eManager);
|
||||
//TODO: maybe create farm?
|
||||
for(xp=x; xp<x+hw; ++xp) {
|
||||
map[xp + yp * w] = TILE_WHEAT;
|
||||
map[xp + (yp+1) * w] = TILE_WHEAT;
|
||||
}
|
||||
}
|
||||
|
||||
//add Latern Entity
|
||||
int loffx = -12;
|
||||
int loffy = -12;
|
||||
if(hid==2) loffx = 12;
|
||||
addEntityToList(newFurnitureEntity(ITEM_LANTERN, NULL, ((x+hw/2) << 4) + loffx, ((y+hh/2) << 4) + loffy, level), &eManager);
|
||||
}
|
||||
|
||||
void createVillage(int w, int h, int level, u8 * map, u8 * data) {
|
||||
int vw = 17;
|
||||
int vh = 17;
|
||||
int accepted[] = {TILE_GRASS};
|
||||
findFeatureLocation(vw, vh, accepted, 1, 500, w, h, map, data);
|
||||
|
||||
int x = featureX;
|
||||
int y = featureY;
|
||||
int cx = x + vw/2;
|
||||
int cy = y + vh/2;
|
||||
int px;
|
||||
int py;
|
||||
|
||||
int hw;
|
||||
int hh;
|
||||
int hx;
|
||||
int hy;
|
||||
int ex;
|
||||
int ey;
|
||||
|
||||
//"well" in the middle
|
||||
map[(cx-1) + (cy-1) * w] = TILE_SAND;
|
||||
map[(cx+0) + (cy-1) * w] = TILE_SAND;
|
||||
map[(cx+1) + (cy-1) * w] = TILE_SAND;
|
||||
map[(cx-1) + (cy+0) * w] = TILE_SAND;
|
||||
map[(cx+0) + (cy+0) * w] = TILE_WATER;
|
||||
map[(cx+1) + (cy+0) * w] = TILE_SAND;
|
||||
map[(cx-1) + (cy+1) * w] = TILE_SAND;
|
||||
map[(cx+0) + (cy+1) * w] = TILE_SAND;
|
||||
map[(cx+1) + (cy+1) * w] = TILE_SAND;
|
||||
|
||||
//"paths" outwards leading to the "houses"
|
||||
//left
|
||||
px = cx-1;
|
||||
py = cy-1 + rand()%3;
|
||||
while(px>x) {
|
||||
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<x+vw) {
|
||||
map[px + py * w] = TILE_SAND;
|
||||
++px;
|
||||
}
|
||||
hw = 4 + rand()%2;
|
||||
hh = 4 + rand()%2;
|
||||
hx = px - hw;
|
||||
hy = py - hh + 2 + rand()%(hh-2);
|
||||
ex = px - hw;
|
||||
ey = py;
|
||||
createVillageHouse(2, hx, hy, hw, hh, ex, ey, w, h, level, map, data);
|
||||
}
|
||||
|
||||
void createDwarfHouse(int w, int h, int level, u8 * map, u8 * data) {
|
||||
int vw = 7;
|
||||
int vh = 7;
|
||||
int accepted[] = {TILE_ROCK};
|
||||
findFeatureLocation(vw, vh, accepted, 1, 500, w, h, map, data);
|
||||
|
||||
int x = featureX;
|
||||
int y = featureY;
|
||||
int xp;
|
||||
int yp;
|
||||
|
||||
for(xp=x; xp<x+vw; ++xp) {
|
||||
for(yp=y; yp<y+vh; ++yp) {
|
||||
if(xp==x || xp==x+vw-1 || yp==y || yp==y+vh-1) map[xp + yp * w] = TILE_STONE_WALL;
|
||||
else map[xp + yp * w] = TILE_DIRT;
|
||||
}
|
||||
}
|
||||
|
||||
//entrance
|
||||
xp = x+vw/2;
|
||||
map[xp + (yp-1) * w] = TILE_DIRT;
|
||||
|
||||
//pillars
|
||||
map[(x+2) + (y+2) * w] = TILE_STONE_WALL;
|
||||
map[(x+vw-1-2) + (y+2) * w] = TILE_STONE_WALL;
|
||||
|
||||
addEntityToList(newNPCEntity(NPC_DWARF, ((x+vw/2) << 4) + 8, (y+vh/2) << 4, level), &eManager);
|
||||
|
||||
|
||||
addEntityToList(newFurnitureEntity(ITEM_LANTERN, NULL, (x+1+1) << 4, (y+1+3) << 4, level), &eManager);
|
||||
addEntityToList(newFurnitureEntity(ITEM_LANTERN, NULL, (x+vw-1-1) << 4, (y+1+3) << 4, level), &eManager);
|
||||
}
|
||||
|
||||
void createDungeonRoom(int w, int h, bool dragon, int level, u8 * map, u8 * data) {
|
||||
int tries;
|
||||
|
||||
for(tries=0; tries<100; ++tries) {
|
||||
int x = 5+(rand()%(w-10 -10));
|
||||
int y = 5+(rand()%(h-10 -10));
|
||||
int xr;
|
||||
int yr;
|
||||
int wr = 10+(rand()%11);
|
||||
int hr = 10+(rand()&11);
|
||||
int xp;
|
||||
int yp;
|
||||
int i;
|
||||
|
||||
//create Dragonroom
|
||||
if(dragon) {
|
||||
wr = 20;
|
||||
hr = 20;
|
||||
x = 5 + (rand()%2)*(w-5*2-wr);
|
||||
y = 5 + (rand()%2)*(h-5*2-hr);
|
||||
}
|
||||
|
||||
if(x+wr > 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 && xr<x+wr-1 && yr>y && yr<y+hr-1 && yr%2==0)) {
|
||||
map[i] = TILE_BOOKSHELVES;
|
||||
data[i] = rand()%3;
|
||||
if(!hasNPC && rand()%50) {
|
||||
hasNPC = true;
|
||||
addEntityToList(newNPCEntity(NPC_LIBRARIAN, (xr << 4) + 8, ((yr+1) << 4) + 8, level), &eManager);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,11 +11,21 @@ float nextFloat();
|
|||
double sample(double * values, int x, int y);
|
||||
double * Noise(int w, int h, int featureSize);
|
||||
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 createAndValidateDungeonMap(int w, int h, u8 * map, u8 * data);
|
||||
void createDungeonMap(int w, int h, u8 * map, u8 * data);
|
||||
void createAndValidateSkyMap(int w, int h, u8 * map, u8 * data);
|
||||
void createSkyMap(int w, int h, u8 * map, u8 * data);
|
||||
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);
|
|
@ -531,6 +531,8 @@ void tickMenu(int menu){
|
|||
}
|
||||
|
||||
enterDungeon();
|
||||
} else if(TESTGODMODE) {
|
||||
enterDungeon();
|
||||
}
|
||||
} else {
|
||||
leaveDungeon();
|
||||
|
@ -755,6 +757,9 @@ void tickMenu(int menu){
|
|||
}
|
||||
|
||||
break;
|
||||
case MENU_NPC:
|
||||
tickNPCMenu();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1158,8 +1163,8 @@ void renderMenu(int menu,int xscr,int yscr){
|
|||
drawTextColor("Cost",248+1,78+1,0xFF000000);
|
||||
drawTextColor("Cost",248,78,0xFF6FE2E2);
|
||||
renderFrame(1,1,14,14,0xFFFF1010);
|
||||
drawTextColor("Crafting",24+1,14+1,0xFF000000);
|
||||
drawTextColor("Crafting",24,14,0xFF6FE2E2);
|
||||
drawTextColor(currentCraftTitle,24+1,14+1,0xFF000000);
|
||||
drawTextColor(currentCraftTitle,24,14,0xFF6FE2E2);
|
||||
renderRecipes(currentRecipes, 1, 1, 14, 14, curInvSel);
|
||||
|
||||
Recipe* rec = ¤tRecipes->recipes[curInvSel];
|
||||
|
@ -1421,6 +1426,19 @@ void renderMenu(int menu,int xscr,int yscr){
|
|||
}
|
||||
sf2d_end_frame();
|
||||
break;
|
||||
case MENU_NPC:
|
||||
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;
|
||||
|
||||
renderNPCMenu(xscr, yscr);
|
||||
sf2d_end_frame();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "MenuTutorial.h"
|
||||
#include "texturepack.h"
|
||||
#include "Quests.h"
|
||||
|
||||
void initMenus();
|
||||
|
||||
|
|
417
source/Quests.c
Normal file
417
source/Quests.c
Normal file
|
@ -0,0 +1,417 @@
|
|||
#include "Quests.h"
|
||||
|
||||
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;
|
||||
|
||||
void initQuests() {
|
||||
questManager.size = 2;
|
||||
questManager.questlines = (Questline*)malloc(sizeof(Questline) * (questManager.size));
|
||||
|
||||
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 resetQuests() {
|
||||
int i;
|
||||
for(i=0; i<questManager.size; ++i) {
|
||||
questManager.questlines[i].currentQuest = 0;
|
||||
questManager.questlines[i].currentQuestDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
void freeQuests() {
|
||||
free(questManager.questlines);
|
||||
free(priestTrades.recipes);
|
||||
free(farmerTrades.recipes);
|
||||
free(dwarfTrades.recipes);
|
||||
}
|
||||
|
||||
void openNPCMenu(int npc) {
|
||||
currentNPC = npc;
|
||||
currentNPCVal = 0;
|
||||
currentMenu = MENU_NPC;
|
||||
currentNPCMenu = NPC_MENU_TALK;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 1;
|
||||
currentTalkOption0 = "Bye";
|
||||
currentTalkOption1 = "";
|
||||
currentTalkOption2 = "";
|
||||
currentTalk0 = "";
|
||||
currentTalk1 = "";
|
||||
currentTalk2 = "";
|
||||
currentTalk3 = "";
|
||||
currentTalk4 = "";
|
||||
currentTalk5 = "";
|
||||
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
switch(currentNPC) {
|
||||
case NPC_GIRL:
|
||||
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
currentTalkOptions = 3;
|
||||
currentTalkOption1 = "Trade";
|
||||
currentTalkOption2 = "Why are you so few?";
|
||||
|
||||
currentTalk0 = "Welcome to our small village";
|
||||
currentTalk1 = "I am the leader of our group.";
|
||||
currentTalk2 = "If you have anything usefull";
|
||||
currentTalk3 = "for us I might be able to";
|
||||
currentTalk4 = "provide something nice in";
|
||||
currentTalk5 = "exchange.";
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
currentTalkOptions = 2;
|
||||
currentTalkOption0 = "Maybe some other time";
|
||||
currentTalkOption1 = "Trade";
|
||||
|
||||
currentTalk0 = "Hello friend!";
|
||||
currentTalk1 = "Nice seeing somebody else";
|
||||
currentTalk2 = "visit my little farm.";
|
||||
currentTalk3 = "Interested in buying some";
|
||||
currentTalk4 = "fresh farm goods?";
|
||||
currentTalk5 = "";
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
currentTalkOptions = 2;
|
||||
currentTalkOption0 = "Nothing";
|
||||
currentTalkOption1 = "What are you doing here?";
|
||||
if(questManager.questlines[1].currentQuest==1) {
|
||||
currentTalkOptions = 3;
|
||||
currentTalkOption2 = "Dwarvish language";
|
||||
}
|
||||
|
||||
currentTalk0 = "Oh hello?";
|
||||
currentTalk1 = "You must be quite brave";
|
||||
currentTalk2 = "or stupid to be walking";
|
||||
currentTalk3 = "around in this dungeon.";
|
||||
currentTalk4 = "";
|
||||
currentTalk5 = "Who can I help you?";
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(questManager.questlines[1].currentQuest<=1) {
|
||||
questManager.questlines[1].currentQuest = 1;
|
||||
|
||||
currentTalkOptions = 1;
|
||||
currentTalkOption0 = "?";
|
||||
|
||||
currentTalk0 = "Dwo neal bet reck da lo";
|
||||
currentTalk1 = "dhum don lir lugn at el";
|
||||
currentTalk2 = "nur tor erno ur yo trad";
|
||||
currentTalk3 = "thra so tir kho ukk tin";
|
||||
currentTalk4 = "hel dro ic";
|
||||
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) {
|
||||
currentTalkOptions = 2;
|
||||
currentTalkOption0 = "Not really";
|
||||
currentTalkOption1 = "Trade";
|
||||
|
||||
currentTalk0 = "How are ya?";
|
||||
currentTalk1 = "Pretty unusal meeting a";
|
||||
currentTalk2 = "human down here.";
|
||||
currentTalk3 = "";
|
||||
currentTalk4 = "have something valuable";
|
||||
currentTalk5 = "to trade?";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void tickTalkMenu() {
|
||||
if (k_menu.clicked || k_decline.clicked) currentMenu = MENU_NONE;
|
||||
|
||||
if (k_up.clicked){ ++currentTalkSel; if(currentTalkSel >= currentTalkOptions) currentTalkSel=0;}
|
||||
if (k_down.clicked){ --currentTalkSel; if(currentTalkSel < 0) currentTalkSel=currentTalkOptions-1;}
|
||||
|
||||
if(k_accept.clicked){
|
||||
currentTalkDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
void tickNPCMenu() {
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
if(currentNPCMenu==NPC_MENU_TALK) tickTalkMenu();
|
||||
|
||||
|
||||
switch(currentNPC) {
|
||||
case NPC_GIRL:
|
||||
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
if(currentNPCMenu==NPC_MENU_TALK && currentTalkDone) {
|
||||
if(currentNPCVal==0) {
|
||||
if(currentTalkSel==0) {
|
||||
currentMenu = MENU_NONE;
|
||||
} else if(currentTalkSel==1) {
|
||||
currentRecipes = &priestTrades;
|
||||
currentCraftTitle = "Trading";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
} else if(currentTalkSel==2) {
|
||||
currentNPCVal = 1;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 1;
|
||||
currentTalkOption0 = "...";
|
||||
|
||||
currentTalk0 = "For quite some time now this";
|
||||
currentTalk1 = "village has been tyrannized";
|
||||
currentTalk2 = "by a powerfull Air Wizard.";
|
||||
currentTalk3 = "We are the only ones who";
|
||||
currentTalk4 = "still have not given up";
|
||||
currentTalk5 = "our old homes.";
|
||||
}
|
||||
} else if(currentNPCVal==1) {
|
||||
if(currentTalkSel==0) {
|
||||
currentNPCVal = 2;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 1;
|
||||
currentTalkOption0 = "...";
|
||||
|
||||
currentTalk0 = "Most of the time the wizard";
|
||||
currentTalk1 = "hides somewhere in the";
|
||||
currentTalk2 = "cloudes. They can only be";
|
||||
currentTalk3 = "reached by a stairwell";
|
||||
currentTalk4 = "protected by an almost";
|
||||
currentTalk5 = "undestroyable stone barrier.";
|
||||
}
|
||||
} else if(currentNPCVal==2) {
|
||||
if(currentTalkSel==0) {
|
||||
currentNPCVal = 3;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 1;
|
||||
currentTalkOption0 = "...";
|
||||
|
||||
currentTalk0 = "I am guessing you would ";
|
||||
currentTalk1 = "need tools atleast as";
|
||||
currentTalk2 = "strong as diamonds to be";
|
||||
currentTalk3 = "able to destroy it.";
|
||||
currentTalk4 = "";
|
||||
currentTalk5 = "";
|
||||
}
|
||||
} else if(currentNPCVal==3) {
|
||||
if(currentTalkSel==0) {
|
||||
currentNPCVal = 4;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 2;
|
||||
currentTalkOption0 = "Let me do it!";
|
||||
currentTalkOption1 = "I am not sure";
|
||||
|
||||
currentTalk0 = "I am willing to give an";
|
||||
currentTalk1 = "ancient artifact passed";
|
||||
currentTalk2 = "down over generations to";
|
||||
currentTalk3 = "anybody who manages to";
|
||||
currentTalk4 = "chase the wizard away and";
|
||||
currentTalk5 = "come back with proof.";
|
||||
}
|
||||
} else if(currentNPCVal==4) {
|
||||
currentMenu = MENU_NONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
if(currentNPCMenu==NPC_MENU_TALK && currentTalkDone) {
|
||||
if(currentNPCVal==0) {
|
||||
if(currentTalkSel==0) {
|
||||
currentMenu = MENU_NONE;
|
||||
} else if(currentTalkSel==1) {
|
||||
currentRecipes = &farmerTrades;
|
||||
currentCraftTitle = "Trading";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
if(currentNPCMenu==NPC_MENU_TALK && currentTalkDone) {
|
||||
if(currentNPCVal==0) {
|
||||
if(currentTalkSel==0) {
|
||||
currentMenu = MENU_NONE;
|
||||
} else if(currentTalkSel==1) {
|
||||
currentNPCVal = 2;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 1;
|
||||
currentTalkOption0 = "Ok";
|
||||
|
||||
currentTalk0 = "The books in this dungeon";
|
||||
currentTalk1 = "house secrets that cannot be";
|
||||
currentTalk2 = "found anywhere else in the";
|
||||
currentTalk3 = "world. So I came to study";
|
||||
currentTalk4 = "them. Most are written in";
|
||||
currentTalk5 = "an ancient language.";
|
||||
} else if(currentTalkSel==2) {
|
||||
currentNPCVal = 1;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 2;
|
||||
currentTalkOption0 = "I need to think about it";
|
||||
currentTalkOption1 = "Here they are";
|
||||
|
||||
currentTalk0 = "So you have met a dwarf but";
|
||||
currentTalk1 = "had a little communication";
|
||||
currentTalk2 = "problem? I do have a dwarvish";
|
||||
currentTalk3 = "translation book but I havent";
|
||||
currentTalk4 = "read it yet. For 10 Gold bars";
|
||||
currentTalk5 = "I will give it to you anyway.";
|
||||
}
|
||||
} else if(currentNPCVal==1) {
|
||||
if(currentTalkSel==0) {
|
||||
currentMenu = MENU_NONE;
|
||||
} else if(currentTalkSel==1) {
|
||||
currentNPCVal = 2;
|
||||
|
||||
currentTalkSel = 0;
|
||||
currentTalkDone = false;
|
||||
currentTalkOptions = 1;
|
||||
currentTalkOption0 = "";
|
||||
|
||||
if(countItemInv(ITEM_GOLDINGOT,0,player.p.inv)>=10) {
|
||||
//remove gold from player inventory
|
||||
//TODO: Maybe I should make a generic substract items method sometime
|
||||
Item* item = getItemFromInventory(ITEM_GOLDINGOT, player.p.inv);
|
||||
item->countLevel -= 10;
|
||||
if(item->countLevel < 1) removeItemFromInventory(item->slotNum, player.p.inv);
|
||||
|
||||
questManager.questlines[1].currentQuest = 2;
|
||||
|
||||
currentTalk0 = "Thank you these will be";
|
||||
currentTalk1 = "really helpfull.";
|
||||
currentTalk2 = "Here take this book with";
|
||||
currentTalk3 = "it you should be able to";
|
||||
currentTalk4 = "easily understand anything";
|
||||
currentTalk5 = "a dwarf can say.";
|
||||
|
||||
currentTalkOption0 = "Thanks";
|
||||
} else {
|
||||
currentTalk0 = "You do not seem to have";
|
||||
currentTalk1 = "enough Gold Bars with you.";
|
||||
currentTalk2 = "";
|
||||
currentTalk3 = "Ask again when you have";
|
||||
currentTalk4 = "collected the 10 Bars.";
|
||||
currentTalk5 = "";
|
||||
|
||||
currentTalkOption0 = "Ok";
|
||||
}
|
||||
}
|
||||
} else if(currentNPCVal==2) {
|
||||
if(currentTalkSel==0) {
|
||||
currentMenu = MENU_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(questManager.questlines[1].currentQuest<=1) {
|
||||
if(currentNPCMenu==NPC_MENU_TALK && currentTalkDone) {
|
||||
if(currentNPCVal==0) currentMenu = MENU_NONE;
|
||||
}
|
||||
} else if(questManager.questlines[1].currentQuest==2) {
|
||||
if(currentNPCMenu==NPC_MENU_TALK && currentTalkDone) {
|
||||
if(currentTalkSel==0) {
|
||||
currentMenu = MENU_NONE;
|
||||
} else if(currentTalkSel==1) {
|
||||
currentRecipes = &dwarfTrades;
|
||||
currentCraftTitle = "Trading";
|
||||
currentMenu = MENU_CRAFTING;
|
||||
checkCanCraftRecipes(currentRecipes, player.p.inv);
|
||||
sortRecipes(currentRecipes);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void renderTalkMenu(char * name) {
|
||||
renderFrame(1,1,24,14,0xFFFF1010);
|
||||
drawTextColor(name,24+1,14+1,0xFF000000);
|
||||
drawTextColor(name,24,14,0xFF6FE2E2);
|
||||
|
||||
drawText(currentTalk0, 32, 32);
|
||||
drawText(currentTalk1, 32, 48);
|
||||
drawText(currentTalk2, 32, 64);
|
||||
drawText(currentTalk3, 32, 80);
|
||||
drawText(currentTalk4, 32, 96);
|
||||
drawText(currentTalk5, 32, 112);
|
||||
|
||||
if(currentTalkOptions>=3) drawText(currentTalkOption2, 64, 147);
|
||||
if(currentTalkOptions>=2) drawText(currentTalkOption1, 64, 171);
|
||||
if(currentTalkOptions>=1) drawText(currentTalkOption0, 64, 195);
|
||||
|
||||
if(currentTalkOptions>=3 && currentTalkSel==2) drawText(">", 48, 147);
|
||||
if(currentTalkOptions>=2 && currentTalkSel==1) drawText(">", 48, 171);
|
||||
if(currentTalkOptions>=1 && currentTalkSel==0) drawText(">", 48, 195);
|
||||
}
|
||||
|
||||
void renderNPCMenu(int xscr, int yscr) {
|
||||
//TODO: Handle upon currentNPC as well as the fitting quest progress
|
||||
switch(currentNPC) {
|
||||
case NPC_GIRL:
|
||||
if(currentNPCMenu==NPC_MENU_TALK) renderTalkMenu("TODO");
|
||||
break;
|
||||
case NPC_PRIEST:
|
||||
if(currentNPCMenu==NPC_MENU_TALK) renderTalkMenu("Priest Brom");
|
||||
break;
|
||||
case NPC_FARMER:
|
||||
if(currentNPCMenu==NPC_MENU_TALK) renderTalkMenu("Farmer Garrow");
|
||||
break;
|
||||
case NPC_LIBRARIAN:
|
||||
if(currentNPCMenu==NPC_MENU_TALK) renderTalkMenu("Librarian Ajihad");
|
||||
break;
|
||||
case NPC_DWARF:
|
||||
if(currentNPCMenu==NPC_MENU_TALK) renderTalkMenu("Dwarf Orik");
|
||||
break;
|
||||
}
|
||||
}
|
32
source/Quests.h
Normal file
32
source/Quests.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "render.h"
|
||||
#include "Crafting.h"
|
||||
|
||||
#define NPC_MENU_TALK 0
|
||||
|
||||
typedef struct {
|
||||
int currentQuest;
|
||||
bool currentQuestDone;
|
||||
} Questline;
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
Questline * questlines;
|
||||
} QuestlineManager;
|
||||
|
||||
QuestlineManager questManager;
|
||||
|
||||
RecipeManager priestTrades;
|
||||
RecipeManager farmerTrades;
|
||||
RecipeManager dwarfTrades;
|
||||
|
||||
void initQuests();
|
||||
void resetQuests();
|
||||
void freeQuests();
|
||||
|
||||
void openNPCMenu(int npc);
|
||||
|
||||
void renderNPCMenu(int xscr, int yscr);
|
||||
void tickNPCMenu();
|
138
source/Render.c
138
source/Render.c
|
@ -472,21 +472,38 @@ void renderTile(int i, int d, int x, int y) {
|
|||
checkSurrTiles4(x >> 4, y >> 4, TILE_FLOWER);
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_SAPLING_TREE);
|
||||
|
||||
renderConnectedTile4(x, y, 256, 0);
|
||||
if(currentLevel==1 && season==3) renderConnectedTile4(x, y, 256, 112);
|
||||
else if(currentLevel==1 && season==2) renderConnectedTile4(x, y, 256, 128);
|
||||
else renderConnectedTile4(x, y, 256, 0);
|
||||
break;
|
||||
case TILE_TREE:
|
||||
renderTile(TILE_GRASS, 0, x, y);
|
||||
|
||||
checkSurrTiles8(x >> 4, y >> 4, TILE_TREE);
|
||||
|
||||
if(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(season==3) {
|
||||
render(x, y, 352+((tu && tl && tul) ? 16 : 0), 112, 0);
|
||||
render(x+8, y, 360+((tu && tr && tur) ? 16 : 0), 112, 0);
|
||||
render(x, y+8, 352+((td && tl && tdl) ? 16 : 0), 120, 0);
|
||||
render(x+8, y+8, 360+((td && tr && tdr) ? 16 : 0), 120, 0);
|
||||
} else {
|
||||
render(x, y, 256+((tu && tl && tul) ? 16 : 0), 48, 0);
|
||||
render(x+8, y, 264+((tu && tr && tur) ? 16 : 0), 48, 0);
|
||||
render(x, y+8, 256+((td && tl && tdl) ? 16 : 0), 56, 0);
|
||||
render(x+8, y+8, 264+((td && tr && tdr) ? 16 : 0), 56, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
case TILE_ROCK:
|
||||
checkSurrTiles8(x >> 4, y >> 4, TILE_ROCK);
|
||||
if(currentLevel>1)
|
||||
renderConnectedTile8(x, y, 256, 96);
|
||||
else
|
||||
renderConnectedTile8(x, y, 336, 64);
|
||||
break;
|
||||
case TILE_HARDROCK:
|
||||
|
@ -504,15 +521,20 @@ void renderTile(int i, int d, int x, int y) {
|
|||
checkSurrTiles4(x >> 4, y >> 4, TILE_CACTUS);
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_SAPLING_CACTUS);
|
||||
|
||||
if(currentLevel==1 && season==3) {
|
||||
renderConnectedTile4(x, y, 256, 112);
|
||||
} else {
|
||||
renderConnectedTile4(x, y, 320, 0);
|
||||
|
||||
if (d > 0) {
|
||||
render16(x, y, 336, 48, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TILE_WATER:
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_WATER);
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE);
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_ICE);
|
||||
|
||||
renderConnectedTile4(x, y, 384, 0);
|
||||
|
||||
|
@ -541,7 +563,8 @@ void renderTile(int i, int d, int x, int y) {
|
|||
break;
|
||||
case TILE_FLOWER:
|
||||
renderTile(TILE_GRASS, 0, x, y);
|
||||
render16(x, y, 320, 48, getData(x >> 4, y >> 4));
|
||||
if(currentLevel==1 && season==3) render16(x, y, 320, 112, getData(x >> 4, y >> 4));
|
||||
else render16(x, y, 320, 48, getData(x >> 4, y >> 4));
|
||||
break;
|
||||
case TILE_STAIRS_DOWN:
|
||||
if (currentLevel == 0)
|
||||
|
@ -619,14 +642,14 @@ void renderTile(int i, int d, int x, int y) {
|
|||
renderConnectedTile8(x, y, 384, 32);
|
||||
break;
|
||||
case TILE_DUNGEON_FLOOR:
|
||||
render16(x, y, 464, 32, 0);
|
||||
render16(x, y, 464 + d*16, 32, 0);
|
||||
break;
|
||||
case TILE_DUNGEON_ENTRANCE:
|
||||
render16(x, y, 480 + (currentLevel==5 ? 16 : 0), 32, 0);
|
||||
render16(x, y, 352 + (currentLevel==5 ? 16 : 0), 80, 0);
|
||||
break;
|
||||
case TILE_MAGIC_BARRIER:
|
||||
renderTile(TILE_DUNGEON_FLOOR, 0, x, y);
|
||||
render16(x, y, 320, 64, 0);
|
||||
render16(x, y, 320, 64, getData(x >> 4, y >> 4));
|
||||
|
||||
//draw remaining pillar count
|
||||
if((player.x - (x+8))*(player.x - (x+8)) + (player.y - (y+8))*(player.y - (y+8)) <= 24*24) {
|
||||
|
@ -650,6 +673,38 @@ void renderTile(int i, int d, int x, int y) {
|
|||
drawSizedTextColor(currentCount, x+4, y+4, 2, dungeonColor[0]);
|
||||
}
|
||||
|
||||
break;
|
||||
case TILE_BOOKSHELVES:
|
||||
checkSurrTiles4(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(x >> 4, y >> 4, TILE_MYCELIUM);
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_MUSHROOM_BROWN);
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_MUSHROOM_RED);
|
||||
|
||||
if(currentLevel==1 && season==3) renderConnectedTile4(x, y, 256, 112);
|
||||
else renderConnectedTile4(x, y, 448, 80);
|
||||
break;
|
||||
case TILE_MUSHROOM_BROWN:
|
||||
renderTile(TILE_MYCELIUM, 0, x, y);
|
||||
render16(x, y, 448 + (d&0x1)*16, 96, 0);
|
||||
break;
|
||||
case TILE_MUSHROOM_RED:
|
||||
renderTile(TILE_MYCELIUM, 0, x, y);
|
||||
render16(x, y, 480 + (d&0x1)*16, 96, 0);
|
||||
break;
|
||||
case TILE_ICE:
|
||||
renderTile(TILE_WATER, 0, x, y);
|
||||
//checkSurrTiles4(x >> 4, y >> 4, TILE_WATER);
|
||||
//checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE);
|
||||
checkSurrTiles4(x >> 4, y >> 4, TILE_ICE);
|
||||
|
||||
renderConnectedTile4(x, y, 448, 112);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -858,6 +913,40 @@ void renderMenuBackground(int xScroll, int yScroll) {
|
|||
renderDayNight();
|
||||
}
|
||||
|
||||
void renderWeather(int xScroll, int yScroll) {
|
||||
if(currentLevel==1) {
|
||||
if(season==3) {
|
||||
int xp = -128 + ((tickCount>>2) - xScroll*2)%128;
|
||||
int yp = -128 + ((tickCount>>1) - yScroll*2)%128;
|
||||
int xp2 = 0 - ((tickCount>>2) + xScroll*2)%128;
|
||||
int yp2 = -128 + ((tickCount>>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(rain) {
|
||||
int xp = -((xScroll*2)%128);
|
||||
int yp = -128 + ((tickCount<<2) - yScroll*2)%128;
|
||||
int xp2 = -((xScroll*2+8)%128);
|
||||
int yp2 = -128 + ((tickCount<<1)+64 - yScroll*2)%128;
|
||||
int xt;
|
||||
int yt;
|
||||
for(xt=0; xt<4; ++xt) {
|
||||
for(yt=0; yt<3; ++yt) {
|
||||
sf2d_draw_texture_part_scale(icons, xp + xt*128, yp + yt*128, 128, 0, 64, 64, 2, 2);
|
||||
sf2d_draw_texture_part_scale(icons, xp2 + xt*128, yp2 + yt*128, 128, 0, 64, 64, 2, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renderDayNight() {
|
||||
if(currentLevel==1 && (daytime<6000 || daytime>18000)) {
|
||||
int color1 = 0x000C0C0C;
|
||||
|
@ -1197,6 +1286,8 @@ void renderEntity(Entity* e, int x, int y) {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1244,8 +1335,7 @@ void renderItemList(Inventory * inv, int xo, int yo, int x1, int y1,
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -1265,16 +1355,16 @@ void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1,
|
|||
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;
|
||||
drawTextColor(
|
||||
getBasicItemName(r->recipes[i + io].itemResult,
|
||||
r->recipes[i + io].itemAmountLevel), x + 18, y + 2,
|
||||
col);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
int yy = selected + 1 - io + yo;
|
||||
|
@ -1317,6 +1407,8 @@ 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;
|
||||
|
@ -1491,11 +1583,31 @@ void renderItemIcon(int itemID, int countLevel, int x, int y) {
|
|||
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 = compassData[currentLevel][0] - (player.x>>4);
|
||||
yd = compassData[currentLevel][1] - (player.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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile);
|
|||
void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile);
|
||||
void renderBackground(int xScroll, int yScroll);
|
||||
void renderMenuBackground(int xScroll, int yScroll); //Renders the darkness
|
||||
void renderWeather(int xScroll, int yScroll);
|
||||
void renderDayNight();
|
||||
void renderButtonIcon(u32 icon, int x, int y, float scale);
|
||||
|
||||
|
|
|
@ -1,27 +1,5 @@
|
|||
#include "SaveLoad.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_SKELETON:
|
||||
case ENTITY_KNIGHT:
|
||||
case ENTITY_ITEM:
|
||||
case ENTITY_FURNITURE:
|
||||
case ENTITY_PASSIVE:
|
||||
case ENTITY_GLOWWORM:
|
||||
case ENTITY_DRAGON:
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool entityIsImportant(Entity * e){
|
||||
switch(e->type){
|
||||
case ENTITY_AIRWIZARD:
|
||||
|
@ -34,12 +12,24 @@ bool entityIsImportant(Entity * e){
|
|||
case ENTITY_PASSIVE:
|
||||
case ENTITY_GLOWWORM:
|
||||
case ENTITY_DRAGON:
|
||||
case ENTITY_NPC:
|
||||
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;
|
||||
|
@ -107,6 +97,9 @@ void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +113,25 @@ void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player
|
|||
|
||||
fwrite(minimapData, sizeof(u8), 128*128, file); // Minimap, visibility data 16KB
|
||||
|
||||
//Quest Data
|
||||
fwrite(&questManager.size, sizeof(int), 1, file);
|
||||
for(i = 0; i < questManager.size; ++i) {
|
||||
fwrite(&(questManager.questlines[i].currentQuest), sizeof(int), 1, file);
|
||||
fwrite(&(questManager.questlines[i].currentQuestDone), sizeof(bool), 1, file);
|
||||
}
|
||||
|
||||
//Compass Data
|
||||
for(i=0; i<6; ++i) {
|
||||
fwrite(&(compassData[i][0]), sizeof(u8), 1, file); //x of choosen stair
|
||||
fwrite(&(compassData[i][1]), sizeof(u8), 1, file); //y of choosen stair
|
||||
fwrite(&(compassData[i][2]), sizeof(u8), 1, file); //count
|
||||
}
|
||||
|
||||
//Day/season Data
|
||||
fwrite(&day, sizeof(int), 1, file);
|
||||
fwrite(&season, sizeof(u8), 1, file);
|
||||
fwrite(&rain, sizeof(bool), 1, file);
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
|
@ -335,6 +347,16 @@ int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * m
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,6 +370,40 @@ int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * m
|
|||
|
||||
fread(minimapData, sizeof(u8), 128*128, file);
|
||||
|
||||
//Quest Data
|
||||
int qsize = 0;
|
||||
fread(&qsize, sizeof(int), 1, file);
|
||||
for(i = 0; i < qsize; ++i) {
|
||||
fread(&(questManager.questlines[i].currentQuest), sizeof(int), 1, file);
|
||||
fread(&(questManager.questlines[i].currentQuestDone), sizeof(bool), 1, file);
|
||||
}
|
||||
//fill missing questlines with "no progress done"
|
||||
for(i = qsize; i < questManager.size; ++i) {
|
||||
questManager.questlines[i].currentQuest = 0;
|
||||
questManager.questlines[i].currentQuestDone = false;
|
||||
}
|
||||
|
||||
//Compass Data
|
||||
//reset incase it is missing in the save
|
||||
for(i=0; i<6; ++i) {
|
||||
compassData[i][0] = 0; //x of choosen stair
|
||||
compassData[i][1] = 0; //y of choosen stair
|
||||
compassData[i][2] = 0; //count
|
||||
}
|
||||
for(i=0; i<6; ++i) {
|
||||
fread(&(compassData[i][0]), sizeof(u8), 1, file); //x of choosen stair
|
||||
fread(&(compassData[i][1]), sizeof(u8), 1, file); //y of choosen stair
|
||||
fread(&(compassData[i][2]), sizeof(u8), 1, file); //count
|
||||
}
|
||||
|
||||
//Day/season Data
|
||||
day = 0;
|
||||
season = 0;
|
||||
rain = false;
|
||||
fread(&day, sizeof(int), 1, file);
|
||||
fread(&season, sizeof(u8), 1, file);
|
||||
fread(&rain, sizeof(bool), 1, file);
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
#include "Menu.h"
|
||||
#include "texturepack.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 initMiniMapData() {
|
||||
int i;
|
||||
for(i = 0; i < 128 * 128; ++i) {
|
||||
|
@ -29,11 +33,11 @@ void initMiniMap(bool loadUpWorld) {
|
|||
|
||||
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]);
|
||||
createAndValidateSkyMap(128, 128, 0, map[0], data[0]);
|
||||
createAndValidateTopMap(128, 128, 1, map[1], data[1]);
|
||||
createAndValidateUndergroundMap(128, 128, 1, 2, map[2], data[2]);
|
||||
createAndValidateUndergroundMap(128, 128, 2, 3, map[3], data[3]);
|
||||
createAndValidateUndergroundMap(128, 128, 3, 4, map[4], data[4]);
|
||||
}
|
||||
|
||||
void setupGame(bool loadUpWorld) {
|
||||
|
@ -48,6 +52,7 @@ void setupGame(bool loadUpWorld) {
|
|||
if (!loadUpWorld) {
|
||||
initNewMap();
|
||||
initPlayer();
|
||||
resetQuests();
|
||||
airWizardHealthDisplay = 2000;
|
||||
int i;
|
||||
for (i = 0; i < 5; ++i) {
|
||||
|
@ -55,8 +60,12 @@ void setupGame(bool loadUpWorld) {
|
|||
}
|
||||
addEntityToList(newAirWizardEntity(630, 820, 0), &eManager);
|
||||
daytime = 6000;
|
||||
day = 0;
|
||||
season = 0;
|
||||
rain = false;
|
||||
} else {
|
||||
initPlayer();
|
||||
resetQuests();
|
||||
loadWorld(currentFileName, &eManager, &player, (u8*) map, (u8*) data);
|
||||
}
|
||||
|
||||
|
@ -78,7 +87,7 @@ void setupBGMap(bool loadUpWorld) {
|
|||
|
||||
if(!loadUpWorld) {
|
||||
newSeed();
|
||||
createAndValidateTopMap(128, 128, map[1], data[1]);
|
||||
createAndValidateTopMap(128, 128, 1, map[1], data[1]);
|
||||
} else {
|
||||
loadWorld(currentFileName, &eManager, &player, (u8*) map, (u8*) data);
|
||||
}
|
||||
|
@ -113,6 +122,14 @@ void tick() {
|
|||
//daytime += 20;
|
||||
if(daytime>=24000) {
|
||||
daytime -= 24000;
|
||||
++day;
|
||||
//TODO: maybe make season length not as hardcoded + make the transition better (fade to black and back maybe?)
|
||||
if(day%7==0) {
|
||||
++season;
|
||||
if(season==4) season = 0;
|
||||
}
|
||||
rain = false;
|
||||
if(season!=3 && rand()%5==0) rain = true;
|
||||
}
|
||||
if(daytime==6000 && currentLevel==1) {
|
||||
playMusic(music_floor1);
|
||||
|
@ -138,25 +155,20 @@ void tick() {
|
|||
else if (yscr > 1912)
|
||||
yscr = 1912;
|
||||
|
||||
if(eManager.lastSlot[currentLevel]<80) {
|
||||
if(eManager.lastSlot[currentLevel]<80 && currentLevel != 5) {
|
||||
trySpawn(1, currentLevel);
|
||||
}
|
||||
|
||||
for (i = 0; i < eManager.lastSlot[currentLevel]; ++i) {
|
||||
Entity * e = &eManager.entities[currentLevel][i];
|
||||
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 && (daytime>6000 || daytime<18000)))
|
||||
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 && (daytime>6000 || daytime<18000))
|
||||
|| (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() {
|
||||
|
@ -243,6 +255,7 @@ int main() {
|
|||
|
||||
tickCount = 0;
|
||||
initRecipes();
|
||||
initQuests();
|
||||
while (aptMainLoop()) {
|
||||
++tickCount;
|
||||
hidScanInput();
|
||||
|
@ -266,6 +279,7 @@ int main() {
|
|||
renderBackground(xscr, yscr);
|
||||
renderEntities(player.x, player.y, &eManager);
|
||||
renderPlayer();
|
||||
renderWeather(xscr, yscr);
|
||||
|
||||
resetStencilStuff();
|
||||
|
||||
|
@ -299,6 +313,7 @@ int main() {
|
|||
|
||||
stopMusic();
|
||||
|
||||
freeQuests();
|
||||
freeRecipes();
|
||||
|
||||
freeLightBakes();
|
||||
|
|
Loading…
Add table
Reference in a new issue