void game_create_object_world(const ScriptArguments& args) { int id = 0; switch(args[0].type) { case TInt8: id = (std::int8_t)args[0].integer; break; case TInt16: id = (std::int16_t)args[0].integer; break; default: RW_ERROR("Unhandled integer type"); break; } if( id < 0 ) { auto& modelname = args.getVM()->getFile()->getModels()[-id]; id = args.getWorld()->data->findModelObject(modelname); if( id == (uint16_t)-1 ) { args.getWorld()->logger->error("SCM", "Failed to find model " + modelname); } } glm::vec3 position(args[1].real, args[2].real, args[3].real); auto inst = args.getWorld()->createInstance(id, position); *args[4].globalInteger = inst->getGameObjectID(); }
std::string GameConfig::getDefaultConfigPath() { #if defined(RW_LINUX) || defined(RW_FREEBSD) char* config_home = getenv("XDG_CONFIG_HOME"); if (config_home != nullptr) { return std::string(config_home) + "/" + kConfigDirectoryName; } char* home = getenv("HOME"); if (home != nullptr) { return std::string(home) + "/.config/" + kConfigDirectoryName; } #elif defined(RW_OSX) char* home = getenv("HOME"); if (home) return std::string(home) + "/Library/Preferences/" + kConfigDirectoryName; #else return "."; #endif // Well now we're stuck. RW_ERROR("No default config path found."); return "."; }
void ViewerWindow::switchView(int mode) { if( mode < int(m_views.size()) ) { m_views[mode]->setViewerWidget( viewerWidget ); } else { RW_ERROR("Unhandled view mode" << mode); } }
GLuint compileShader(GLenum type, const char* source) { GLuint shader = glCreateShader(type); if (shader == 0) { RW_ERROR("[OGL] Failed to create shader object"); throw std::runtime_error("Compiling shader failed"); } glShaderSource(shader, 1, &source, nullptr); glCompileShader(shader); GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { RW_ERROR("[OGL] Shader Compilation Failed"); } GLint len; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); if (len > 1) { auto buffer = std::make_unique<GLchar[]>(len); glGetShaderInfoLog(shader, len, nullptr, buffer.get()); GLint sourceLen; glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLen); auto sourceBuff = std::make_unique<GLchar[]>(sourceLen); glGetShaderSource(shader, sourceLen, nullptr, sourceBuff.get()); RW_ERROR("[OGL] Shader InfoLog(" << shader << "):\n" << buffer.get() << "\nSource:\n" << sourceBuff.get()); } if (status != GL_TRUE) { throw std::runtime_error("Compiling shader failed"); } return shader; }
GLuint compileProgram(const char* vertex, const char* fragment) { GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertex); GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragment); GLuint prog = glCreateProgram(); glAttachShader(prog, vertexShader); glAttachShader(prog, fragmentShader); glLinkProgram(prog); glDetachShader(prog, vertexShader); glDetachShader(prog, fragmentShader); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); GLint status; glGetProgramiv(prog, GL_LINK_STATUS, &status); if (status != GL_TRUE) { RW_ERROR("[OGL] Program Link Failed"); } GLint len; glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len); if (len > 1) { auto buffer = std::make_unique<GLchar[]>(len); glGetProgramInfoLog(prog, len, nullptr, buffer.get()); RW_ERROR("[OGL] Program InfoLog(" << prog << "):\n" << buffer.get()); } if (status != GL_TRUE) { throw std::runtime_error("Linking shaders failed"); } return prog; }
void game_set_close_object_visible(const ScriptArguments& args) { glm::vec3 position(args[0].real, args[1].real, args[2].real); float radius = args[3].real; int modelid = 0; /// @todo fix this being a problem. switch(args[4].type) { case TInt8: modelid = (std::int8_t)args[4].integer; break; case TInt16: modelid = (std::int16_t)args[4].integer; break; default: RW_ERROR("Unhandled integer type"); break; } if( std::abs(modelid) > 178 ) { /// @todo implement this path, return; } std::string model; if(modelid < 0) modelid = -modelid; model = args.getVM()->getFile()->getModels()[modelid]; std::transform(model.begin(), model.end(), model.begin(), ::tolower); for(auto& p : args.getWorld()->instancePool.objects) { auto o = p.second; if( !o->model ) continue; if( o->model->name != model ) continue; float d = glm::distance(position, o->getPosition()); if( d < radius ) { o->visible = !!args[5].integer; } } }
void game_change_nearest_model(const ScriptArguments& args) { glm::vec3 position(args[0].real, args[1].real, args[2].real); float radius = args[3].real; int newid = 0, oldid = 0; /// @todo fix this being a problem. switch(args[4].type) { case TInt8: oldid = (std::int8_t)args[4].integer; break; case TInt16: oldid = (std::int16_t)args[4].integer; break; default: RW_ERROR("Unhandled integer type"); break; } switch(args[5].type) { case TInt8: newid = (std::int8_t)args[5].integer; break; case TInt16: newid = (std::int16_t)args[5].integer; break; default: RW_ERROR("Unhandled integer type"); break; } if( std::abs(newid) > 178 || std::abs(oldid) > 178 ) { /// @todo implement this path, return; } std::string newmodel; std::string oldmodel; if(newid < 0) newid = -newid; if(oldid < 0) oldid = -oldid; newmodel = args.getVM()->getFile()->getModels()[newid]; oldmodel = args.getVM()->getFile()->getModels()[oldid]; std::transform(newmodel.begin(), newmodel.end(), newmodel.begin(), ::tolower); std::transform(oldmodel.begin(), oldmodel.end(), oldmodel.begin(), ::tolower); auto newobjectid = args.getWorld()->data->findModelObject(newmodel); auto nobj = args.getWorld()->data->findObjectType<ObjectData>(newobjectid); /// @todo Objects need to adopt the new object ID, not just the model. for(auto p : args.getWorld()->instancePool.objects) { auto o = p.second; if( !o->model ) continue; if( o->model->name != oldmodel ) continue; float d = glm::distance(position, o->getPosition()); if( d < radius ) { args.getWorld()->data->loadDFF(newmodel + ".dff", false); InstanceObject* inst = static_cast<InstanceObject*>(o); inst->changeModel(nobj); inst->model = args.getWorld()->data->models[newmodel]; } } }
void game_create_pickup(const ScriptArguments& args) { glm::vec3 pos (args[2].real, args[3].real, args[4].real); int id; int type = args[1].integer; switch(args[0].type) { case TInt8: id = (std::int8_t)args[0].integer; break; case TInt16: id = (std::int16_t)args[0].integer; break; default: RW_ERROR("Unhandled integer type"); *args[5].globalInteger = 0; return; } if ( id < 0 ) { id = -id; auto model = args.getVM()->getFile()->getModels()[id]; std::transform(model.begin(), model.end(), model.begin(), ::tolower); id = args.getWorld()->data->findModelObject(model); args.getWorld()->data->loadDFF(model+".dff"); args.getWorld()->data->loadTXD("icons.txd"); } else { auto data = args.getWorld()->data->findObjectType<ObjectData>(id); if ( ! ( id >= 170 && id <= 184 ) ) { args.getWorld()->data->loadDFF(data->modelName+".dff"); } args.getWorld()->data->loadTXD(data->textureName+".txd"); } PickupObject* pickup = nullptr; if ( id >= 170 && id <= 184 ) { // Find the item for this model ID auto world = args.getWorld(); InventoryItem *item = nullptr; for (auto i = 0; i < maxInventorySlots; ++i) { item = world->getInventoryItem(i); if (item->getModelID() == id) { auto pickuptype = (PickupObject::PickupType)type; pickup = new ItemPickup(args.getWorld(), pos, pickuptype, item); world->pickupPool.insert( pickup ); world->allObjects.push_back(pickup); *args[5].globalInteger = pickup->getGameObjectID(); } } } else { RW_UNIMPLEMENTED("non-item pickups"); *args[5].globalInteger = 0; } }
bool Activities::UseItem::update(CharacterObject *character, CharacterController *controller) { RW_UNUSED(controller); if (itemslot >= kMaxInventorySlots) { return true; } // Finds the cycle associated with an anim from the AnimGroup /// @todo doesn't need to happen every update.. auto find_cycle = [&](const std::string &name) { if (name == "null") { return AnimCycle::Idle; } for (auto &i : character->animations->animations_) { if (i.name == name) return i.id; } return AnimCycle::Idle; }; auto world = character->engine; auto weapon = &world->data->weaponData.at(itemslot); auto &state = character->getCurrentState().weapons[itemslot]; auto &animator = character->animator; auto shootcycle = find_cycle(weapon->animation1); auto throwcycle = find_cycle(weapon->animation2); // No weapon except for Uzi can be used while in a vehicle if (character->getCurrentVehicle() && weapon->name != "uzi") { return false; } // Instant hit weapons loop their anim // Thrown projectiles have lob / throw. // Update player direction character->setRotation( glm::angleAxis(character->getLook().x, glm::vec3{0.f, 0.f, 1.f})); if (state.bulletsClip == 0 && state.bulletsTotal > 0) { state.bulletsClip += std::min(static_cast<int>(state.bulletsTotal), weapon->clipSize); state.bulletsTotal -= state.bulletsClip; } bool hasammo = state.bulletsClip > 0; if (weapon->fireType == WeaponData::INSTANT_HIT) { if (!character->getCurrentState().primaryActive) { // Character is no longer firing return true; } if (hasammo) { if (character->getCurrentCycle() != shootcycle) { character->playCycle(shootcycle); } auto loopstart = weapon->animLoopStart / 100.f; auto loopend = weapon->animLoopEnd / 100.f; auto firetime = weapon->animFirePoint / 100.f; auto currenttime = animator->getAnimationTime(AnimIndexAction); if (currenttime >= firetime && !fired) { state.bulletsClip--; Weapon::fireHitscan(weapon, character); fired = true; } if (currenttime > loopend) { animator->setAnimationTime(AnimIndexAction, loopstart); fired = false; } } else if (animator->isCompleted(AnimIndexAction)) { // Should we exit this state when out of ammo? return true; } } /// @todo Use Thrown flag instead of project (RPG isn't thrown eg.) else if (weapon->fireType == WeaponData::PROJECTILE && hasammo) { if (character->getCurrentCycle() == shootcycle) { if (character->getCurrentState().primaryActive) { power = animator->getAnimationTime(AnimIndexAction) / 0.5f; } if (animator->isCompleted(AnimIndexAction)) { character->playCycle(throwcycle); } } else if (character->getCurrentCycle() == throwcycle) { auto firetime = weapon->animCrouchFirePoint / 100.f; auto currID = animator->getAnimationTime(AnimIndexAction); if (currID >= firetime && !fired) { state.bulletsClip--; Weapon::fireProjectile(weapon, character, power); fired = true; } if (animator->isCompleted(AnimIndexAction)) { return true; } } else { character->playCycle(shootcycle); } } else if (weapon->fireType == WeaponData::MELEE) { auto currentAnim = character->getCurrentCycle(); if (currentAnim == shootcycle || currentAnim == throwcycle) { auto fireTime = weapon->animFirePoint / 100.f; auto loopStart = weapon->animLoopStart / 100.f; auto currentTime = animator->getAnimationTime(AnimIndexAction); if (currentTime >= fireTime && !fired) { Weapon::meleeHit(weapon, character); fired = true; } if (animator->isCompleted(AnimIndexAction)) { if (character->getCurrentState().primaryActive) { animator->setAnimationTime(AnimIndexAction, loopStart); fired = false; } else { return true; } } } else { const auto onGround = Weapon::targetOnGround(weapon, character); if (onGround) { character->playCycle(throwcycle); } else { character->playCycle(shootcycle); } } } else { RW_ERROR("Unrecognized fireType: " << weapon->fireType); return true; } return false; }