TWP: Fix several bugs

- actorDistanceWithin if actors is not in the same room
- add STOP_LOOPING const
- call actorEnter and actorExit
- fix loadDialog
- add name to cutscene
- annoying kid should not stop music when talking with him
This commit is contained in:
scemino 2024-02-13 20:25:39 +01:00 committed by Eugene Sandulenko
parent 2efa0d60b5
commit bce1313ad6
13 changed files with 149 additions and 44 deletions

View File

@ -207,31 +207,36 @@ static SQInteger actorDistanceTo(HSQUIRRELVM v) {
static SQInteger actorDistanceWithin(HSQUIRRELVM v) {
SQInteger nArgs = sq_gettop(v);
if (nArgs == 3) {
Common::SharedPtr<Object> actor1 = g_engine->_actor;
Common::SharedPtr<Object> actor2 = sqactor(v, 2);
Common::SharedPtr<Object> actor1(g_engine->_actor);
Common::SharedPtr<Object> actor2(sqactor(v, 2));
if (!actor2)
return sq_throwerror(v, "failed to get actor");
Common::SharedPtr<Object> obj = sqobj(v, 3);
if (!obj)
return sq_throwerror(v, "failed to get spot");
if(actor1->_room != actor2->_room)
return false;
// not sure about this, needs to be check one day ;)
sqpush(v, distance((Vector2i)actor1->_node->getAbsPos(), (Vector2i)obj->getUsePos()) < distance((Vector2i)actor2->_node->getAbsPos(), (Vector2i)obj->getUsePos()));
return 1;
} else if (nArgs == 4) {
Common::SharedPtr<Object> actor = sqactor(v, 2);
}
if (nArgs == 4) {
Common::SharedPtr<Object> actor(sqactor(v, 2));
if (!actor)
return sq_throwerror(v, "failed to get actor");
Common::SharedPtr<Object> obj = sqobj(v, 3);
Common::SharedPtr<Object> obj(sqobj(v, 3));
if (!obj)
return sq_throwerror(v, "failed to get object");
int dist;
if (SQ_FAILED(sqget(v, 4, dist)))
return sq_throwerror(v, "failed to get distance");
if(actor->_room != obj->_room)
return false;
sqpush(v, distance((Vector2i)actor->_node->getAbsPos(), (Vector2i)obj->getUsePos()) < dist);
return 1;
} else {
return sq_throwerror(v, "actorDistanceWithin not implemented");
}
return sq_throwerror(v, "actorDistanceWithin not implemented");
}
// Makes the actor face a given direction.
@ -439,7 +444,10 @@ static SQInteger actorLockFacing(HSQUIRRELVM v) {
int facing = 0;
if (SQ_FAILED(sqget(v, 3, facing)))
return sq_throwerror(v, "failed to get facing");
actor->lockFacing(facing);
if (facing == 0)
actor->resetLockFacing();
else
actor->lockFacing(facing);
} break;
case OT_TABLE: {
HSQOBJECT obj;

View File

@ -111,10 +111,11 @@ void Camera::update(Common::SharedPtr<Room> room, Common::SharedPtr<Object> foll
InterpolationMethod intToInterpolationMethod(int value) {
bool loop = (value & 0x10);
bool swing = (value & 0x20);
bool stopLooping = (value & 0x40);
InterpolationKind kind = (InterpolationKind)(value & 0x0F);
InterpolationMethod im;
im.kind = kind;
im.loop = loop;
im.loop = loop && !stopLooping;
im.swing = swing;
return im;
}

View File

@ -24,6 +24,7 @@
#include "twp/twp.h"
#include "twp/thread.h"
#include "twp/lighting.h"
#include "twp/squtil.h"
#include "common/debug-channels.h"
namespace Twp {
@ -35,12 +36,15 @@ static struct {
bool _showAudio = false;
bool _showResources = false;
bool _showScenegraph = false;
bool _showActor = false;
Node* _node = nullptr;
ImGuiTextFilter _objFilter;
ImGuiTextFilter _actorFilter;
int _fadeEffect = 0;
float _fadeDuration = 0.f;
bool _fadeToSepia = false;
Common::String _textureSelected;
int _selectedActor = 0;
} state;
ImVec4 gray(0.6f, 0.6f, 0.6f, 1.f);
@ -64,6 +68,26 @@ static void drawThreads() {
ImGui::TableSetupColumn("Line");
ImGui::TableHeadersRow();
if(g_engine->_cutscene) {
Common::SharedPtr<ThreadBase> thread(g_engine->_cutscene);
SQStackInfos infos;
sq_stackinfos(thread->getThread(), 0, &infos);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%5d", thread->getId());
ImGui::TableNextColumn();
ImGui::Text("%-56s", thread->getName().c_str());
ImGui::TableNextColumn();
ImGui::Text("%-6s", "cutscene");
ImGui::TableNextColumn();
ImGui::Text("%-9s", infos.funcname);
ImGui::TableNextColumn();
ImGui::Text("%-9s", infos.source);
ImGui::TableNextColumn();
ImGui::Text("%5lld", infos.line);
}
for (const auto &thread : threads) {
SQStackInfos infos;
sq_stackinfos(thread->getThread(), 0, &infos);
@ -147,6 +171,52 @@ static ImVec4 getCategoryColor(Audio::Mixer::SoundType type) {
return ImVec4(1.f, 1.f, 1.f, 1.f);
}
static void drawActors() {
if (!state._showActor)
return;
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
ImGui::Begin("Actors", &state._showStack);
state._actorFilter.Draw();
ImGui::BeginChild("Actor_List");
for(auto& actor : g_engine->_actors) {
bool selected = actor->getId() == state._selectedActor;
Common::String key(actor->_key);
if (state._actorFilter.PassFilter(actor->_key.c_str())) {
if (key.empty()) {
key = "??";
}
if (ImGui::Selectable(key.c_str(), &selected)) {
state._selectedActor = actor->getId();
}
}
}
ImGui::EndChild();
ImGui::End();
}
static void drawActor() {
if (!state._showActor)
return;
Common::SharedPtr<Object> actor(sqobj(state._selectedActor));
if (!actor)
return;
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
ImGui::Begin("Actor", &state._showStack);
ImGui::Text("Name: %s", actor->_key.c_str());
ImGui::Text("Costume: %s (%s)", actor->_costumeName.c_str(), actor->_costumeSheet.c_str());
ImGui::Text("Animation: %s", actor->_animName.c_str());
Common::String hiddenLayers(Twp::join(actor->_hiddenLayers, ", "));
ImGui::Text("Hidden Layers: %s", hiddenLayers.c_str());
ImGui::Text("Facing: %d", actor->_facing);
ImGui::Text("Facing Lock: %d", actor->_facingLockValue);
ImGui::ColorEdit3("Talk color", actor->_talkColor.v);
ImGui::DragFloat2("Talk offset", actor->_talkOffset.getData());
ImGui::End();
}
static void drawStack() {
if (!state._showStack)
return;
@ -275,9 +345,9 @@ static void drawGeneral() {
ImGui::TextColored(gray, "Stack:");
ImGui::SameLine();
ImGui::Text("%lld", size);
ImGui::TextColored(gray, "In cutscene:");
ImGui::TextColored(gray, "Cutscene:");
ImGui::SameLine();
ImGui::Text("%s", g_engine->_cutscene ? "yes" : "no");
ImGui::Text("%s", g_engine->_cutscene ? g_engine->_cutscene->getName().c_str() : "no");
DialogState dialogState = g_engine->_dialog.getState();
ImGui::TextColored(gray, "In dialog:");
ImGui::SameLine();
@ -415,10 +485,11 @@ static void drawGeneral() {
if (ImGui::CollapsingHeader("Windows")) {
ImGui::Checkbox("Threads", &state._showThreads);
ImGui::Checkbox("Objects", &state._showObjects);
ImGui::Checkbox("Actor", &state._showActor);
ImGui::Checkbox("Stack", &state._showStack);
ImGui::Checkbox("Audio", &state._showAudio);
ImGui::Checkbox("Resources", &state._showResources);
ImGui::Checkbox("Scenegraph", &state._showScenegraph);
ImGui::Checkbox("Scene graph", &state._showScenegraph);
}
ImGui::Separator();
@ -523,6 +594,8 @@ void onImGuiRender() {
drawAudio();
drawResources();
drawScenegraph();
drawActors();
drawActor();
}
} // namespace Twp

View File

@ -140,9 +140,7 @@ public:
void setUniform2(const char * name, float* value, size_t count);
void setUniform3(const char * name, float* value, size_t count);
void setUniform(const char *name, Math::Matrix4 value);
void setUniform(const char * name, Math::Vector2d value);
void setUniform(const char * name, Math::Vector3d value);
void setUniform3(const char * name, Color value);
void setUniform4(const char * name, Color value);

View File

@ -74,6 +74,7 @@
#define SLOW_EASE_OUT 5
#define LOOPING 0x10
#define SWING 0X20
#define STOP_LOOPING 0X40
#define ALIGN_LEFT 0x0000000010000000
#define ALIGN_CENTER 0x0000000020000000
#define ALIGN_RIGHT 0x0000000040000000

View File

@ -372,8 +372,9 @@ int Object::getFlags() {
}
void Object::setRoom(Common::SharedPtr<Object> object, Common::SharedPtr<Room> room) {
if ((object->_room != room) || !object->_node->getParent()) {
if (object->_room != room) {
bool roomChanged = object->_room != room;
if (roomChanged || !object->_node->getParent()) {
if (roomChanged) {
object->stopObjectMotors();
}
Common::SharedPtr<Room> oldRoom = object->_room;
@ -399,6 +400,14 @@ void Object::setRoom(Common::SharedPtr<Object> object, Common::SharedPtr<Room> r
}
}
object->_room = room;
if(roomChanged && isActor(object->getId())) {
if(room == g_engine->_room) {
g_engine->actorEnter(object);
} else if(oldRoom == g_engine->_room) {
g_engine->actorExit(object);
}
}
}
}
@ -418,6 +427,12 @@ void Object::stopObjectMotors() {
disableMotor(_shakeTo);
disableMotor(_jiggleTo);
disableMotor(_scaleTo);
_node->setRotation(0);
_node->setRotationOffset(0);
_node->setOffset({0.f, 0.f});
_node->setShakeOffset({0.f, 0.f});
_node->setAlpha(1);
_node->setScale({1.f,1.f});
}
void Object::setFacing(Facing facing) {
@ -537,10 +552,8 @@ void Object::stand() {
void Object::setAlphaTo(Common::SharedPtr<Motor> alphaTo) { SET_MOTOR(alphaTo); }
void Object::setRotateTo(Common::SharedPtr<Motor> rotateTo) { SET_MOTOR(rotateTo); }
void Object::setMoveTo(Common::SharedPtr<Motor> moveTo) { SET_MOTOR(moveTo); }
void Object::setWalkTo(Common::SharedPtr<Motor> walkTo) { SET_MOTOR(walkTo); }
void Object::setReach(Common::SharedPtr<Motor> reach) { SET_MOTOR(reach); }
void Object::setTalking(Common::SharedPtr<Motor> talking) { SET_MOTOR(talking); }
void Object::setTurnTo(Common::SharedPtr<Motor> turnTo) { SET_MOTOR(turnTo); }
void Object::setShakeTo(Common::SharedPtr<Motor> shakeTo) { SET_MOTOR(shakeTo); }
void Object::setScaleTo(Common::SharedPtr<Motor> scaleTo) { SET_MOTOR(scaleTo); }
@ -629,6 +642,7 @@ void Object::say(Common::SharedPtr<Object> obj, const Common::StringArray &texts
void Object::resetLockFacing() {
_facingMap.clear();
_facingLockValue = 0;
}
void Object::lockFacing(int facing) {

View File

@ -170,7 +170,6 @@ public:
bool contains(Math::Vector2d pos);
static void setRoom(Common::SharedPtr<Object> object, Common::SharedPtr<Room> room);
void delObject();
void stopObjectMotors();
void dependentOn(Common::SharedPtr<Object> dependentObj, int state);
@ -190,7 +189,6 @@ public:
void setAlphaTo(Common::SharedPtr<Motor> alphaTo);
void setRotateTo(Common::SharedPtr<Motor> rotateTo);
void setMoveTo(Common::SharedPtr<Motor> moveTo);
void setWalkTo(Common::SharedPtr<Motor> walkTo);
void setReach(Common::SharedPtr<Motor> reach);
Common::SharedPtr<Motor> getWalkTo() { return _walkTo; }
Common::SharedPtr<Motor> getReach() { return _reach; }
@ -198,8 +196,6 @@ public:
static void walk(Common::SharedPtr<Object> actor, Common::SharedPtr<Object> obj);
void setTalking(Common::SharedPtr<Motor> talking);
void setBlink(Common::SharedPtr<Motor> blink);
void setTurnTo(Common::SharedPtr<Motor> turnTo);
void setShakeTo(Common::SharedPtr<Motor> shakeTo);
void setScaleTo(Common::SharedPtr<Motor> scaleTo);

View File

@ -397,7 +397,7 @@ bool SaveGameManager::loadGame(const SaveGame &savegame) {
sqcall("preLoad");
loadGameScene(json["gameScene"]->asObject());
loadDialog(json["gameScene"]->asObject());
loadDialog(json["dialog"]->asObject());
loadCallbacks(json["callbacks"]->asObject());
loadGlobals(json["globals"]->asObject());
loadActors(json["actors"]->asObject());

View File

@ -483,7 +483,8 @@ static SQInteger cutscene(HSQUIRRELVM v) {
}
Common::SharedPtr<ThreadBase> parentThread = sqthread(v);
Common::SharedPtr<Cutscene> cutscene(new Cutscene(parentThread->getId(), threadObj, closure, closureOverride, envObj));
Common::String cutsceneName = Common::String::format("%s (%lld)", _stringval(_closure(closure)->_function->_sourcename), _closure(closure)->_function->_lineinfos->_line);
Common::SharedPtr<Cutscene> cutscene(new Cutscene(cutsceneName, parentThread->getId(), threadObj, closure, closureOverride, envObj));
g_engine->_cutscene = cutscene;
// call the closure in the thread
@ -892,6 +893,7 @@ void sqgame_register_constants(HSQUIRRELVM v) {
regConst(v, "SLOW_EASE_OUT", SLOW_EASE_OUT);
regConst(v, "LOOPING", LOOPING);
regConst(v, "SWING", SWING);
regConst(v, "STOP_LOOPING", STOP_LOOPING);
regConst(v, "ALIGN_LEFT", ALIGN_LEFT);
regConst(v, "ALIGN_CENTER", ALIGN_CENTER);
regConst(v, "ALIGN_RIGHT", ALIGN_RIGHT);

View File

@ -115,14 +115,14 @@ void Thread::stop() {
suspend();
}
Cutscene::Cutscene(int parentThreadId, HSQOBJECT threadObj, HSQOBJECT closure, HSQOBJECT closureOverride, HSQOBJECT envObj)
Cutscene::Cutscene(const Common::String& name, int parentThreadId, HSQOBJECT threadObj, HSQOBJECT closure, HSQOBJECT closureOverride, HSQOBJECT envObj)
: _parentThreadId(parentThreadId),
_threadObj(threadObj),
_closure(closure),
_closureOverride(closureOverride),
_envObj(envObj) {
_name = "cutscene";
_name = name;
_id = newThreadId();
_inputState = g_engine->_inputState.getState();
_actor = g_engine->_followActor;

View File

@ -105,7 +105,7 @@ enum CutsceneState {
class Object;
class Cutscene final : public ThreadBase {
public:
Cutscene(int parentThreadId, HSQOBJECT threadObj, HSQOBJECT closure, HSQOBJECT closureOverride, HSQOBJECT envObj);
Cutscene(const Common::String& name, int parentThreadId, HSQOBJECT threadObj, HSQOBJECT closure, HSQOBJECT closureOverride, HSQOBJECT envObj);
~Cutscene() override final;
void start();

View File

@ -509,9 +509,10 @@ void TwpEngine::update(float elapsed) {
Common::Array<Common::SharedPtr<ThreadBase> > threads(_threads);
Common::Array<Common::SharedPtr<ThreadBase> > threadsToRemove;
bool isNotInDialog = _dialog.getState() == DialogState::None;
for (auto it = threads.begin(); it != threads.end(); it++) {
Common::SharedPtr<ThreadBase> thread(*it);
if (thread->update(elapsed)) {
if ((isNotInDialog || !thread->isGlobal()) && thread->update(elapsed)) {
threadsToRemove.push_back(thread);
}
}
@ -1212,8 +1213,9 @@ void TwpEngine::enterRoom(Common::SharedPtr<Room> room, Common::SharedPtr<Object
_camera.setRoom(room);
_camera.setAt(camPos);
stopTalking();
// call actor enter function and objects enter function
actorEnter();
for (size_t i = 0; i < room->_layers.size(); i++) {
Common::SharedPtr<Layer> layer = room->_layers[i];
for (size_t j = 0; j < layer->_objects.size(); j++) {
@ -1225,7 +1227,9 @@ void TwpEngine::enterRoom(Common::SharedPtr<Room> room, Common::SharedPtr<Object
_room->_scalingTriggers.push_back(ScalingTrigger(obj, scaling));
}
}
if (sqrawexists(obj->_table, "enter"))
if(isActor(obj->getId())) {
actorEnter(_actor);
} else if (sqrawexists(obj->_table, "enter"))
sqcall(obj->_table, "enter");
}
}
@ -1248,14 +1252,12 @@ void TwpEngine::enterRoom(Common::SharedPtr<Room> room, Common::SharedPtr<Object
sqcall("enteredRoom", room->_table);
}
void TwpEngine::actorEnter() {
if (_actor) {
sqcall(_actor->_table, "actorEnter");
if (_room) {
if (sqrawexists(_room->_table, "actorEnter")) {
sqcall(_room->_table, "actorEnter", _actor->_table);
}
}
void TwpEngine::actorEnter(Common::SharedPtr<Object> actor) {
if(!actor) return;
if(sqrawexists(g_engine->_room->_table, "actorEnter")) {
sqcall(g_engine->_room->_table, "actorEnter", actor->_table);
} else {
sqcall("actorEnter", actor->_table);
}
}
@ -1266,7 +1268,16 @@ void TwpEngine::exitRoom(Common::SharedPtr<Room> nextRoom) {
_room->_triggers.clear();
_room->_scalingTriggers.clear();
actorExit();
for (size_t i = 0; i < _room->_layers.size(); i++) {
Common::SharedPtr<Layer> layer(_room->_layers[i]);
for (size_t j = 0; j < layer->_objects.size(); j++) {
Common::SharedPtr<Object> obj = layer->_objects[j];
obj->stopObjectMotors();
if(isActor(obj->getId())) {
actorExit(obj);
}
}
}
// call room exit function with the next room as a parameter if requested
int nparams = sqparamCount(v, _room->_table, "exit");
@ -1312,8 +1323,8 @@ void TwpEngine::setRoom(Common::SharedPtr<Room> room) {
enterRoom(room);
}
void TwpEngine::actorExit() {
if (_actor && _room) {
void TwpEngine::actorExit(Common::SharedPtr<Object> actor) {
if (actor && _room) {
if (sqrawexists(_room->_table, "actorExit")) {
sqcall(_room->_table, "actorExit", _actor->_table);
}
@ -1625,7 +1636,8 @@ void TwpEngine::updateTriggers() {
}
void TwpEngine::stopTalking() {
for (auto it = g_engine->_room->_layers.begin(); it != g_engine->_room->_layers.end(); it++) {
if(!_room) return;
for (auto it = _room->_layers.begin(); it != _room->_layers.end(); it++) {
Common::SharedPtr<Layer> layer = *it;
for (auto it2 = layer->_objects.begin(); it2 != layer->_objects.end(); it2++) {
(*it2)->stopTalking();

View File

@ -129,6 +129,8 @@ public:
void stopTalking();
void walkFast(bool state = true);
void actorEnter(Common::SharedPtr<Object> actor);
void actorExit(Common::SharedPtr<Object> actor);
Common::SharedPtr<Room> defineRoom(const Common::String &name, HSQOBJECT table, bool pseudo = false);
void setRoom(Common::SharedPtr<Room> room);
void enterRoom(Common::SharedPtr<Room> room, Common::SharedPtr<Object> door = nullptr);
@ -151,8 +153,6 @@ private:
void update(float elapsedMs);
void draw(RenderTexture *texture = nullptr);
void exitRoom(Common::SharedPtr<Room> nextRoom);
void actorEnter();
void actorExit();
void cancelSentence(Common::SharedPtr<Object> actor = nullptr);
void clickedAt(Math::Vector2d scrPos);
bool clickedAtHandled(Math::Vector2d roomPos);