Example sign with conversation.
This commit is contained in:
@ -21,7 +21,11 @@
|
||||
"maps": {
|
||||
"testmap": {
|
||||
"bob": "Hello, I am Bob.",
|
||||
"sign": "This is a sign."
|
||||
"sign": "This is a sign.",
|
||||
"sign2": {
|
||||
"1": "This is another sign.",
|
||||
"2": "It has two lines."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -42,6 +42,15 @@
|
||||
"y": 8,
|
||||
"text": "maps.testmap.sign"
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"x": 2,
|
||||
"y": 2,
|
||||
"texts": [
|
||||
"maps.testmap.sign2.1",
|
||||
"maps.testmap.sign2.2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 4,
|
||||
"x": 6,
|
||||
|
@ -53,7 +53,27 @@ void assetMapLoadEntity(
|
||||
val->type == ASSET_JSON_DATA_TYPE_STRING,
|
||||
"assetMapLoad: Sign text is not a string!"
|
||||
);
|
||||
signTextSet(&ent->sign, val->string);
|
||||
signTextAppend(&ent->sign, val->string);
|
||||
}
|
||||
|
||||
val = assetJsonGetObjectValue(jEnt, "texts");
|
||||
if(val != NULL) {
|
||||
assertTrue(
|
||||
val->type == ASSET_JSON_DATA_TYPE_ARRAY,
|
||||
"assetMapLoad: Sign texts is not an array!"
|
||||
);
|
||||
assertTrue(
|
||||
val->array.length <= SIGN_TEXT_COUNT_MAX,
|
||||
"assetMapLoad: Too many sign texts!"
|
||||
);
|
||||
for(int32_t i = 0; i < val->array.length; i++) {
|
||||
assetjson_t *subVal = val->array.value[i];
|
||||
assertTrue(
|
||||
subVal->type == ASSET_JSON_DATA_TYPE_STRING,
|
||||
"assetMapLoad: Sign text is not a string!"
|
||||
);
|
||||
signTextAppend(&ent->sign, subVal->string);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -46,7 +46,6 @@ void gameInit() {
|
||||
gameupdateresult_t gameUpdate(const float_t delta) {
|
||||
timeUpdate(delta);
|
||||
inputUpdate();
|
||||
conversationUpdate();
|
||||
|
||||
switch(GAME.state) {
|
||||
case GAME_STATE_INITIAL:
|
||||
|
@ -10,10 +10,13 @@
|
||||
#include "input.h"
|
||||
#include "ui/textbox.h"
|
||||
#include "ui/testmenu.h"
|
||||
#include "rpg/conversation/conversation.h"
|
||||
|
||||
void gameStateOverworldUpdate() {
|
||||
textboxUpdate();
|
||||
testMenuUpdate();
|
||||
conversationUpdate();
|
||||
|
||||
if(GAME.currentMap) mapUpdate(GAME.currentMap);
|
||||
if(inputWasPressed(INPUT_BIND_PAUSE)) GAME.state = GAME_STATE_PAUSED;
|
||||
}
|
@ -30,8 +30,10 @@ void conversationUpdate() {
|
||||
if(CONVERSATION.init == NULL || CONVERSATION.update == NULL) return;
|
||||
|
||||
uint16_t ret;
|
||||
bool_t recheck = true;
|
||||
|
||||
// Init or update.
|
||||
while(recheck) {
|
||||
switch(CONVERSATION.index) {
|
||||
case CONVERSATION_NOT_INITIALIZED:
|
||||
CONVERSATION.index = 0;
|
||||
@ -45,6 +47,7 @@ void conversationUpdate() {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Check ret value and update conversation.
|
||||
switch(ret) {
|
||||
case CONVERSATION_NEXT:
|
||||
@ -55,7 +58,8 @@ void conversationUpdate() {
|
||||
break;
|
||||
|
||||
case CONVERSATION_CONTINUE:
|
||||
return;
|
||||
recheck = false;
|
||||
break;
|
||||
|
||||
case CONVERSATION_RESTART:
|
||||
CONVERSATION.index = 0;
|
||||
@ -64,11 +68,13 @@ void conversationUpdate() {
|
||||
|
||||
case CONVERSATION_INVALID:
|
||||
assertUnreachable("Invalid converstaion retval");
|
||||
recheck = false;
|
||||
break;
|
||||
|
||||
case CONVERSATION_DONE:
|
||||
CONVERSATION.init = NULL;
|
||||
CONVERSATION.update = NULL;
|
||||
recheck = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -76,3 +82,4 @@ void conversationUpdate() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -21,12 +21,12 @@ uint16_t conversationInteractEntityInit(
|
||||
entity_t *e = (entity_t*)convo->data.entityInteract.entity;
|
||||
switch(e->type) {
|
||||
case ENTITY_TYPE_SIGN:
|
||||
textboxSetText("entities.sign.name", e->sign.text);
|
||||
return 0;
|
||||
textboxSetText("entities.sign.name", e->sign.texts[i]);
|
||||
return i;
|
||||
|
||||
case ENTITY_TYPE_NPC:
|
||||
textboxSetText(e->npc.name, e->npc.text);
|
||||
return 0;
|
||||
textboxSetText(e->npc.text.name, e->npc.text.text);
|
||||
return i;
|
||||
|
||||
default:
|
||||
assertUnreachable("Invalid entity type for conversation.");
|
||||
@ -38,6 +38,18 @@ uint16_t conversationInteractEntityUpdate(
|
||||
conversation_t *convo,
|
||||
const uint16_t i
|
||||
) {
|
||||
assertNotNull(convo, "Conversation is NULL!");
|
||||
assertNotNull(convo->data.entityInteract.entity, "Conversation user is NULL!");
|
||||
|
||||
entity_t *e = (entity_t*)convo->data.entityInteract.entity;
|
||||
switch(e->type) {
|
||||
case ENTITY_TYPE_SIGN:
|
||||
if(textboxIsOpen()) return CONVERSATION_CONTINUE;
|
||||
if(i == SIGN_TEXT_COUNT_MAX-1) return CONVERSATION_DONE;
|
||||
if(e->sign.texts[i+1][0] == '\0') return CONVERSATION_DONE;
|
||||
return CONVERSATION_NEXT;
|
||||
|
||||
default:
|
||||
switch(i) {
|
||||
case 0:
|
||||
return textboxIsOpen() ? CONVERSATION_CONTINUE : CONVERSATION_DONE;
|
||||
@ -46,3 +58,4 @@ uint16_t conversationInteractEntityUpdate(
|
||||
return CONVERSATION_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ void entityInteractEntity(
|
||||
conversationInteractEntityUpdate,
|
||||
(conversationdata_t){ .entityInteract = { .entity = target } }
|
||||
);
|
||||
source->state = ENTITY_STATE_TALKING;
|
||||
return;
|
||||
|
||||
case ENTITY_TYPE_SIGN:
|
||||
@ -41,6 +42,7 @@ void entityInteractEntity(
|
||||
conversationInteractEntityUpdate,
|
||||
(conversationdata_t){ .entityInteract = { .entity = target } }
|
||||
);
|
||||
source->state = ENTITY_STATE_TALKING;
|
||||
return;
|
||||
|
||||
case ENTITY_TYPE_DOOR:
|
||||
|
@ -10,18 +10,16 @@
|
||||
|
||||
void npcInit(npc_t *npc) {
|
||||
assertNotNull(npc, "npcInit: NPC is NULL!");
|
||||
npc->name[0] = '\0';
|
||||
npc->text[0] = '\0';
|
||||
}
|
||||
|
||||
void npcNameSet(npc_t *npc, const char_t *name) {
|
||||
assertNotNull(npc, "npcNameSet: NPC is NULL!");
|
||||
assertNotNull(name, "npcNameSet: Name is NULL!");
|
||||
strncpy(npc->name, name, LANGUAGE_STRING_KEY_LENGTH_MAX);
|
||||
strncpy(npc->text.name, name, LANGUAGE_STRING_KEY_LENGTH_MAX);
|
||||
}
|
||||
|
||||
void npcTextSet(npc_t *npc, const char_t *text) {
|
||||
assertNotNull(npc, "npcTextSet: NPC is NULL!");
|
||||
assertNotNull(text, "npcTextSet: Text is NULL!");
|
||||
strncpy(npc->text, text, LANGUAGE_STRING_KEY_LENGTH_MAX);
|
||||
strncpy(npc->text.text, text, LANGUAGE_STRING_KEY_LENGTH_MAX);
|
||||
}
|
@ -11,6 +11,15 @@
|
||||
typedef struct {
|
||||
char_t name[LANGUAGE_STRING_KEY_LENGTH_MAX+1];
|
||||
char_t text[LANGUAGE_STRING_KEY_LENGTH_MAX+1];
|
||||
} npctext_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t nothing;
|
||||
} npcconversation_t;
|
||||
|
||||
typedef union {
|
||||
npctext_t text;
|
||||
npcconversation_t conversation;
|
||||
} npc_t;
|
||||
|
||||
/**
|
||||
|
@ -7,14 +7,24 @@
|
||||
|
||||
#include "sign.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
void signInit(sign_t *sign) {
|
||||
assertNotNull(sign, "signInit: Sign is NULL!");
|
||||
sign->text[0] = '\0';
|
||||
memorySet(sign, 0, sizeof(sign_t));
|
||||
}
|
||||
|
||||
void signTextSet(sign_t *sign, const char_t *text) {
|
||||
assertNotNull(sign, "signTextSet: Sign is NULL!");
|
||||
assertNotNull(text, "signTextSet: Text is NULL!");
|
||||
strncpy(sign->text, text, LANGUAGE_STRING_KEY_LENGTH_MAX);
|
||||
void signTextAppend(sign_t *sign, const char_t *text) {
|
||||
assertNotNull(sign, "signConversationAppend: Sign is NULL!");
|
||||
assertNotNull(text, "signConversationAppend: Text is NULL!");
|
||||
|
||||
// Find the first empty slot
|
||||
for(int32_t i = 0; i < SIGN_TEXT_COUNT_MAX; i++) {
|
||||
if(sign->texts[i][0] == '\0') {
|
||||
strncpy(sign->texts[i], text, LANGUAGE_STRING_KEY_LENGTH_MAX);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assertUnreachable("signConversationAppend: No empty slots found!");
|
||||
}
|
@ -8,8 +8,10 @@
|
||||
#pragma once
|
||||
#include "locale/language.h"
|
||||
|
||||
#define SIGN_TEXT_COUNT_MAX 32
|
||||
|
||||
typedef struct {
|
||||
char_t text[LANGUAGE_STRING_KEY_LENGTH_MAX+1];
|
||||
char_t texts[SIGN_TEXT_COUNT_MAX][LANGUAGE_STRING_KEY_LENGTH_MAX+1];
|
||||
} sign_t;
|
||||
|
||||
/**
|
||||
@ -20,9 +22,9 @@ typedef struct {
|
||||
void signInit(sign_t *sign);
|
||||
|
||||
/**
|
||||
* Sets the text of a sign.
|
||||
* Appends text to the sign's conversation.
|
||||
*
|
||||
* @param sign Sign to set text for.
|
||||
* @param text Text to set.
|
||||
* @param sign Sign to append conversation to.
|
||||
* @param text Text to append.
|
||||
*/
|
||||
void signTextSet(sign_t *sign, const char_t *text);
|
||||
void signTextAppend(sign_t *sign, const char_t *text);
|
Reference in New Issue
Block a user