Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/WolfireGames/overgrowth.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Objects/hotspot.cpp')
-rw-r--r--Source/Objects/hotspot.cpp815
1 files changed, 815 insertions, 0 deletions
diff --git a/Source/Objects/hotspot.cpp b/Source/Objects/hotspot.cpp
new file mode 100644
index 00000000..630baa4d
--- /dev/null
+++ b/Source/Objects/hotspot.cpp
@@ -0,0 +1,815 @@
+//-----------------------------------------------------------------------------
+// Name: hotspot.cpp
+// Developer: Wolfire Games LLC
+// Author: Phillip Isola
+// Description:
+// License: Read below
+//-----------------------------------------------------------------------------
+//
+// Copyright 2022 Wolfire Games LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-----------------------------------------------------------------------------
+#include "hotspot.h"
+
+#include <Graphics/graphics.h>
+#include <Graphics/shaders.h>
+#include <Graphics/pxdebugdraw.h>
+
+#include <Internal/filesystem.h>
+#include <Internal/memwrite.h>
+#include <Internal/common.h>
+#include <Internal/profiler.h>
+
+#include <Scripting/angelscript/asfuncs.h>
+#include <Scripting/angelscript/add_on/scripthandle/scripthandle.h>
+#include <Scripting/angelscript/add_on/scriptarray/scriptarray.h>
+
+#include <Math/vec3math.h>
+#include <Math/vec4math.h>
+
+#include <Game/level.h>
+#include <Game/savefile_script.h>
+
+#include <Main/scenegraph.h>
+#include <Objects/hotspot.h>
+#include <Physics/bulletworld.h>
+#include <Game/EntityDescription.h>
+#include <Editors/map_editor.h>
+#include <Logging/logdata.h>
+#include <Asset/Asset/hotspotfile.h>
+
+#include <imgui.h>
+
+extern std::string script_dir_path;
+extern std::string preview_script_name;
+extern bool show_script;
+
+extern bool g_debug_runtime_disable_hotspot_draw;
+extern bool g_debug_runtime_disable_hotspot_pre_draw_frame;
+
+Hotspot::Hotspot():
+ as_context(NULL),
+ collision_object(NULL),
+ abstract_collision(true)
+{
+ collidable = false;
+ box_.dims = vec3(4.0f);
+}
+
+Hotspot::~Hotspot() {
+ if(as_context){
+ delete as_context;
+ as_context = NULL;
+ }
+ if(collision_object){
+ scenegraph_->abstract_bullet_world_->RemoveObject(&collision_object);
+ collision_object = NULL;
+ }
+}
+
+void Hotspot::UpdateCollisionShape() {
+ if(collision_object){
+ scenegraph_->abstract_bullet_world_->RemoveObject(&collision_object);
+ collision_object = NULL;
+ }
+ if(abstract_collision){
+ vec3 scale = GetScale();
+ scale[0] = fabs(scale[0]);
+ scale[1] = fabs(scale[1]);
+ scale[2] = fabs(scale[2]);
+ collision_object = scenegraph_->abstract_bullet_world_->CreateBox(
+ vec3(0.0f), scale * 4.0f, BW_STATIC);
+ //mat4 mat = m_transform.blGetMatrix();
+ //mat4 no_scale_mat = mat.GetRotationPart();
+ //no_scale_mat.SetTranslationPart(GetCenter());
+ //col_sphere->SetTransform(no_scale_mat);
+ collision_object->SetTransform(GetTranslation(), Mat4FromQuaternion(GetRotation()), vec3(1.0f));//GetScale());
+ collision_object->body->setInterpolationWorldTransform(collision_object->body->getWorldTransform());
+ collision_object->body->setCollisionFlags(collision_object->body->getCollisionFlags() |
+ btCollisionObject::CF_NO_CONTACT_RESPONSE);
+ collision_object->SetVisibility(true);
+ collision_object->FixDiscontinuity();
+ collision_object->Sleep();
+ scenegraph_->abstract_bullet_world_->dynamics_world_->updateSingleAabb(collision_object->body);
+ collision_object->owner_object = this;
+ }
+}
+
+void Hotspot::Dispose() {
+ as_context->CallScriptFunction(as_funcs.dispose);
+}
+
+void Hotspot::GetDisplayName(char* buf, int buf_size) {
+ if( GetName().empty() ) {
+ FormatString(buf, buf_size, "%d: Hotspot: %s", GetID(), obj_file.c_str());
+ } else {
+ FormatString(buf, buf_size, "%s: Hotspot: %s", GetName().c_str(), obj_file.c_str());
+ }
+}
+
+void Hotspot::DrawImGuiEditor() {
+ ImGui::Text("Script: %s", m_script_file.c_str());
+ ImGui::SameLine();
+ if (ImGui::Button("Preview script")) {
+ show_script = preview_script_name == m_script_file ? !show_script : true;
+ preview_script_name = m_script_file;
+ }
+}
+
+bool Hotspot::Initialize() {
+ UpdateCollisionShape();
+
+ std::string script_file_path = script_dir_path+m_script_file;
+ if(!m_script_file.empty() && FileExists(script_file_path.c_str(), kDataPaths|kModPaths)){
+ ASData as_data;
+ as_data.scenegraph = scenegraph_;
+ as_data.gui = scenegraph_->map_editor->gui;
+ as_context = new ASContext("hotspot", as_data);
+ AttachUIQueries(as_context);
+ AttachActiveCamera(as_context);
+ AttachScreenWidth(as_context);
+ AttachPhysics(as_context);
+ AttachEngine(as_context);
+ AttachScenegraph(as_context, scenegraph_);
+ AttachTextCanvasTextureToASContext(as_context);
+ AttachLevel(as_context);
+ AttachInterlevelData(as_context);
+ AttachPlaceholderObject(as_context);
+ AttachTokenIterator(as_context);
+ AttachStringConvert(as_context);
+ AttachMessages(as_context);
+ AttachSaveFile(as_context, &Engine::Instance()->save_file_);
+ AttachIMGUI(as_context);
+ AttachOnline(as_context);
+ hud_images.AttachToContext(as_context);
+
+ as_collisions.reset(new ASCollisions(scenegraph_));
+ as_collisions->AttachToContext(as_context);
+
+ ScriptParams::RegisterScriptType(as_context);
+ sp.RegisterScriptInstance(as_context);
+
+ as_context->RegisterGlobalProperty("Hotspot hotspot", this);
+
+ as_funcs.init = as_context->RegisterExpectedFunction("void Init()", false);
+ as_funcs.set_parameters = as_context->RegisterExpectedFunction("void SetParameters()", false);
+ as_funcs.receive_message = as_context->RegisterExpectedFunction("void ReceiveMessage(string)", false);
+ as_funcs.update = as_context->RegisterExpectedFunction("void Update()", false);
+ as_funcs.pre_draw = as_context->RegisterExpectedFunction("void PreDraw(float curr_game_time)", false);
+ as_funcs.draw = as_context->RegisterExpectedFunction("void Draw()", false);
+ as_funcs.draw_editor = as_context->RegisterExpectedFunction("void DrawEditor()", false);
+ as_funcs.reset = as_context->RegisterExpectedFunction("void Reset()", false);
+ as_funcs.set_enabled = as_context->RegisterExpectedFunction("void SetEnabled(bool val)", false);
+ as_funcs.handle_event = as_context->RegisterExpectedFunction("void HandleEvent(string event, MovementObject @mo)", false);
+ as_funcs.handle_event_item = as_context->RegisterExpectedFunction("void HandleEventItem(string event, ItemObject @obj)", false);
+ as_funcs.get_type_string = as_context->RegisterExpectedFunction("string GetTypeString()", false);
+ as_funcs.dispose = as_context->RegisterExpectedFunction("void Dispose()", false);
+ as_funcs.pre_script_reload = as_context->RegisterExpectedFunction("void PreScriptReload()", false);
+ as_funcs.post_script_reload = as_context->RegisterExpectedFunction("void PostScriptReload()", false);
+ as_funcs.connect_to = as_context->RegisterExpectedFunction("bool ConnectTo(Object @other)", false);
+ as_funcs.disconnect = as_context->RegisterExpectedFunction("bool Disconnect(Object @other)", false);
+ as_funcs.connected_from = as_context->RegisterExpectedFunction("void ConnectedFrom(Object @other)", false);
+ as_funcs.disconnected_from = as_context->RegisterExpectedFunction("void DisconnectedFrom(Object @other)", false);
+ as_funcs.accept_connections_from = as_context->RegisterExpectedFunction("bool AcceptConnectionsFrom(ConnectionType type)", false);
+ as_funcs.accept_connections_from_obj = as_context->RegisterExpectedFunction("bool AcceptConnectionsFrom(Object @other)", false);
+ as_funcs.accept_connections_to_obj = as_context->RegisterExpectedFunction("bool AcceptConnectionsTo(Object @other)", false);
+ as_funcs.launch_custom_gui = as_context->RegisterExpectedFunction("void LaunchCustomGUI()", false);
+ as_funcs.object_inspector_read_only = as_context->RegisterExpectedFunction("bool ObjectInspectorReadOnly()", false);
+
+ PROFILER_ENTER(g_profiler_ctx, "Exporting docs");
+ char path[kPathSize];
+ FormatString(path, kPathSize, "%sashotspot_docs.h", GetWritePath(CoreGameModID).c_str());
+ as_context->ExportDocs(path);
+ PROFILER_LEAVE(g_profiler_ctx);
+
+ Path script_path = FindFilePath(script_file_path, kDataPaths | kModPaths);
+ as_context->LoadScript(script_path);
+ as_context->CallScriptFunction(as_funcs.init);
+ as_context->CallScriptFunction(as_funcs.set_parameters);
+ return true;
+ } else {
+ LOGE << "Hotspot script \"" << script_file_path << "\" not found" << std::endl;
+ return false;
+ }
+}
+
+void Hotspot::ReceiveObjectMessageVAList( OBJECT_MSG::Type type, va_list args ) {
+ switch(type){
+ case OBJECT_MSG::SCRIPT: {
+ const std::string &str = *va_arg(args, std::string*);
+ ASArglist args;
+ args.AddObject((void*)&str);
+ as_context->CallScriptFunction(as_funcs.receive_message, &args);
+ break;}
+ case OBJECT_MSG::QUEUE_SCRIPT: {
+ const std::string &str = *va_arg(args, std::string*);
+ message_queue.push(str);
+ break;}
+ case OBJECT_MSG::RESET:{
+ Reset();
+ std::string str = "reset";
+ ReceiveObjectMessage(OBJECT_MSG::SCRIPT, &str);
+ break;}
+ default:
+ Object::ReceiveObjectMessageVAList(type, args);
+ break;
+ }
+}
+
+void Hotspot::Update(float timestep) {
+ if(as_context){
+ while(message_queue.empty() == false) {
+ ASArglist args;
+ const std::string str = message_queue.front();
+ args.AddObject((void*)&str);
+ as_context->CallScriptFunction(as_funcs.receive_message, &args);
+ message_queue.pop();
+ }
+ as_context->CallScriptFunction(as_funcs.update);
+ }
+}
+
+void Hotspot::PreDrawFrame(float curr_game_time) {
+ if (g_debug_runtime_disable_hotspot_pre_draw_frame) {
+ return;
+ }
+
+ PROFILER_ZONE(g_profiler_ctx, "Hotspot::PreDrawFrame");
+ ASArglist args;
+ args.Add(curr_game_time);
+ as_context->CallScriptFunction(as_funcs.pre_draw, &args);
+}
+
+void Hotspot::Draw() {
+ if (g_debug_runtime_disable_hotspot_draw) {
+ return;
+ }
+
+ as_context->CallScriptFunction(as_funcs.draw);
+ if(scenegraph_->map_editor->state_ != MapEditor::kInGame){
+ as_context->CallScriptFunction(as_funcs.draw_editor);
+ }
+ if(!Graphics::Instance()->media_mode() && billboard_texture_ref_.valid()){
+ DrawBillboard(billboard_texture_ref_->GetTextureRef(), GetTranslation() + GetScale() * vec3(0.0f,0.5f,0.0f), 2.0f, vec4(1.0f), kStraight);
+ }
+ hud_images.Draw();
+}
+
+void Hotspot::Reset() {
+ if(as_context){
+ as_context->CallScriptFunction(as_funcs.reset);
+ }
+}
+
+void Hotspot::SetEnabled(bool val)
+{
+ Object::SetEnabled(val);
+ PROFILER_ZONE(g_profiler_ctx, "Hotspot::SetEnabled");
+ ASArglist args;
+ args.Add(val);
+ as_context->CallScriptFunction(as_funcs.set_enabled, &args);
+}
+
+int Hotspot::lineCheck(const vec3 &start, const vec3 &end, vec3 *point, vec3 *normal) {
+ return LineCheckEditorCube(start,end,point,normal);
+}
+
+void Hotspot::Moved(Object::MoveType type) {
+ Object::Moved(type);
+ if(collision_object){
+ UpdateCollisionShape();
+ }
+}
+
+void Hotspot::GetDesc(EntityDescription &desc) const {
+ Object::GetDesc(desc);
+ desc.AddString(EDF_FILE_PATH, obj_file);
+ desc.AddIntVec(EDF_CONNECTIONS, connected_to);
+ desc.AddIntVec(EDF_CONNECTIONS_FROM, connected_from);
+}
+
+//Just handle everything in hotspots
+
+void Hotspot::NotifyDeleted(Object* o) {
+ std::vector<int>::iterator iter = std::find(connected_to.begin(), connected_to.end(), o->GetID());
+ if(iter != connected_to.end()) {
+ Disconnect(*scenegraph_->GetObjectFromID(*iter));
+ }
+ Object::NotifyDeleted(o);
+}
+
+void Hotspot::HandleEvent( const std::string &event, MovementObject* mo ) {
+ if(!as_context){
+ return;
+ }
+ ASArglist args;
+ args.AddObject((void*)&event);
+ args.AddObject(mo);
+ as_context->CallScriptFunction(as_funcs.handle_event, &args);
+}
+
+void Hotspot::HandleEventItem( const std::string &event, ItemObject* obj ) {
+ if(!as_context){
+ return;
+ }
+ ASArglist args;
+ args.AddObject((void*)&event);
+ args.AddObject(obj);
+ as_context->CallScriptFunction(as_funcs.handle_event_item, &args);
+}
+
+void Hotspot::SetScriptParams( const ScriptParamMap& spm ) {
+ Object::SetScriptParams(spm);
+}
+
+void Hotspot::UpdateScriptParams() {
+ if(as_context){
+ as_context->CallScriptFunction(as_funcs.set_parameters);
+ }
+}
+
+std::string Hotspot::GetTypeString() {
+ if(!as_context){
+ return "unknown - no script";
+ }
+ ASArglist args;
+ ASArg ret_val;
+ ret_val.type = _as_object;
+ bool success = as_context->CallScriptFunction(as_funcs.get_type_string, &args, &ret_val);
+ if(success){
+ return *((std::string*)ret_val.data);
+ } else {
+ return "unknown - hotspot has no 'GetTypeString()' function";
+ }
+}
+
+bool Hotspot::ASHasVar( const std::string &name ) {
+ return as_context->GetVarPtr(name.c_str()) != NULL;
+}
+
+int Hotspot::ASGetIntVar( const std::string &name ) {
+ return *((int*)as_context->GetVarPtr(name.c_str()));
+}
+
+int Hotspot::ASGetArrayIntVar( const std::string &name, int index ) {
+ return *((int*)as_context->GetArrayVarPtr(name, index));
+}
+
+float Hotspot::ASGetFloatVar( const std::string &name ) {
+ return *((float*)as_context->GetVarPtr(name.c_str()));
+}
+
+bool Hotspot::ASGetBoolVar( const std::string &name ) {
+ return *((bool*)as_context->GetVarPtr(name.c_str()));
+}
+
+void Hotspot::ASSetIntVar( const std::string &name, int value ) {
+ *(int*)as_context->GetVarPtr(name.c_str()) = value;
+}
+
+void Hotspot::ASSetArrayIntVar( const std::string &name, int index, int value ) {
+ *(int*)as_context->GetArrayVarPtr(name, index) = value;
+}
+
+void Hotspot::ASSetFloatVar( const std::string &name, float value ) {
+ *(float*)as_context->GetVarPtr(name.c_str()) = value;
+}
+
+void Hotspot::ASSetBoolVar( const std::string &name, bool value ) {
+ *(bool*)as_context->GetVarPtr(name.c_str()) = value;
+}
+
+bool Hotspot::SetFromDesc( const EntityDescription& desc ) {
+ bool ret = Object::SetFromDesc(desc);
+ if( ret ) {
+ for(unsigned i=0; i<desc.fields.size(); ++i){
+ const EntityDescriptionField& field = desc.fields[i];
+ switch(field.type){
+ case EDF_FILE_PATH: {
+ std::string type_file;
+ field.ReadString(&type_file);
+ if(obj_file != type_file){
+ obj_file = type_file;
+ //HotspotFileRef hfr = HotspotFiles::Instance()->ReturnRef(type_file);
+ HotspotFileRef hfr = Engine::Instance()->GetAssetManager()->LoadSync<HotspotFile>(type_file);
+ if( hfr.valid() ) {
+ if(hfr->billboard_color_map != "Data/UI/spawner/thumbs/Hotspot/empty.png"){
+ SetBillboardColorMap(hfr->billboard_color_map);
+ }
+ SetScriptFile(hfr->script);
+ } else {
+ ret = false;
+ }
+ }
+ break;}
+ case EDF_CONNECTIONS: {
+ field.ReadIntVec(&unfinalized_connected_to);
+ break;}
+ case EDF_CONNECTIONS_FROM: {
+ field.ReadIntVec(&unfinalized_connected_from);
+ break;}
+ }
+ }
+ }
+ return ret;
+}
+
+void Hotspot::SetBillboardColorMap(const std::string& color_map) {
+ billboard_texture_ref_ = Engine::Instance()->GetAssetManager()->LoadSync<TextureAsset>(color_map, PX_SRGB, 0x0);
+ if( billboard_texture_ref_.valid() == false ) {
+ LOGE << "Failed to load Hotspot Billboard texture: " << color_map << " for " << this << std::endl;
+ }
+}
+
+static vec3 GetWind(vec3 check_where, float curr_game_time, float change_rate) {
+ vec3 wind_vel;
+ check_where[0] += curr_game_time*0.7f*change_rate;
+ check_where[1] += curr_game_time*0.3f*change_rate;
+ check_where[2] += curr_game_time*0.5f*change_rate;
+ wind_vel[0] = sin(check_where[0])+cos(check_where[1]*1.3f)+sin(check_where[2]*3.0f);
+ wind_vel[1] = sin(check_where[0]*1.2f)+cos(check_where[1]*1.8f)+sin(check_where[2]*0.8f);
+ wind_vel[2] = sin(check_where[0]*1.6f)+cos(check_where[1]*0.5f)+sin(check_where[2]*1.2f);
+
+ return wind_vel;
+}
+
+void Hotspot::Reload() {
+ if(as_context){
+ as_context->CallScriptFunction(as_funcs.pre_script_reload);
+ as_context->Reload();
+ as_context->CallScriptFunction(as_funcs.post_script_reload);
+ }
+}
+
+static void CFireRibbonUpdate(asIScriptObject* obj, float delta_time, float curr_game_time, const vec3& fire_pos) {
+ CScriptArray& particles = *(CScriptArray*)obj->GetAddressOfProperty(0);
+ vec3& rel_pos = *(vec3*)obj->GetAddressOfProperty(1);
+ vec3& pos = *(vec3*)obj->GetAddressOfProperty(2);
+ float& base_rand = *(float*)obj->GetAddressOfProperty(3);
+ float& spawn_new_particle_delay = *(float*)obj->GetAddressOfProperty(4);
+
+ spawn_new_particle_delay -= delta_time;
+ if(spawn_new_particle_delay <= 0.0f){
+ particles.Resize(particles.GetSize() + 1);
+ asIScriptObject* particle = (asIScriptObject*)particles.At(particles.GetSize()-1);
+ *(vec3*)particle->GetAddressOfProperty(0) = pos;
+ *(vec3*)particle->GetAddressOfProperty(1) = vec3(0.0, 0.0, 0.0);
+ *(float*)particle->GetAddressOfProperty(2) = RangedRandomFloat(0.5,1.5);
+ *(float*)particle->GetAddressOfProperty(3) = curr_game_time;
+
+ while(spawn_new_particle_delay <= 0.0f){
+ spawn_new_particle_delay += 0.1f;
+ }
+ }
+
+ int max_particles = 5;
+ if((int)particles.GetSize() > max_particles) {
+ for(int i=0; i<max_particles; ++i){
+ asIScriptObject* dst_particle = (asIScriptObject*)particles.At(i);
+ asIScriptObject* src_particle = (asIScriptObject*)particles.At(particles.GetSize()-max_particles+i);
+ dst_particle->CopyFrom(src_particle);
+ }
+ particles.Resize(max_particles);
+ }
+ for(int i=0, len=(int)particles.GetSize(); i<len; ++i){
+ asIScriptObject* particle = (asIScriptObject*)particles.At(i);
+ vec3& particle_pos = *(vec3*)particle->GetAddressOfProperty(0);
+ vec3& particle_vel = *(vec3*)particle->GetAddressOfProperty(1);
+ float& particle_heat = *(float*)particle->GetAddressOfProperty(2);
+ particle_vel *= pow(0.2f, delta_time);
+ particle_pos += particle_vel * delta_time;
+ particle_vel += GetWind(particle_pos * 5.0f, curr_game_time, 10.0f) * delta_time * 1.0f;
+ particle_vel += GetWind(particle_pos * 30.0f, curr_game_time, 10.0f) * delta_time * 2.0f;
+ vec3 rel = particle_pos - fire_pos;
+ rel[1] = 0.0;
+ particle_heat -= delta_time * (2.0f + min(1.0f, powf(dot(rel,rel), 2.0)*64.0f)) * 2.0f;
+ if(dot(rel,rel) > 1.0){
+ rel = normalize(rel);
+ }
+
+ particle_vel += rel * delta_time * -3.0f * 6.0f;
+ particle_vel[1] += delta_time * 12.0f;
+ }
+}
+
+
+void CFireRibbonPreDraw(asIScriptObject* obj, float curr_game_time) {
+ CScriptArray& particles = *(CScriptArray*)obj->GetAddressOfProperty(0);
+ float& base_rand = *(float*)obj->GetAddressOfProperty(3);
+
+ DebugDraw* debug_draw = DebugDraw::Instance();
+ int ribbon_id = debug_draw->AddRibbon(_delete_on_draw);
+ DebugDrawElement* element = DebugDraw::Instance()->GetElement(ribbon_id);
+ DebugDrawRibbon* ribbon = (DebugDrawRibbon*) element;
+ const float flame_width = 0.12f;
+ for(int i=0, len=particles.GetSize(); i<len; ++i){
+ asIScriptObject* particle = (asIScriptObject*)particles.At(i);
+ vec3& particle_pos = *(vec3*)particle->GetAddressOfProperty(0);
+ vec3& particle_vel = *(vec3*)particle->GetAddressOfProperty(1);
+ float& particle_heat = *(float*)particle->GetAddressOfProperty(2);
+ float& particle_spawn_time = *(float*)particle->GetAddressOfProperty(3);
+ ribbon->AddPoint(particle_pos, vec4(particle_heat, particle_spawn_time + base_rand, curr_game_time + base_rand, 0.0), flame_width);
+ }
+}
+
+static void ASSetCollisionEnabled(Hotspot* hotspot, bool val) {
+ if(val != hotspot->abstract_collision){
+ hotspot->abstract_collision = val;
+ hotspot->UpdateCollisionShape();
+ }
+}
+
+bool Hotspot::AcceptConnectionsFromImplemented() {
+ if(!as_context)
+ return false;
+ return as_context->HasFunction(as_funcs.accept_connections_from_obj) || as_context->HasFunction(as_funcs.accept_connections_from);
+}
+
+bool Hotspot::AcceptConnectionsFrom(Object::ConnectionType type, Object& other) {
+ bool return_value = false;
+ if(as_context) {
+ ASArglist args;
+
+ ASArg ret_val;
+ ret_val.type = _as_bool;
+ ret_val.data = &return_value;
+ args.AddObject(&other);
+ if(!as_context->CallScriptFunction(as_funcs.accept_connections_from_obj, &args, &ret_val)) {
+ args.clear();
+ args.Add((int)type);
+ as_context->CallScriptFunction(as_funcs.accept_connections_from, &args, &ret_val);
+ }
+ }
+
+ return return_value;
+}
+
+bool Hotspot::AcceptConnectionsTo(Object& other) {
+ bool return_value = false;
+ if(as_context) {
+ ASArglist args;
+
+ ASArg ret_val;
+ ret_val.type = _as_bool;
+ ret_val.data = &return_value;
+ args.AddObject(&other);
+ as_context->CallScriptFunction(as_funcs.accept_connections_to_obj, &args, &ret_val);
+ }
+
+ return return_value;
+}
+
+bool Hotspot::ConnectTo(Object& other, bool checking_other/*= false*/) {
+ if(std::find(connected_to.begin(), connected_to.end(), other.GetID()) != connected_to.end())
+ return false;
+
+ bool return_value = false;
+ if(as_context) {
+ ASArglist args;
+ args.AddObject(&other);
+
+ ASArg ret_val;
+ ret_val.type = _as_bool;
+ ret_val.data = &return_value;
+
+ as_context->CallScriptFunction(as_funcs.connect_to, &args, &ret_val);
+ }
+
+ if(return_value) {
+ connected_to.push_back(other.GetID());
+ other.ConnectedFrom(*this);
+ }
+
+ return return_value;
+}
+
+bool Hotspot::Disconnect(Object& other, bool checking_other/* = false*/) {
+ if(std::find(connected_to.begin(), connected_to.end(), other.GetID()) == connected_to.end())
+ return false;
+
+ bool return_value = false;
+ if(as_context) {
+ ASArglist args;
+ args.AddObject(&other);
+
+ ASArg ret_val;
+ ret_val.type = _as_bool;
+ ret_val.data = &return_value;
+
+ as_context->CallScriptFunction(as_funcs.disconnect, &args, &ret_val);
+ }
+
+ if(return_value) {
+ connected_to.erase(std::remove(connected_to.begin(), connected_to.end(), other.GetID()), connected_to.end());
+ other.DisconnectedFrom(*this);
+ }
+
+ return return_value;
+}
+
+void Hotspot::ConnectedFrom(Object& other) {
+ if(as_context) {
+ ASArglist args;
+ args.AddObject(&other);
+ as_context->CallScriptFunction(as_funcs.connected_from, &args);
+ }
+ connected_from.push_back(other.GetID());
+}
+
+void Hotspot::DisconnectedFrom(Object& other) {
+ if(as_context) {
+ ASArglist args;
+ args.AddObject(&other);
+ as_context->CallScriptFunction(as_funcs.disconnected_from, &args);
+ }
+ connected_from.erase(std::remove(connected_from.begin(), connected_from.end(), other.GetID()), connected_from.end());
+}
+
+CScriptArray* Hotspot::ASGetConnectedObjects() {
+ asIScriptEngine* engine = as_context->GetEngine();
+ asITypeInfo* arrayType = engine->GetTypeInfoByDecl("array<int>");
+ CScriptArray* array = CScriptArray::Create(arrayType);
+
+ array->Reserve(connected_to.size());
+ for(size_t i = 0; i < connected_to.size(); ++i) {
+ array->InsertLast(&connected_to[i]);
+ }
+ return array;
+}
+
+bool Hotspot::HasCustomGUI() {
+ return as_context && as_context->HasFunction(as_funcs.launch_custom_gui);
+}
+
+void Hotspot::LaunchCustomGUI() {
+ if(as_context) {
+ as_context->CallScriptFunction(as_funcs.launch_custom_gui);
+ }
+}
+
+bool Hotspot::ObjectInspectorReadOnly() {
+ bool return_value = false;
+ if(as_context) {
+ ASArg ret_val;
+ ret_val.type = _as_bool;
+ ret_val.data = &return_value;
+ as_context->CallScriptFunction(as_funcs.object_inspector_read_only, NULL, &ret_val);
+ }
+ return return_value;
+}
+
+bool Hotspot::HasFunction(const std::string& function_definition) {
+ bool result = false;
+
+ if(as_context) {
+ result = as_context->HasFunction(function_definition);
+ }
+
+ return result;
+}
+
+int Hotspot::QueryIntFunction(const std::string& function) {
+ if(as_context) {
+ ASArglist args;
+ int val;
+ ASArg return_val;
+ return_val.type = _as_int;
+ return_val.data = &val;
+ as_context->CallScriptFunction(function, &args, &return_val);
+ return val;
+ } else {
+ return -1;
+ }
+}
+
+bool Hotspot::QueryBoolFunction(const std::string& function) {
+ if(as_context) {
+ ASArglist args;
+ bool val;
+ ASArg return_val;
+ return_val.type = _as_bool;
+ return_val.data = &val;
+ as_context->CallScriptFunction(function, &args, &return_val);
+ return val;
+ } else {
+ return false;
+ }
+}
+
+float Hotspot::QueryFloatFunction(const std::string& function) {
+ if(as_context) {
+ ASArglist args;
+ float val;
+ ASArg return_val;
+ return_val.type = _as_float;
+ return_val.data = &val;
+ as_context->CallScriptFunction(function, &args, &return_val);
+ return val;
+ } else {
+ return -1.0f;
+ }
+}
+
+std::string Hotspot::QueryStringFunction(const std::string& function) {
+ if(as_context) {
+ ASArglist args;
+ std::string val;
+ ASArg return_val;
+ return_val.type = _as_string;
+ as_context->CallScriptFunction(function, &args, &return_val);
+ return return_val.strData;
+ } else {
+ return "";
+ }
+}
+
+static bool ConnectTo(Hotspot* obj, Object* other) {
+ if(!other)
+ return false;
+ return obj->ConnectTo(*other);
+}
+static bool Disconnect(Hotspot* obj, Object* other) {
+ if(!other)
+ return false;
+ return obj->Disconnect(*other);
+}
+
+void DefineHotspotTypePublic(ASContext* as_context) {
+ as_context->RegisterObjectType("Hotspot", 0, asOBJ_REF | asOBJ_NOCOUNT);
+ as_context->GetEngine()->RegisterInterface("C_ACCEL");
+ as_context->RegisterObjectMethod("Hotspot",
+ "int GetID()",
+ asMETHOD(Hotspot, GetID), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "string GetTypeString()",
+ asMETHOD(Hotspot, GetTypeString), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "bool HasVar(string& in name)",
+ asMETHOD(Hotspot, ASHasVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "bool GetBoolVar(string& in name)",
+ asMETHOD(Hotspot, ASGetBoolVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "int GetIntVar(string& in name)",
+ asMETHOD(Hotspot, ASGetIntVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "int GetArrayIntVar(const string &in name, int index)",
+ asMETHOD(Hotspot, ASGetArrayIntVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "float GetFloatVar(string& in name)",
+ asMETHOD(Hotspot, ASGetFloatVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "void SetIntVar(string& in name, int value)",
+ asMETHOD(Hotspot, ASSetIntVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "void SetArrayIntVar(const string &in name, int index, int value)",
+ asMETHOD(Hotspot, ASSetArrayIntVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "void SetFloatVar(string& in name, float value)",
+ asMETHOD(Hotspot, ASSetFloatVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "void SetBoolVar(string& in name, bool value)",
+ asMETHOD(Hotspot, ASSetBoolVar), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "array<int> @GetConnectedObjects()",
+ asMETHOD(Hotspot, ASGetConnectedObjects), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "bool HasFunction(const string &in function_definition)",
+ asMETHOD(Hotspot, HasFunction), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "int QueryIntFunction(const string &in function)",
+ asMETHOD(Hotspot, QueryIntFunction), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "bool QueryBoolFunction(const string &in function)",
+ asMETHOD(Hotspot, QueryBoolFunction), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "float QueryFloatFunction(const string &in function)",
+ asMETHOD(Hotspot, QueryFloatFunction), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "string QueryStringFunction(const string &in function)",
+ asMETHOD(Hotspot, QueryStringFunction), asCALL_THISCALL);
+ as_context->RegisterObjectMethod("Hotspot",
+ "void SetCollisionEnabled(bool)",
+ asFUNCTION(ASSetCollisionEnabled), asCALL_CDECL_OBJFIRST);
+ // Inherited from Object
+ as_context->RegisterObjectMethod("Hotspot", "bool ConnectTo(Object@)", asFUNCTION(ConnectTo), asCALL_CDECL_OBJFIRST);
+ as_context->RegisterObjectMethod("Hotspot", "bool Disconnect(Object@)", asFUNCTION(Disconnect), asCALL_CDECL_OBJFIRST);
+
+ as_context->RegisterGlobalFunction("void CFireRibbonUpdate(C_ACCEL @, float delta_time, float curr_game_time, vec3 &in pos)",
+ asFUNCTION(CFireRibbonUpdate), asCALL_CDECL);
+ as_context->RegisterGlobalFunction("void CFireRibbonPreDraw(C_ACCEL @, float curr_game_time)",
+ asFUNCTION(CFireRibbonPreDraw), asCALL_CDECL);
+ as_context->DocsCloseBrace();
+}