476 lines
12 KiB
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
|
|
|