marrub
/
Lithia
Archived
1
0
Fork 0
This repository has been archived on 2023-06-17. You can view files and clone it, but cannot push or open issues/pull-requests.
Lithia/source/Main/p_bip.c

476 lines
12 KiB
C

// Copyright © 2016-2017 Graham Sanderson, all rights reserved.
#include "lith_common.h"
#include "lith_player.h"
#include "lith_bip.h"
#include "lith_list.h"
#include "lith_world.h"
#include "lith_file.h"
#include "lith_tokbuf.h"
#include <ctype.h>
#define ForCategory() for(int categ = BIPC_NONE + 1; categ < BIPC_MAX; categ++)
#define ForPage() forlist(bippage_t *page, bip->infogr[categ])
#define ForCategoryAndPage() ForCategory() ForPage()
// Types ---------------------------------------------------------------------|
struct page_info
{
__str shname;
__str flname;
__str body;
};
struct page_init
{
int pclass;
__str name;
bip_unlocks_t unlocks;
bool isfree;
};
// Static Functions ----------------------------------------------------------|
//
// GetPageInfo
//
static struct page_info GetPageInfo(bippage_t const *page)
{
struct page_info pinf;
pinf.shname = page->category == BIPC_MAIL
? page->name
: Language("LITH_TXT_INFO_SHORT_%S", page->name);
pinf.body = page->body
? page->body
: Language("LITH_TXT_INFO_DESCR_%S", page->name);
pinf.flname = page->title
? page->title
: Language("LITH_TXT_INFO_TITLE_%S", page->name);
return pinf;
}
//
// SetCurPage
//
static void SetCurPage(gui_state_t *g, bip_t *bip, bippage_t *page, __str body)
{
bip->curpage = page;
Lith_GUI_TypeOn(g, &CBIState(g)->biptypeon, body);
Lith_GUI_ScrollReset(g, &CBIState(g)->bipinfoscr);
}
//
// UnlockPage
//
static void UnlockPage(bip_t *bip, bippage_t *page, int pclass)
{
bip->pageavail++;
bip->categoryavail[page->category]++;
page->unlocked = true;
for(int i = 0; i < countof(page->unlocks) && page->unlocks[i]; i++)
bip->unlock(page->unlocks[i], pclass);
}
//
// AddToBIP
//
optargs(1) static void AddToBIP(bip_t *bip, int categ, int pclass, struct page_init const *pinit, bool isfree)
{
__str image = LanguageNull("LITH_TXT_INFO_IMAGE_%S", pinit->name);
int height = strtoi_str(Language("LITH_TXT_INFO_CSIZE_%S", pinit->name), null, 0);
bippage_t *page = Salloc(bippage_t);
page->name = pinit->name;
page->category = categ;
page->unlocked = false;
page->image = image;
page->height = height;
memmove(page->unlocks, pinit->unlocks, sizeof(page->unlocks));
page->link.construct(page);
page->link.link(&bip->infogr[categ]);
// we have to pass along the player's class so discriminators don't fuck up
if(isfree) UnlockPage(bip, page, pclass);
}
//
// CatFromStr
//
stkcall static int CatFromStr(__str name)
{
#define LITH_X(n, _) if(name == #n) return BIPC_##n;
#include "lith_bip.h"
return BIPC_NONE;
}
//
// PClFromStr
//
stkcall static int PClFromStr(__str name)
{
#define LITH_X(n, pc) if(name == #n || name == #pc) return pc;
#include "lith_player.h"
return 0;
}
//
// LoadBIPInfo
//
static int LoadBIPInfo(__str fname, bip_t *bip, int pclass)
{
struct tokbuf tb = {
.bbeg = 4, .bend = 10,
.fp = W_Open(fname, c"r"),
.tokProcess = Lith_TBufProcL
};
if(!tb.fp) return 0;
tb.ctor();
bool catfree = false;
int categ = BIPC_NONE;
int total = 0;
struct page_init page;
for(struct token *tok; (tok = tb.get())->type != tok_eof;) switch(tok->type)
{
case tok_lnend:
continue;
case tok_at:
// @ Include
tok = tb.get();
total += LoadBIPInfo(Lith_TokStr(tok), bip, pclass);
break;
case tok_xor:
// ^ Category [*]
tok = tb.get();
categ = CatFromStr(Lith_TokStr(tok));
catfree = tb.drop(tok_mul);
break;
case tok_identi:
// Classes... Name [*] [-> Unlocks...]
page = (struct page_init){};
do
page.pclass |= PClFromStr(Lith_TokStr(tok));
while(tb.drop(tok_or) && (tok = tb.get()));
tok = tb.get();
page.name = Lith_TokStr(tok);
page.isfree = tb.drop(tok_mul);
if(tb.drop(tok_rarrow))
for(int i = 0; i < countof(page.unlocks) && !tb.drop(tok_lnend); i++)
{
tok = tb.get();
page.unlocks[i] = Lith_TokStr(tok);
}
if(categ != BIPC_NONE && pclass & page.pclass)
AddToBIP(bip, categ, pclass, &page, page.isfree || catfree);
total++;
break;
}
tb.dtor();
fclose(tb.fp);
return total;
}
// Extern Functions ----------------------------------------------------------|
//
// Lith_PlayerInitBIP
//
script void Lith_PlayerInitBIP(struct player *p)
{
bip_t *bip = &p->bip;
ForCategory()
bip->infogr[categ].free(true);
int total = LoadBIPInfo("LITH_BIPINFO", bip, p->pclass);
if(world.dbgLevel) p->logH("> There are %i info pages!", total);
ForCategory()
bip->pagemax += bip->categorymax[categ] = bip->infogr[categ].size;
if(world.dbgBIP)
{
bip->pageavail = bip->pagemax;
ForCategory() bip->categoryavail[categ] = bip->categorymax[categ];
ForCategoryAndPage() page->unlocked = true;
}
bip->init = true;
}
//
// Lith_DeliverMail
//
script void Lith_DeliverMail(struct player *p, __str title, int flags)
{
if(p->pclass & pcl_mods) return;
p->setActivator();
flags |= strtoi_str(Language("LITH_TXT_MAIL_FLAG_%S", title), null, 0);
ifauto(__str, discrim, p->discrim) {
flags |= strtoi_str(Language("LITH_TXT_MAIL_FLAG_%S%S", title, discrim), null, 0);
if(!(flags & MAILF_AllPlayers))
title = StrParam("%S%S", title, discrim);
}
bip_t *bip = &p->bip;
bippage_t *page = Salloc(bippage_t);
__str date = LanguageNull("LITH_TXT_MAIL_TIME_%S", title);
__str size = LanguageNull("LITH_TXT_MAIL_SIZE_%S", title);
__str send = LanguageNull("LITH_TXT_MAIL_SEND_%S", title);
__str name = LanguageNull("LITH_TXT_MAIL_NAME_%S", title);
__str body = Language ("LITH_TXT_MAIL_BODY_%S", title);
if(!send) send = "<internal>";
page->name = date ? date : world.canontimeshort;
page->title = name ? name : "<title omitted>";
page->body = StrParam(Language("LITH_TXT_MAIL_TEMPLATE"), send, page->name, body);
page->category = BIPC_MAIL;
page->unlocked = true;
if(size) page->height = strtoi_str(size, null, 0);
page->link.construct(page);
page->link.link(&bip->infogr[BIPC_MAIL]);
bip->mailreceived++;
if(!(flags & MAILF_NoPrint))
{
ACS_Delay(20);
p->log("> Mail received from <\Cj%S\C->.", send);
if(ACS_Random(1, 10000) == 1)
{
bip->mailtrulyreceived++;
ACS_LocalAmbientSound("player/YOUVEGOTMAIL", 127);
}
else
ACS_LocalAmbientSound("player/cbi/mail", 127);
}
}
//
// Lith_FindBIPPage
//
bippage_t *Lith_FindBIPPage(bip_t *bip, __str name)
{
if(!name)
return null;
ForCategoryAndPage()
if(page->name == name)
return page;
return null;
}
//
// Lith_UnlockBIPPage
//
bippage_t *Lith_UnlockBIPPage(bip_t *bip, __str name, int pclass)
{
bippage_t *page = bip->find(name);
if(!page && pclass)
ifauto(__str, discrim, Lith_PlayerDiscriminator(pclass))
{
page = bip->find(StrParam("%S%S", name, discrim));
}
if(page && !page->unlocked)
UnlockPage(bip, page, pclass);
return page;
}
//
// Lith_DeallocateBIP
//
script void Lith_DeallocateBIP(bip_t *bip)
{
ForCategory()
bip->infogr[categ].free(true);
bip->init = false;
}
//
// CheckMatch
//
script static bool CheckMatch(struct page_info *pinf, __str query)
{
return strcasestr_str(pinf->shname, query) ||
strcasestr_str(pinf->flname, query) ||
strcasestr_str(pinf->body, query);
}
//
// Lith_CBITab_BIP
//
void Lith_CBITab_BIP(gui_state_t *g, struct player *p)
{
bip_t *bip = &p->bip;
int avail, max;
if(bip->curcategory == BIPC_MAIN)
{
int n = 0;
HudMessageF("CBIFONT", "INFO CATEGORIES");
HudMessageParams(0, g->hid--, CR_PURPLE, 40.1, 70.1, TS);
bip->lastcategory = BIPC_MAIN;
static __str const lines[] = {
"Weapons and weapon upgrades.",
"Enemies and bosses.",
"Armors and other loot.",
"Your attributes, abilities and history.",
"Body upgrades.",
"Places of interest around the galaxy.",
"Important companies, historic and current.",
"Received mail."
};
for(int i = 0; i < countof(lines); i++)
{
HudMessageF("CBIFONT", "%S", lines[i]);
HudMessageParams(0, g->hid--, CR_WHITE, 105.1, 85.1 + n + i * 10, TS);
}
#define LITH_X(name, capt) \
if(Lith_GUI_Button_Id(g, BIPC_##name, capt, 45, 85 + n, Pre(btnbipmain))) \
{ \
bip->curcategory = BIPC_##name; \
bip->curpage = null; \
} \
n += 10;
#include "lith_bip.h"
avail = bip->pageavail;
max = bip->pagemax;
}
else
{
list_t *list = &bip->infogr[bip->curcategory];
size_t n = list->size;
size_t i = 0;
Lith_GUI_ScrollBegin(g, &CBIState(g)->bipscr, 15, 50, guipre.btnlist.w, 170, guipre.btnlist.h * n);
forlistIt(bippage_t *page, *list, i++)
{
int y = guipre.btnlist.h * i;
if(Lith_GUI_ScrollOcclude(g, &CBIState(g)->bipscr, y, guipre.btnlist.h))
continue;
struct page_info pinf = GetPageInfo(page);
__str name = StrParam("%S%S", bip->curpage == page ? "\Ci" : "", pinf.shname);
if(Lith_GUI_Button_Id(g, i, name, 0, y, !page->unlocked || bip->curpage == page, Pre(btnlist)))
SetCurPage(g, bip, page, pinf.body);
}
Lith_GUI_ScrollEnd(g, &CBIState(g)->bipscr);
if(bip->curpage)
{
bippage_t *page = bip->curpage;
struct page_info pinf = GetPageInfo(page);
gui_typeon_state_t const *typeon = Lith_GUI_TypeOnUpdate(g, &CBIState(g)->biptypeon);
int oy = 0;
if(page->height)
{
Lith_GUI_ScrollBegin(g, &CBIState(g)->bipinfoscr, 100, 40, 200, 180, page->height, 184);
oy = g->oy - 40;
}
else
ACS_SetHudClipRect(111, 40, 200, 180, 184);
if(page->image)
DrawSpriteAlpha(page->image, g->hid--, 296.2, 180.2, TS, 0.4);
DrawSpriteAlpha(":UI:Background", g->hid--, 0.1, 0.1, TS, 0.5);
HudMessageF("CBIFONT", "\Ci%S", pinf.flname);
HudMessagePlain(g->hid--, 200.4, 45.1 + oy, TS);
#define DrawText(txt, pos, ...) \
HudMessageF("CBIFONT", "%.*S%S", pos, txt, pos == typeon->len ? Ticker("\n|", "") : "|"), \
HudMessageParams(0, g->hid--, __VA_ARGS__ + oy, TS)
// render an outline if the page has an image
if(page->image)
{
__str s = Lith_RemoveTextColors(typeon->txt, typeon->pos);
int len = ACS_StrLen(s);
DrawText(s, len, CR_BLACK, 112.1, 61.1); DrawText(s, len, CR_BLACK, 110.1, 61.1);
DrawText(s, len, CR_BLACK, 112.1, 59.1); DrawText(s, len, CR_BLACK, 110.1, 59.1);
DrawText(s, len, CR_BLACK, 111.1, 59.1);
DrawText(s, len, CR_BLACK, 111.1, 61.1);
DrawText(s, len, CR_BLACK, 112.1, 60.1);
DrawText(s, len, CR_BLACK, 110.1, 60.1);
}
DrawText(typeon->txt, typeon->pos, CR_WHITE, 111.1, 60.1);
if(page->height) Lith_GUI_ScrollEnd(g, &CBIState(g)->bipinfoscr);
else ACS_SetHudClipRect(0, 0, 0, 0);
}
avail = bip->categoryavail[bip->curcategory];
max = bip->categorymax[bip->curcategory];
}
if(bip->curcategory != BIPC_MAIN)
{
if(Lith_GUI_Button(g, "<BACK", 20, 38, false, Pre(btnbipback)))
bip->curcategory = bip->lastcategory;
}
else
{
DrawSpriteAlpha(":UI:bip", g->hid--, 20.1, 30.1, TS, 0.6);
HudMessageF("CBIFONT", "BIOTIC INFORMATION PANEL ver2.5");
HudMessagePlain(g->hid--, 35.1, 30.1, TS);
}
if(max)
{
HudMessageF("CBIFONT", "%i/%i AVAILABLE", avail, max);
HudMessagePlain(g->hid--, 300.2, 30.1, TS);
}
}
// EOF