void sensor_support_think( gentity_t *self ) { if(!self->enabled) { self->nextthink = level.time + SENSOR_POLL_PERIOD * 5; return; } switch (self->conditions.team) { case TEAM_HUMANS: self->powered = G_FindPower( self, qfalse ); break; case TEAM_ALIENS: self->powered = G_FindCreep( self ); break; case TEAM_ALL: self->powered = G_FindPower( self, qfalse ); if(!self->powered) self->powered = G_FindCreep( self ); break; default: G_Printf(S_ERROR "missing team field for %s\n", etos( self )); G_FreeEntity( self ); break; } if(self->powered) G_FireEntity( self, self->powerSource ); self->nextthink = level.time + SENSOR_POLL_PERIOD; }
bool G_ValidateEntity( entityClassDescriptor_t *entityClass, gentity_t *entity ) { switch (entityClass->chainType) { case CHAIN_ACTIVE: if(!entity->callTargetCount) //check target usage for backward compatibility { if( g_debugEntities.integer > -2 ) Log::Warn("Entity %s needs to call or target to something — Removing it.", etos( entity ) ); return false; } break; case CHAIN_TARGET: case CHAIN_PASSIV: if(!entity->names[0]) { if( g_debugEntities.integer > -2 ) Log::Warn("Entity %s needs a name, so other entities can target it — Removing it.", etos( entity ) ); return false; } break; case CHAIN_RELAY: if((!entity->callTargetCount) //check target usage for backward compatibility || !entity->names[0]) { if( g_debugEntities.integer > -2 ) Log::Warn("Entity %s needs a name as well as a target to conditionally relay the firing — Removing it.", etos( entity ) ); return false; } break; default: break; } return true; }
int DbProxy::getTaskHistory(const string & application, const string & serverName, const string & command, vector<TaskRsp> &taskRsp) { string sql = "select t1.`create_time`, t1.`serial`, t1.`user_name`, t2.* from t_task as t1, t_task_item as t2 where t1.task_no=t2.task_no and t2.application='" + _mysqlReg.escapeString(application) + "' and t2.server_name='" + _mysqlReg.escapeString(serverName) + "' and t2.command='" + _mysqlReg.escapeString(command) + "' order by create_time desc, task_no"; try { tars::TC_Mysql::MysqlData res = _mysqlReg.queryRecord(sql); TLOGDEBUG("DbProxy::getTaskHistory size:" << res.size() << ", sql:" << sql << endl); for (unsigned i = 0; i < res.size(); i++) { string taskNo = res[i]["task_no"]; //获取Item TaskItemRsp itemRsp; itemRsp.startTime = res[i]["start_time"]; itemRsp.endTime = res[i]["end_time"]; itemRsp.status = (EMTaskItemStatus)TC_Common::strto<int>(res[i]["status"]); itemRsp.statusInfo= etos(itemRsp.status); itemRsp.req.taskNo = res[i]["task_no"]; itemRsp.req.itemNo = res[i]["item_no"]; itemRsp.req.application = res[i]["application"]; itemRsp.req.serverName = res[i]["server_name"]; itemRsp.req.nodeName = res[i]["node_name"]; itemRsp.req.setName = res[i]["set_name"]; itemRsp.req.command = res[i]["command"]; itemRsp.req.parameters = TC_Parsepara(res[i]["parameters"]).toMap(); if (taskRsp.empty() || taskRsp[taskRsp.size() - 1].taskNo != taskNo) { //新的TaskRsp TaskRsp rsp; rsp.taskNo = res[i]["task_no"]; rsp.serial = TC_Common::strto<int>(res[i]["serial"]); rsp.userName = res[i]["user_name"]; rsp.taskItemRsp.push_back(itemRsp); taskRsp.push_back(rsp); } else { taskRsp.back().taskItemRsp.push_back(itemRsp); } } } catch (exception &ex) { TLOGERROR("DbProxy::getTaskHistory exception: " << ex.what() << endl); return -1; } return 0; }
// マップオブジェクトを取得 MapObject* GameEventHelper::getMapObjectById(const string& objectId, bool available) { // heroであったら主人公を返す if (objectId == "hero" || objectId == etos(ObjectID::HERO)) { return DungeonSceneManager::getInstance()->getParty()->getMainCharacter(); } // heroでなければIDから検索して返す else { if(available) return DungeonSceneManager::getInstance()->getMapObjectList()->getMapObject(stoi(objectId)); return DungeonSceneManager::getInstance()->getMapObjectList()->getMapObjectFromDisableList(stoi(objectId)); } }
int DbProxy::getTaskRsp(const string &taskNo, TaskRsp &taskRsp) { try { string sql = "select * from t_task as t1, t_task_item as t2 where t1.task_no=t2.task_no and t2.task_no='" + _mysqlReg.escapeString(taskNo) + "'"; tars::TC_Mysql::MysqlData item = _mysqlReg.queryRecord(sql); if (item.size() == 0) { TLOGERROR("DbProxy::getTaskRsp 't_task' not task: " << taskNo << endl); return -1; } taskRsp.taskNo = item[0]["task_no"]; taskRsp.serial = TC_Common::strto<int>(item[0]["serial"]); taskRsp.userName = item[0]["user_name"]; for (unsigned i = 0; i < item.size(); i++) { TaskItemRsp rsp; rsp.startTime = item[i]["start_time"]; rsp.endTime = item[i]["end_time"]; rsp.status = (EMTaskItemStatus)TC_Common::strto<int>(item[i]["status"]); rsp.statusInfo = etos(rsp.status); rsp.req.taskNo = item[i]["task_no"]; rsp.req.itemNo = item[i]["item_no"]; rsp.req.application = item[i]["application"]; rsp.req.serverName = item[i]["server_name"]; rsp.req.nodeName = item[i]["node_name"]; rsp.req.setName = item[i]["set_name"]; rsp.req.command = item[i]["command"]; rsp.req.parameters = TC_Parsepara(item[i]["parameters"]).toMap(); taskRsp.taskItemRsp.push_back(rsp); } ExecuteTask::getInstance()->checkTaskRspStatus(taskRsp); } catch (TC_Mysql_Exception& ex) { TLOGERROR("DbProxy::getTaskRsp exception"<<ex.what()<<endl); return -3; } return 0; }
void Svcmd_EntityFire_f() { char argument[ MAX_STRING_CHARS ]; int entityNum; gentity_t *selection; gentityCall_t call; gentityCallDefinition_t callDefinition = { nullptr, ON_DEFAULT, nullptr, nullptr, ECA_DEFAULT }; if ( trap_Argc() < 2 || trap_Argc() > 3 ) { G_Printf( "usage: entityFire <entityNum> [<action>]\n" ); return; } trap_Argv( 1, argument, sizeof( argument ) ); entityNum = atoi( argument ); if ( entityNum >= level.num_entities || entityNum < MAX_CLIENTS ) { G_Printf( "invalid entityId %d\n", entityNum ); return; } selection = &g_entities[entityNum]; if (!selection->inuse) { G_Printf("entity slot %d is not in use\n", entityNum); return; } if( trap_Argc() >= 3 ) { trap_Argv( 2, argument, sizeof( argument ) ); callDefinition.action = argument; callDefinition.actionType = G_GetCallActionTypeFor( callDefinition.action ); } G_Printf( "firing %s:%s\n", etos( selection ), callDefinition.action ? callDefinition.action : "default" ); if(selection->names[0]) callDefinition.name = selection->names[0]; call.definition = &callDefinition; call.caller = &g_entities[ ENTITYNUM_NONE ]; call.activator = &g_entities[ ENTITYNUM_NONE ] ; G_CallEntity(selection, &call); }
/* =============== SP_trigger_ammo =============== */ void SP_env_afx_ammo( gentity_t *self ) { G_SpawnInt( "ammo", "1", &self->config.amount ); if ( self->config.amount <= 0 ) { self->config.amount = 1; Log::Warn( "%s with negative or unset ammo amount key", etos(self) ); } self->touch = env_afx_ammo_touch; self->act = env_afx_toggle; InitEnvAFXEntity( self, true ); }
void SocketHandler::onClose(int id, int fd, const string& ip, int port, int closeType) { STORM_INFO << m_config.serviceName << " close " << id << " " << fd << " " << ip << ":" << port << ", " << etos((Socket_CloseType)closeType); m_conList.del(id); m_timelist.del(id); Connection::ptr pack(new Connection); pack->type = Net_Close; pack->id = id; pack->fd = fd; pack->port = port; pack->ip = ip; pack->closeType = closeType; m_packets.push_back(pack); }
void SP_WaitFields( gentity_t *self, float defaultWait, float defaultWaitVariance ) { if (!self->config.wait.time) self->config.wait.time = defaultWait; if (!self->config.wait.variance) self->config.wait.variance = defaultWaitVariance; if ( self->config.wait.variance >= self->config.wait.time && self->config.wait.variance > 0) { self->config.wait.variance = self->config.wait.time - FRAMETIME; if( g_debugEntities.integer > -1) { Log::Warn( "Entity %s has wait.variance >= wait.time", etos( self ) ); } } }
void SP_sfx_speaker( gentity_t *self ) { char buffer[ MAX_QPATH ]; char *tmpString; if ( !G_SpawnString( "noise", "NOSOUND", &tmpString ) ) { G_Error( "speaker %s without a noise key", etos( self ) ); } // force all client-relative sounds to be "activator" speakers that // play on the entity that activates the speaker if ( tmpString[ 0 ] == '*' ) { self->spawnflags |= 8; } self->soundIndex = G_SoundIndex( tmpString ); // a repeating speaker can be done completely client side self->s.eType = ET_SPEAKER; self->s.eventParm = self->soundIndex; self->s.frame = self->config.wait.time * 10; self->s.clientNum = self->config.wait.variance * 10; // check for prestarted looping sound if ( self->spawnflags & 1 ) { self->s.loopSound = self->soundIndex; } self->act = target_speaker_act; if ( self->spawnflags & 4 ) { self->r.svFlags |= SVF_BROADCAST; } VectorCopy( self->s.origin, self->s.pos.trBase ); // must link the entity so we get areas and clusters so // the server can determine who to send updates to trap_LinkEntity( self ); }
/* ================= G_FreeEntity Marks the entity as free ================= */ void G_FreeEntity( gentity_t *entity ) { trap_UnlinkEntity( entity ); // unlink from world if ( entity->neverFree ) { return; } if ( g_debugEntities.integer > 2 ) G_Printf(S_DEBUG "Freeing Entity %s\n", etos(entity)); if( entity->eclass && entity->eclass->instanceCounter > 0) entity->eclass->instanceCounter--; memset( entity, 0, sizeof( *entity ) ); entity->classname = "freent"; entity->freetime = level.time; entity->inuse = qfalse; }
/* ================= G_FreeEntity Marks the entity as free ================= */ void G_FreeEntity( gentity_t *entity ) { trap_UnlinkEntity( entity ); // unlink from world if ( entity->neverFree ) { return; } if ( g_debugEntities.integer > 2 ) { G_Printf(S_DEBUG "Freeing Entity %s\n", etos(entity)); } if ( entity->obstacleHandle ) { trap_BotRemoveObstacle( entity->obstacleHandle ); } if( entity->eclass && entity->eclass->instanceCounter > 0 ) { entity->eclass->instanceCounter--; } if ( entity->s.eType == ET_BEACON && entity->s.modelindex == BCT_TAG ) { // It's possible that this happened before, but we need to be sure. BaseClustering::Remove(entity); } if (entity->entity != &emptyEntity) { delete entity->entity; } memset( entity, 0, sizeof( *entity ) ); entity->entity = &emptyEntity; entity->classname = "freent"; entity->freetime = level.time; entity->inuse = false; }
/** * @brief */ static void G_trigger_hurt_Touch(g_entity_t *self, g_entity_t *other, const cm_bsp_plane_t *plane, const cm_bsp_texinfo_t *surf) { if (!other->locals.take_damage) { // deal with items that land on us if (other->locals.item) { if (other->locals.item->type == ITEM_FLAG) { G_ResetDroppedFlag(other); } else if (other->locals.item->type == ITEM_TECH) { G_ResetDroppedTech(other); } else { G_FreeEntity(other); } } gi.Debug("%s\n", etos(other)); return; } if (self->locals.timestamp > g_level.time) { return; } if (self->locals.spawn_flags & 16) { self->locals.timestamp = g_level.time + 1000; } else { self->locals.timestamp = g_level.time + 100; } const int16_t d = self->locals.damage; int32_t dflags = DMG_NO_ARMOR; if (self->locals.spawn_flags & 8) { dflags = DMG_NO_GOD; } G_Damage(other, self, NULL, NULL, NULL, NULL, d, d, dflags, MOD_TRIGGER_HURT); }
int DbProxy::updateServerState(const string& app, const string& serverName, const string& nodeName, const string& stateFields, tars::ServerState state, int processId) { try { int64_t iStart = TC_TimeProvider::getInstance()->getNowMs(); if (stateFields != "setting_state" && stateFields != "present_state") { TLOGDEBUG(app << "." << serverName << "_" << nodeName << " not supported fields:" << stateFields << endl); return -1; } string sProcessIdSql = (stateFields == "present_state" ? (", process_id = " + TC_Common::tostr<int>(processId) + " ") : ""); string sql = "update t_server_conf " "set " + stateFields + " = '" + etos(state) + "' " + sProcessIdSql + "where application='" + _mysqlReg.escapeString(app) + "' " " and server_name='" + _mysqlReg.escapeString(serverName) + "' " " and node_name='" + _mysqlReg.escapeString(nodeName) + "' "; _mysqlReg.execute(sql); TLOGDEBUG(__FUNCTION__ << " " << app << "." << serverName << "_" << nodeName << " affected:" << _mysqlReg.getAffectedRows() << "|cost:" << (TC_TimeProvider::getInstance()->getNowMs() - iStart) << endl); return 0; } catch (TC_Mysql_Exception& ex) { TLOGERROR(__FUNCTION__ << " " << app << "." << serverName << "_" << nodeName << " exception: " << ex.what() << endl); return -1; } }
bool G_HandleEntityVersions( entityClassDescriptor_t *spawnDescription, gentity_t *entity ) { if ( spawnDescription->versionState == ENT_V_CURRENT ) // we don't need to handle anything return true; if ( !spawnDescription->replacement || !Q_stricmp(entity->classname, spawnDescription->replacement)) { if ( g_debugEntities.integer > -2 ) Log::Warn("Class %s has been marked deprecated but no replacement has been supplied", etos( entity ) ); return false; } if ( g_debugEntities.integer >= 0 ) //dont't warn about anything with -1 or lower { if( spawnDescription->versionState < ENT_V_TMPORARY || ( g_debugEntities.integer >= 1 && spawnDescription->versionState >= ENT_V_TMPORARY) ) { Log::Warn("Entity %s uses a deprecated classtype — use the class ^5%s^* instead", etos( entity ), spawnDescription->replacement ); } } entity->classname = spawnDescription->replacement; return true; }
/** * G_PickRandomTargetFor * Selects a random entity from among the targets */ gentity_t *G_PickRandomTargetFor( gentity_t *self ) { int targetIndex; gentity_t *foundTarget = nullptr; int totalChoiceCount = 0; gentity_t *choices[ MAX_GENTITIES ]; //collects the targets while( ( foundTarget = G_IterateTargets( foundTarget, &targetIndex, self ) ) != nullptr ) choices[ totalChoiceCount++ ] = foundTarget; if ( !totalChoiceCount ) { if ( g_debugEntities.integer > -1 ) { Log::Warn( "none of the following targets could be resolved for Entity %s:", etos(self)); G_PrintEntityNameList( self ); } return nullptr; } //return a random one from among the choices return choices[ rand() / ( RAND_MAX / totalChoiceCount + 1 ) ]; }
/* * @brief Search for all entities that the specified entity targets, and call their * use functions. Set their activator to our activator. Print our message, * if set, to the activator. */ void G_UseTargets(g_entity_t *ent, g_entity_t *activator) { g_entity_t *t; // check for a delay if (ent->locals.delay) { // create a temp object to fire at a later time t = G_AllocEntity(__func__); t->locals.next_think = g_level.time + ent->locals.delay * 1000; t->locals.Think = G_UseTargets_Delay; t->locals.activator = activator; if (!activator) gi.Debug("No activator for %s\n", etos(ent)); t->locals.message = ent->locals.message; t->locals.target = ent->locals.target; t->locals.kill_target = ent->locals.kill_target; return; } // print the message if ((ent->locals.message) && activator->client) { gi.WriteByte(SV_CMD_CENTER_PRINT); gi.WriteString(ent->locals.message); gi.Unicast(activator, true); if (ent->locals.noise_index) gi.Sound(activator, ent->locals.noise_index, ATTEN_NORM); else gi.Sound(activator, gi.SoundIndex("misc/chat"), ATTEN_NORM); } // kill kill_targets if (ent->locals.kill_target) { t = NULL; while ((t = G_Find(t, LOFS(target_name), ent->locals.kill_target))) { G_FreeEntity(t); if (!ent->in_use) { gi.Debug("%s was removed while using kill_targets\n", etos(ent)); return; } } } // doors fire area portals in a specific way const _Bool is_door = g_str_has_prefix(ent->class_name, "func_door"); // fire targets if (ent->locals.target) { t = NULL; while ((t = G_Find(t, LOFS(target_name), ent->locals.target))) { if (is_door && !g_strcmp0(t->class_name, "func_areaportal")) { continue; } if (t == ent) { gi.Debug("%s tried to use itself\n", etos(ent)); continue; } if (t->locals.Use) { t->locals.Use(t, ent, activator); if (!ent->in_use) { // see if our target freed us gi.Debug("%s was removed while using targets\n", etos(ent)); break; } } } } }
void G_CallEntity(gentity_t *targetedEntity, gentityCall_t *call) { if ( g_debugEntities.integer > 1 ) { G_Printf(S_DEBUG "[%s] %s calling %s %s:%s\n", etos( call->activator ), etos( call->caller ), call->definition ? call->definition->event : "onUnknown", etos( targetedEntity ), call->definition && call->definition->action ? call->definition->action : "default"); } targetedEntity->callIn = *call; if((!targetedEntity->handleCall || !targetedEntity->handleCall(targetedEntity, call)) && call->definition) { switch (call->definition->actionType) { case ECA_NOP: break; case ECA_CUSTOM: if ( g_debugEntities.integer > -1 ) { G_Printf(S_WARNING "Unknown action \"%s\" for %s\n", call->definition->action, etos(targetedEntity)); } break; case ECA_FREE: G_FreeEntity(targetedEntity); return; //we have to handle notification differently in the free-case case ECA_PROPAGATE: G_FireEntity( targetedEntity, call->activator); break; case ECA_ENABLE: if(!targetedEntity->enabled) //only fire an event if we weren't already enabled { targetedEntity->enabled = true; G_EventFireEntity( targetedEntity, call->activator, ON_ENABLE ); } break; case ECA_DISABLE: if(targetedEntity->enabled) //only fire an event if we weren't already disabled { targetedEntity->enabled = false; G_EventFireEntity( targetedEntity, call->activator, ON_DISABLE ); } break; case ECA_TOGGLE: targetedEntity->enabled = !targetedEntity->enabled; G_EventFireEntity( targetedEntity, call->activator, targetedEntity->enabled ? ON_ENABLE : ON_DISABLE ); break; case ECA_USE: if (!targetedEntity->use) { if(g_debugEntities.integer >= 0) G_Printf(S_WARNING "calling :use on %s, which has no use function!\n", etos(targetedEntity)); break; } if(!call->activator || !call->activator->client) { if(g_debugEntities.integer >= 0) G_Printf(S_WARNING "calling %s:use, without a client as activator.\n", etos(targetedEntity)); break; } targetedEntity->use(targetedEntity, call->caller, call->activator); break; case ECA_RESET: if (targetedEntity->reset) { targetedEntity->reset(targetedEntity); G_EventFireEntity( targetedEntity, call->activator, ON_RESET ); } break; case ECA_ACT: G_HandleActCall( targetedEntity, call ); break; default: if (targetedEntity->act) targetedEntity->act(targetedEntity, call->caller, call->activator); break; } } if(targetedEntity->notifyHandler) targetedEntity->notifyHandler( targetedEntity, call ); targetedEntity->callIn = NULL_CALL; /**< not called anymore */ }
/* =============== G_ParseField Takes a key/value pair and sets the binary values in a gentity =============== */ void G_ParseField( const char *key, const char *rawString, gentity_t *entity ) { fieldDescriptor_t *fieldDescriptor; byte *entityDataField; vec4_t tmpFloatData; variatingTime_t varTime = {0, 0}; fieldDescriptor = bsearch( key, fields, ARRAY_LEN( fields ), sizeof( fieldDescriptor_t ), cmdcmp ); if ( !fieldDescriptor ) { return; } entityDataField = ( byte * ) entity + fieldDescriptor->offset; switch ( fieldDescriptor->type ) { case F_STRING: * ( char ** ) entityDataField = G_NewString( rawString ); break; case F_TARGET: if(entity->targetCount >= MAX_ENTITY_TARGETS) G_Error("Maximal number of %i targets reached.", MAX_ENTITY_TARGETS); ( ( char ** ) entityDataField ) [ entity->targetCount++ ] = G_NewString( rawString ); break; case F_CALLTARGET: if(entity->callTargetCount >= MAX_ENTITY_CALLTARGETS) G_Error("Maximal number of %i calltargets reached. You can solve this by using a Relay.", MAX_ENTITY_CALLTARGETS); ( ( gentityCallDefinition_t * ) entityDataField ) [ entity->callTargetCount++ ] = G_NewCallDefinition( fieldDescriptor->replacement ? fieldDescriptor->replacement : fieldDescriptor->name, rawString ); break; case F_TIME: sscanf( rawString, "%f %f", &varTime.time, &varTime.variance ); * ( variatingTime_t * ) entityDataField = varTime; break; case F_3D_VECTOR: sscanf( rawString, "%f %f %f", &tmpFloatData[ 0 ], &tmpFloatData[ 1 ], &tmpFloatData[ 2 ] ); ( ( float * ) entityDataField ) [ 0 ] = tmpFloatData[ 0 ]; ( ( float * ) entityDataField ) [ 1 ] = tmpFloatData[ 1 ]; ( ( float * ) entityDataField ) [ 2 ] = tmpFloatData[ 2 ]; break; case F_4D_VECTOR: sscanf( rawString, "%f %f %f %f", &tmpFloatData[ 0 ], &tmpFloatData[ 1 ], &tmpFloatData[ 2 ], &tmpFloatData[ 3 ] ); ( ( float * ) entityDataField ) [ 0 ] = tmpFloatData[ 0 ]; ( ( float * ) entityDataField ) [ 1 ] = tmpFloatData[ 1 ]; ( ( float * ) entityDataField ) [ 2 ] = tmpFloatData[ 2 ]; ( ( float * ) entityDataField ) [ 3 ] = tmpFloatData[ 3 ]; break; case F_INT: * ( int * ) entityDataField = atoi( rawString ); break; case F_FLOAT: * ( float * ) entityDataField = atof( rawString ); break; case F_YAW: ( ( float * ) entityDataField ) [ PITCH ] = 0; ( ( float * ) entityDataField ) [ YAW ] = atof( rawString ); ( ( float * ) entityDataField ) [ ROLL ] = 0; break; case F_SOUNDINDEX: if ( strlen( rawString ) >= MAX_QPATH ) { G_Error( S_ERROR "Sound filename %s in field %s of %s exceeds MAX_QPATH\n", rawString, fieldDescriptor->name, etos( entity ) ); } * ( int * ) entityDataField = G_SoundIndex( rawString ); break; default: G_Printf( S_ERROR "unknown datatype %i for field %s\n", fieldDescriptor->type, fieldDescriptor->name ); break; } if ( fieldDescriptor->replacement && fieldDescriptor->versionState ) G_WarnAboutDeprecatedEntityField(entity, fieldDescriptor->replacement, key, fieldDescriptor->versionState ); }
/* =================== Svcmd_EntityShow_f =================== */ void Svcmd_EntityShow_f() { int entityNum; int lastTargetIndex, targetIndex; gentity_t *selection; gentity_t *possibleTarget = nullptr; char argument[ 6 ]; if (trap_Argc() != 2) { G_Printf("usage: entityShow <entityId>\n"); return; } trap_Argv( 1, argument, sizeof( argument ) ); entityNum = atoi( argument ); if (entityNum >= level.num_entities || entityNum < MAX_CLIENTS) { G_Printf("entityId %d is out of range\n", entityNum); return; } selection = &g_entities[entityNum]; if (!selection->inuse) { G_Printf("entity slot %d is unused/free\n", entityNum); return; } G_Printf( "⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼\n" ); G_Printf( "^5#%3i^*: %16s", entityNum, Com_EntityTypeName( selection->s.eType ) ); if (IS_NON_NULL_VEC3(selection->s.origin)) { G_Printf("%26s", vtos( selection->s.origin ) ); } G_Printf( "\n⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼\n" ); G_Printf( "Classname: ^5%s^*\n", selection->classname ); G_Printf( "Capabilities:%s%s%s%s%s%s%s\n\n", selection->act ? " acts" : "", selection->think ? " thinks" : "", selection->pain ? " pains" : "", selection->die ? " dies" : "", selection->reset ? " resets" : "", selection->touch ? " touchable" : "", selection->use ? " usable" : ""); if (selection->names[0]) { G_Printf( "Names: "); G_PrintEntityNameList( selection ); } G_Printf("State: %s\n", selection->enabled ? "enabled" : "disabled"); if (selection->groupName) { G_Printf("Member of Group: %s%s\n", selection->groupName, !selection->groupMaster ? " [master]" : ""); } G_Printf( "\n"); if(selection->targetCount) { G_Printf( "Aims at\n"); while ((possibleTarget = G_IterateTargets(possibleTarget, &targetIndex, selection)) != nullptr ) { G_Printf(" • %s %s\n", etos( possibleTarget ), vtos( possibleTarget->s.origin)); } G_Printf( "\n"); } if(selection->callTargetCount) { lastTargetIndex = -1; while ((possibleTarget = G_IterateCallEndpoints(possibleTarget, &targetIndex, selection)) != nullptr ) { if(lastTargetIndex != targetIndex) { G_Printf("Calls %s \"%s:%s\"\n", selection->calltargets[ targetIndex ].event ? selection->calltargets[ targetIndex ].event : "onUnknown", selection->calltargets[ targetIndex ].name, selection->calltargets[ targetIndex ].action ? selection->calltargets[ targetIndex ].action : "default"); lastTargetIndex = targetIndex; } G_Printf(" • %s", etos(possibleTarget)); if(possibleTarget->names[1]) { G_Printf(" using \"%s\" ∈ ", selection->calltargets[ targetIndex ].name); G_PrintEntityNameList( possibleTarget ); } G_Printf("\n"); } } G_Printf( "\n" ); }
qboolean G_HandleEntityVersions( entityClassDescriptor_t *spawnDescription, gentity_t *entity ) { if ( spawnDescription->versionState == ENT_V_CURRENT ) // we don't need to handle anything return qtrue; if ( !spawnDescription->replacement || !Q_stricmp(entity->classname, spawnDescription->replacement)) { if ( g_debugEntities.integer > -2 ) G_Printf(S_ERROR "Class %s has been marked deprecated but no replacement has been supplied\n", etos( entity ) ); return qfalse; } if ( g_debugEntities.integer >= 0 ) //dont't warn about anything with -1 or lower { if( spawnDescription->versionState < ENT_V_TMPORARY || ( g_debugEntities.integer >= 1 && spawnDescription->versionState >= ENT_V_TMPORARY) ) { G_Printf( S_WARNING "Entity %s uses a deprecated classtype — use the class " S_COLOR_CYAN "%s" S_COLOR_WHITE " instead\n", etos( entity ), spawnDescription->replacement ); } } entity->classname = spawnDescription->replacement; return qtrue; }
void trigger_multiple_compat_reset( gentity_t *self ) { if (!!( self->spawnflags & 1 ) != !!( self->spawnflags & 2 )) //if both are set or none are set we assume TEAM_ALL { if ( self->spawnflags & 1 ) self->conditions.team = TEAM_HUMANS; else if ( self->spawnflags & 2 ) self->conditions.team = TEAM_ALIENS; } if ( self->spawnflags && g_debugEntities.integer >= -1 ) //dont't warn about anything with -1 or lower { G_Printf( S_ERROR "It appears as if %s has set spawnflags that were not defined behavior of the entities.def; this is likely to break in the future\n", etos( self )); } }
inline string list_gets(list_t lst, uint32 index) { return etos(lst.data[index]); }
//some old sensors/triggers used to propagate use-events, this is deprecated behavior void trigger_compat_propagation_act( gentity_t *self, gentity_t *other, gentity_t *activator ) { G_FireEntity( self, self ); if ( g_debugEntities.integer >= -1 ) //dont't warn about anything with -1 or lower { G_Printf( S_ERROR "It appears as if %s is targeted by %s to enforce firing, which is undefined behavior — stop doing that! This WILL break in future releases and toggle the sensor instead.\n", etos( self ), etos( activator ) ); } }
/** * @brief Called whenever an entity changes origin, mins, maxs, or solid to add it to * the clipping hull. */ void Sv_LinkEntity(g_entity_t *ent) { int32_t leafs[MAX_ENT_LEAFS]; int32_t clusters[MAX_ENT_LEAFS]; size_t i, j; int32_t top_node; if (ent == svs.game->entities) { // never bother with the world return; } // remove it from its current sector Sv_UnlinkEntity(ent); if (!ent->in_use) { // and if its free, we're done return; } // set the size VectorSubtract(ent->maxs, ent->mins, ent->size); // encode the size into the entity state for client prediction ent->s.solid = ent->solid; switch (ent->s.solid) { case SOLID_TRIGGER: case SOLID_PROJECTILE: case SOLID_DEAD: case SOLID_BOX: PackBounds(ent->mins, ent->maxs, &ent->s.bounds); break; default: PackBounds(vec3_origin, vec3_origin, &ent->s.bounds); break; } // set the absolute bounding box; ensure it is symmetrical Cm_EntityBounds(ent->solid, ent->s.origin, ent->s.angles, ent->mins, ent->maxs, ent->abs_mins, ent->abs_maxs); sv_entity_t *sent = &sv.entities[NUM_FOR_ENTITY(ent)]; // link to PVS leafs sent->num_clusters = 0; sent->areas[0] = sent->areas[1] = 0; // get all leafs, including solids const size_t len = Cm_BoxLeafnums(ent->abs_mins, ent->abs_maxs, leafs, lengthof(leafs), &top_node, 0); // set areas, allowing entities (doors) to occupy up to two for (i = 0; i < len; i++) { clusters[i] = Cm_LeafCluster(leafs[i]); const int32_t area = Cm_LeafArea(leafs[i]); if (area) { if (sent->areas[0] && sent->areas[0] != area) { if (sent->areas[1] && sent->areas[1] != area && sv.state == SV_LOADING) { Com_Warn("Object touching 3 areas at %s\n", vtos(ent->abs_mins)); } sent->areas[1] = area; } else { sent->areas[0] = area; } } } if (len == MAX_ENT_LEAFS) { // use top_node sent->num_clusters = -1; sent->top_node = top_node; } else { sent->num_clusters = 0; for (i = 0; i < len; i++) { if (clusters[i] == -1) { continue; // not a visible leaf } for (j = 0; j < i; j++) if (clusters[j] == clusters[i]) { break; } if (j == i) { if (sent->num_clusters == MAX_ENT_CLUSTERS) { // use top_node Com_Debug(DEBUG_SERVER, "%s exceeds MAX_ENT_CLUSTERS\n", etos(ent)); sent->num_clusters = -1; sent->top_node = top_node; break; } sent->clusters[sent->num_clusters++] = clusters[i]; } } } if (ent->solid == SOLID_NOT) { return; } // find the first sector that the ent's box crosses sv_sector_t *sector = sv_world.sectors; while (true) { if (sector->axis == -1) { break; } if (ent->abs_mins[sector->axis] > sector->dist) { sector = sector->children[0]; } else if (ent->abs_maxs[sector->axis] < sector->dist) { sector = sector->children[1]; } else { break; // crosses the node } } // add it to the sector sent->sector = sector; sector->entities = g_list_prepend(sector->entities, ent); // and update its clipping matrices const vec_t *angles = ent->solid == SOLID_BSP ? ent->s.angles : vec3_origin; Matrix4x4_CreateFromEntity(&sent->matrix, ent->s.origin, angles, 1.0); Matrix4x4_Invert_Simple(&sent->inverse_matrix, &sent->matrix); }