5#include <Tempest/MemReader>
6#include <Tempest/MemWriter>
18using namespace Tempest;
21const uint64_t GameSession::multTime=14500;
22const uint64_t GameSession::divTime =1000;
24void GameSession::HeroStorage::save(
Npc& npc) {
26 Tempest::MemWriter wr{storage};
30 npc.
save(sr,0,
"/npc/");
33void GameSession::HeroStorage::putToWorld(
World& owner, std::string_view wayPoint)
const {
36 Tempest::MemReader rd{storage};
40 if(
auto pl = owner.
player()) {
41 pl->load(sr,0,
"/npc/");
47 pl->attachToPoint(pos);
49 auto ptr = std::make_unique<Npc>(owner,-1,wayPoint);
50 ptr->load(sr,0,
"/npc/");
54 if(
auto pl = owner.
player()) {
55 if(
auto pos = pl->currentWayPoint()) {
56 pl->setPosition (pos->position() );
57 pl->setDirection(pos->direction());
61 pl->setAnim(Npc::Anim::Idle);
64 pl->updateTransform();
79 setWorld(std::unique_ptr<World>(
new World(*
this,std::move(file),
true,[&](
int v){
86 const bool testMode=
false;
105 wrld->createPlayer(hero);
110 wrld->triggerOnStart(
true);
111 cam->reset(wrld->player());
129 visitedWorlds.resize(wssSize);
130 for(
size_t i=0; i<wssSize; ++i)
131 fin.
read(visitedWorlds[i].name);
132 for(
size_t i=0; i<wssSize; ++i)
133 visitedWorlds[i].load(fin);
138 fin.
read(ticks,wrldTime,wrldTimePart,wname);
145 setWorld(std::unique_ptr<World>(
new World(*
this,wname,
false,[&](
int v){
154 vm->loadPerc(fin);
else
163 if(
auto hero = wrld->player())
164 vm->setInstanceNPC(
"HERO",*hero);
167 cam->load(fin,wrld->player());
178 hdr.
world = wrld->name();
180 time_t now = std::time(
nullptr);
181 tm* tp = std::localtime(&now);
191 uint16_t wssSize = uint16_t(visitedWorlds.size());
193 for(
auto& i:visitedWorlds)
201 fout.
write(ticks,wrldTime,wrldTimePart,wrld->name());
207 for(
auto& i:visitedWorlds) {
220 vm->saveQuests(fout);
228 constexpr const float soundScale = 2.f;
231 sound.setGlobalVolume(soundVolume*soundScale);
236 if(!isWorldKnown(wrld->name()))
237 visitedWorlds.emplace_back(*wrld);
244 if(!isWorldKnown(wrld->name())) {
245 visitedWorlds.emplace_back(*wrld);
248 return std::move(wrld);
253 chWorld.wp = wayPoint;
272 return sound.load(raw);
274 catch(std::bad_alloc&) {
275 Tempest::Log::d(
"Exceeding OpenAL source limit");
276 return Tempest::SoundEffect();
282 return fx.
load(sound,looped);
284 catch(std::bad_alloc&) {
285 Tempest::Log::d(
"Exceeding OpenAL source limit");
286 return Tempest::SoundEffect();
292 return wrld->player();
297 sound.setListenerPosition (lpos.
pos);
298 sound.setListenerDirection(lpos.
front, lpos.
up);
309 dt = dt*timeMul + timeMulFract;
310 timeMulFract = dt%1000;
315 uint64_t add = dt*multTime + wrldTimePart;
316 wrldTimePart = add%divTime;
324 exitSessionFlg =
false;
330 if(!chWorld.zen.empty()) {
331 for(
auto& c:chWorld.zen)
332 c =
char(std::tolower(c));
333 size_t beg = chWorld.zen.rfind(
'\\');
334 size_t end = chWorld.zen.rfind(
'.');
337 if(beg!=std::string::npos && end!=std::string::npos)
338 wname = chWorld.zen.substr(beg+1,end-beg-1);
339 else if(end!=std::string::npos)
340 wname = chWorld.zen.substr(0,end);
else
343 const char *w = (beg!=std::string::npos) ? (chWorld.zen.c_str()+beg+1) : chWorld.zen.c_str();
349 auto ret = implChangeWorld(std::move(game),chWorld.zen,chWorld.wp);
358 timeMul = uint64_t(t*1000);
361auto GameSession::implChangeWorld(std::unique_ptr<GameSession>&& game,
362 std::string_view world, std::string_view wayPoint) -> std::unique_ptr<GameSession> {
363 size_t cut = world.rfind(
'\\');
364 std::string_view w = world;
365 if(cut!=std::string::npos)
366 w = world.substr(cut+1);
369 Log::i(
"World not found[",world,
"]");
370 return std::move(game);
374 if(
auto hero = wrld->player())
378 vm->resetVarPointers();
385 auto loadProgress = [](
int v) {
390 std::unique_ptr<World> ret = std::unique_ptr<World>(
new World(*
this,w,wss.
isEmpty(),loadProgress));
391 setWorld(std::move(ret));
401 hdata.putToWorld(*game->wrld,wayPoint);
403 if(
auto hero = wrld->player())
404 vm->setInstanceNPC(
"HERO",*hero);
407 wrld->triggerOnStart(wss.
isEmpty());
409 for(
auto& i:visitedWorlds)
410 if(i.compareName(wrld->name())){
411 i = std::move(visitedWorlds.back());
412 visitedWorlds.pop_back();
416 cam->reset(wrld->player());
417 Log::i(
"Done loading world[",world,
"]");
418 return std::move(game);
422 for(
auto& i:visitedWorlds)
423 if(i.compareName(name))
431 wrld->updateAnimation(dt);
435 return vm->updateDialog(dlg,
player,npc);
439 return vm->exec(dlg,
player,npc);
445 return vm->messageFromSvm(
id,voice);
451 return vm->messageByName(
id);
457 return vm->messageTime(
id);
474bool GameSession::isWorldKnown(std::string_view name)
const {
475 for(
auto& i:visitedWorlds)
481void GameSession::initPerceptions() {
483 if(vm->hasSymbolName(
"initPerceptions"))
484 vm->getVm().call_function(
"initPerceptions");
487void GameSession::initScripts(
bool firstTime) {
488 auto wname = wrld->name();
489 auto dot = wname.rfind(
'.');
490 auto name = (dot==std::string::npos ? wname : wname.substr(0,dot));
493 if(vm->hasSymbolName(
"startup_global"))
494 vm->getVm().call_function(
"startup_global");
497 if(vm->hasSymbolName(startup))
498 vm->getVm().call_function(startup);
501 if(vm->hasSymbolName(
"init_global"))
502 vm->getVm().call_function(
"init_global");
505 if(vm->hasSymbolName(init))
506 vm->getVm().call_function(init);
508 wrld->resetPositionToTA();
std::string_view messageFromSvm(std::string_view id, int voice) const
auto updateDialog(const GameScript::DlgChoice &dlg, Npc &player, Npc &npc) -> std::vector< GameScript::DlgChoice >
auto clearWorld() -> std::unique_ptr< World >
void changeWorld(std::string_view world, std::string_view wayPoint)
void dialogExec(const GameScript::DlgChoice &dlg, Npc &player, Npc &npc)
void setTimeMultiplyer(float t)
void updateAnimation(uint64_t dt)
uint32_t messageTime(std::string_view id) const
bool isNpcInDialog(const Npc &npc) const
void updateListenerPos(const Camera::ListenerPos &lpos)
auto version() const -> const VersionInfo &
void save(Serialize &fout, std::string_view name, const Tempest::Pixmap &screen)
AiOuputPipe * openDlgOuput(Npc &player, Npc &npc)
void setWorld(std::unique_ptr< World > &&w)
const World * world() const
std::string_view messageByName(std::string_view id) const
auto loadSound(const Tempest::Sound &raw) -> Tempest::SoundEffect
std::string_view defaultPlayer() const
void openDialogPipe(Npc &player, Npc &npc, AiOuputPipe *&pipe)
auto version() const -> const VersionInfo &
auto clearGame() -> std::unique_ptr< GameSession >
void startLoad(std::string_view banner, const std::function< std::unique_ptr< GameSession >(std::unique_ptr< GameSession > &&)> f)
bool isNpcInDialog(const Npc &npc) const
static float settingsGetF(std::string_view sec, std::string_view name)
void setLoadingProgress(int v)
Tempest::Signal< void()> onSessionExit
void save(Serialize &fout, size_t id, std::string_view directory)
static bool hasFile(std::string_view fname)
void write(const Arg &... a)
bool setEntry(const Args &... args)
void setGlobalVersion(uint16_t v)
Tempest::SoundEffect load(Tempest::SoundDevice &dev, bool &loop) const
std::vector< uint8_t > storage
const WayPoint * findPoint(std::string_view name, bool inexact=true) const
void insertPlayer(std::unique_ptr< Npc > &&npc, std::string_view waypoint)
const WayPoint & startPoint() const
void addMilis(uint64_t t)