Esempio n. 1
0
void SpawnConditionManager::ReloadEvent(uint32 event_id) {
	string zone_short_name;
	
	_log(SPAWNS__CONDITIONS, "Requested to reload event %d from the database.", event_id);
	
	//first look for the event in our local event list
	vector<SpawnEvent>::iterator cur,end;
	cur = spawn_events.begin();
	end = spawn_events.end();
	for(; cur != end; cur++) {
		SpawnEvent &cevent = *cur;
		
		if(cevent.id == event_id) {
			//load the event into the old event slot
			if(!LoadDBEvent(event_id, cevent, zone_short_name)) {
				//unable to find the event in the database...
				_log(SPAWNS__CONDITIONS, "Failed to reload event %d from the database.", event_id);
				return;
			}
			//sync up our nearest event
			FindNearestEvent();
			return;
		}
	}
	
	//if we get here, it is a new event...
	SpawnEvent e;
	if(!LoadDBEvent(event_id, e, zone_short_name)) {
		//unable to find the event in the database...
		_log(SPAWNS__CONDITIONS, "Failed to reload event %d from the database.", event_id);
		return;
	}
	
	//we might want to check the next timer like we do on
	//regular load events, but we are assuming this is a new event
	//and anyways, this will get handled (albeit not optimally)
	//naturally by the event handling code.
	
	spawn_events.push_back(e);
	
	//sync up our nearest event
	FindNearestEvent();
}
Esempio n. 2
0
void SpawnConditionManager::Process() {
	if(spawn_events.empty())
		return;

	if(minute_timer.Check()) {
		//check each spawn event.

		//get our current time
		TimeOfDay_Struct tod;
		zone->zone_time.GetCurrentEQTimeOfDay(&tod);

		//see if time is past our nearest event.
		if(EQTime::IsTimeBefore(&next_event, &tod))
			return;

		//at least one event should get triggered,
		std::vector<SpawnEvent>::iterator cur,end;
		cur = spawn_events.begin();
		end = spawn_events.end();
		for(; cur != end; ++cur) {
			SpawnEvent &cevent = *cur;

			if(cevent.enabled)
			{
				if(EQTime::IsTimeBefore(&tod, &cevent.next)) {
					//this event has been triggered.
					//execute the event
					if(!cevent.strict || (cevent.strict && cevent.next.hour == tod.hour && cevent.next.day == tod.day && cevent.next.month == tod.month && cevent.next.year == tod.year))
						ExecEvent(cevent, true);

					//add the period of the event to the trigger time
					EQTime::AddMinutes(cevent.period, &cevent.next);
					std::string t;
					EQTime::ToString(&cevent.next, t);
					Log(Logs::Detail, Logs::Spawns, "Event %d: Will trigger again in %d EQ minutes at %s.", cevent.id, cevent.period, t.c_str());
					//save the next event time in the DB
					UpdateDBEvent(cevent);
					//find the next closest event timer.
					FindNearestEvent();
					//minor optimization, if theres no more possible events,
					//then stop trying... I dunno how worth while this is.
					if(EQTime::IsTimeBefore(&next_event, &tod))
						return;
				}
			}
		}
	}
}
Esempio n. 3
0
bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 instance_id) 
{
	char errbuf[MYSQL_ERRMSG_SIZE];
	char* query = 0;
	MYSQL_RES *result;
	MYSQL_ROW row;
	int len;
	
	//clear out old stuff..
	spawn_conditions.clear();
	
	//load spawn conditions	
	SpawnCondition cond;
	len = MakeAnyLenString(&query, "SELECT id, onchange, value FROM spawn_conditions WHERE zone='%s'", zone_name);
	if (database.RunQuery(query, len, errbuf, &result)) {
		safe_delete_array(query);
		while((row = mysql_fetch_row(result))) {
			cond.condition_id = atoi(row[0]);
			cond.value = atoi(row[2]);
			cond.on_change = (SpawnCondition::OnChange) atoi(row[1]);
			spawn_conditions[cond.condition_id] = cond;
			
			_log(SPAWNS__CONDITIONS, "Loaded spawn condition %d with value %d and on_change %d", cond.condition_id, cond.value, cond.on_change);
		}
		mysql_free_result(result);
	} else {
		LogFile->write(EQEMuLog::Error, "Error in LoadSpawnConditions query '%s': %s", query, errbuf);
		safe_delete_array(query);
		return false;
	}

	//load values
	len = MakeAnyLenString(&query, "SELECT id, value FROM spawn_condition_values WHERE zone='%s' and instance_id=%u", zone_name, instance_id);
	if (database.RunQuery(query, len, errbuf, &result)) {
		safe_delete_array(query);
		while((row = mysql_fetch_row(result))) 
		{			
			std::map<uint16, SpawnCondition>::iterator iter = spawn_conditions.find(atoi(row[0]));
			if(iter != spawn_conditions.end())
			{
				iter->second.value = atoi(row[1]);
			}
		}
		mysql_free_result(result);
	} 
	else 
	{
		LogFile->write(EQEMuLog::Error, "Error in LoadSpawnConditions query '%s': %s", query, errbuf);
		safe_delete_array(query);
		spawn_conditions.clear();
		return false;
	}
	
	//load spawn events
	SpawnEvent event;
	len = MakeAnyLenString(&query, 
	"SELECT id,cond_id,period,next_minute,next_hour,next_day,next_month,next_year,enabled,action,argument "
	"FROM spawn_events WHERE zone='%s'", zone_name);
	if (database.RunQuery(query, len, errbuf, &result)) {
		safe_delete_array(query);
		while((row = mysql_fetch_row(result))) {
			event.id = atoi(row[0]);
			event.condition_id = atoi(row[1]);
			event.period = atoi(row[2]);
			if(event.period == 0) {
				LogFile->write(EQEMuLog::Error, "Refusing to load spawn event #%d because it has a period of 0\n", event.id);
				continue;
			}
			
			event.next.minute = atoi(row[3]);
			event.next.hour = atoi(row[4]);
			event.next.day = atoi(row[5]);
			event.next.month = atoi(row[6]);
			event.next.year = atoi(row[7]);
			
			event.enabled = atoi(row[8])==0?false:true;
			event.action = (SpawnEvent::Action) atoi(row[9]);
			event.argument = atoi(row[10]);
			spawn_events.push_back(event);
			
			_log(SPAWNS__CONDITIONS, "Loaded %s spawn event %d on condition %d with period %d, action %d, argument %d",
				event.enabled?"enabled":"disabled", event.id, event.condition_id, event.period, event.action, event.argument);
		}
		mysql_free_result(result);
	} else {
		LogFile->write(EQEMuLog::Error, "Error in LoadSpawnConditions events query '%s': %s", query, errbuf);
		safe_delete_array(query);
		return false;
	}
	
	//now we need to catch up on events that happened  while we were away
	//and use them to alter just the condition variables.
	
	//each spawn2 will then use its correct condition value when
	//it decides what to do. This essentially forces a 'depop' action
	//on spawn points which are turned off, and a 'repop' action on
	//spawn points which get turned on. Im too lazy to figure out a
	//better solution, and I just dont care thats much.
	//get our current time
	TimeOfDay_Struct tod;
	zone->zone_time.getEQTimeOfDay(&tod);
	
	vector<SpawnEvent>::iterator cur,end;
	cur = spawn_events.begin();
	end = spawn_events.end();
	bool ran;
	for(; cur != end; cur++) {
		SpawnEvent &cevent = *cur;
		
		if(!cevent.enabled)
			continue;
		
		//watch for special case of all 0s, which means to reset next to now
		if(cevent.next.year == 0 && cevent.next.month == 0 && cevent.next.day == 0 && cevent.next.hour == 0 && cevent.next.minute == 0) {
			_log(SPAWNS__CONDITIONS, "Initial next trigger time set for spawn event %d", cevent.id);
			memcpy(&cevent.next, &tod, sizeof(cevent.next));
			//add one period
			EQTime::AddMinutes(cevent.period, &cevent.next);
			//save it in the db.
			UpdateDBEvent(cevent);
			continue;	//were done with this event.
		}
		
		ran = false;
		while(EQTime::IsTimeBefore(&tod, &cevent.next)) {
			_log(SPAWNS__CONDITIONS, "Catch up triggering on event %d", cevent.id);
			//this event has been triggered.
			//execute the event
			ExecEvent(cevent, false);
			//add the period of the event to the trigger time
			EQTime::AddMinutes(cevent.period, &cevent.next);
			ran = true;
		}
		//only write it out if the event actually ran
		if(ran) {
			//save the event in the DB
			UpdateDBEvent(cevent);
		}
	}
	
	//now our event timers are all up to date, find our closest event.
	FindNearestEvent();
	
	return(true);
}
Esempio n. 4
0
void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool reset_base) {
	
	_log(SPAWNS__CONDITIONS, "Request to %s spawn event %d %sresetting trigger time", enabled?"enable":"disable", event_id, reset_base?"":"without ");
	
	//first look for the event in our local event list
	vector<SpawnEvent>::iterator cur,end;
	cur = spawn_events.begin();
	end = spawn_events.end();
	for(; cur != end; cur++) {
		SpawnEvent &cevent = *cur;
		
		if(cevent.id == event_id) {
			//make sure were actually changing something
			if(cevent.enabled != enabled || reset_base) {
				cevent.enabled = enabled;
				if(reset_base) {
					_log(SPAWNS__CONDITIONS, "Spawn event %d located in this zone. State set. Trigger time reset (period %d).", event_id, cevent.period);
					//start with the time now
					zone->zone_time.getEQTimeOfDay(&cevent.next);
					//advance the next time by our period
					EQTime::AddMinutes(cevent.period, &cevent.next);
				} else {
					_log(SPAWNS__CONDITIONS, "Spawn event %d located in this zone. State changed.", event_id);
				}
				
				//save the event in the DB
				UpdateDBEvent(cevent);
				
				//sync up our nearest event
				FindNearestEvent();
			} else {
				_log(SPAWNS__CONDITIONS, "Spawn event %d located in this zone but no change was needed.", event_id);
			}
			//even if we dont change anything, we still found it
			return;
		}
	}
	
	//if we get here, the condition must be in another zone.
	//first figure out what zone it applies to.
	//update the DB and send and send an update packet to 
	//the zone if its up
	
	//we need to load the event from the DB and then update 
	//the values in the DB, because we do not know if the zone
	//is up or not. The message to the zone will just tell it to
	//update its in-memory event list
	SpawnEvent e;
	string zone_short_name;
	if(!LoadDBEvent(event_id, e, zone_short_name)) {
		_log(SPAWNS__CONDITIONS, "Unable to find spawn event %d in the database.", event_id);
		//unable to find the event in the database...
		return;
	}
	if(e.enabled == enabled && !reset_base) {
		_log(SPAWNS__CONDITIONS, "Spawn event %d is not located in this zone but no change was needed.", event_id);
		return;	//no changes.
	}
	
	e.enabled = enabled;
	if(reset_base) {
		_log(SPAWNS__CONDITIONS, "Spawn event %d is in zone %s. State set. Trigger time reset (period %d). Notifying world.", event_id, zone_short_name.c_str(), e.period);
		//start with the time now
		zone->zone_time.getEQTimeOfDay(&e.next);
		//advance the next time by our period
		EQTime::AddMinutes(e.period, &e.next);
	} else {
		_log(SPAWNS__CONDITIONS, "Spawn event %d is in zone %s. State changed.  Notifying world.", event_id, zone_short_name.c_str(), e.period);
	}
	//save the event in the DB
	UpdateDBEvent(e);
	
	
	//now notify the zone
	ServerPacket* pack = new ServerPacket(ServerOP_SpawnEvent, sizeof(ServerSpawnEvent_Struct));
	ServerSpawnEvent_Struct* sse = (ServerSpawnEvent_Struct*)pack->pBuffer;
	
	sse->zoneID = database.GetZoneID(zone_short_name.c_str());
	sse->event_id = event_id;
	
	worldserver.SendPacket(pack);
	safe_delete(pack);
}
Esempio n. 5
0
bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 instance_id)
{
	//clear out old stuff..
	spawn_conditions.clear();

	std::string query = StringFormat("SELECT id, onchange, value "
                                    "FROM spawn_conditions "
                                    "WHERE zone = '%s'", zone_name);
    auto results = database.QueryDatabase(query);
    if (!results.Success()) {
		return false;
    }

    for (auto row = results.begin(); row != results.end(); ++row) {
        //load spawn conditions
        SpawnCondition cond;

        cond.condition_id = atoi(row[0]);
        cond.value = atoi(row[2]);
        cond.on_change = (SpawnCondition::OnChange) atoi(row[1]);
        spawn_conditions[cond.condition_id] = cond;

        Log(Logs::Detail, Logs::Spawns, "Loaded spawn condition %d with value %d and on_change %d", cond.condition_id, cond.value, cond.on_change);
    }

	//load values
	query = StringFormat("SELECT id, value FROM spawn_condition_values "
                        "WHERE zone = '%s' AND instance_id = %u",
                        zone_name, instance_id);
    results = database.QueryDatabase(query);
    if (!results.Success()) {
		spawn_conditions.clear();
		return false;
    }

    for (auto row = results.begin(); row != results.end(); ++row) {
        auto iter = spawn_conditions.find(atoi(row[0]));

        if(iter != spawn_conditions.end())
            iter->second.value = atoi(row[1]);
    }

	//load spawn events
    query = StringFormat("SELECT id, cond_id, period, next_minute, next_hour, "
                        "next_day, next_month, next_year, enabled, action, argument, strict "
                        "FROM spawn_events WHERE zone = '%s'", zone_name);
    results = database.QueryDatabase(query);
    if (!results.Success()) {
		return false;
    }

    for (auto row = results.begin(); row != results.end(); ++row) {
        SpawnEvent event;

        event.id = atoi(row[0]);
        event.condition_id = atoi(row[1]);
        event.period = atoi(row[2]);

        if(event.period == 0) {
            Log(Logs::General, Logs::Error, "Refusing to load spawn event #%d because it has a period of 0\n", event.id);
            continue;
        }

        event.next.minute = atoi(row[3]);
        event.next.hour = atoi(row[4]);
        event.next.day = atoi(row[5]);
        event.next.month = atoi(row[6]);
        event.next.year = atoi(row[7]);

        event.enabled = atoi(row[8])==0?false:true;
        event.action = (SpawnEvent::Action) atoi(row[9]);
        event.argument = atoi(row[10]);
        event.strict = atoi(row[11])==0?false:true;

        spawn_events.push_back(event);

        Log(Logs::Detail, Logs::Spawns, "(LoadSpawnConditions) Loaded %s spawn event %d on condition %d with period %d, action %d, argument %d, strict %d", event.enabled? "enabled": "disabled", event.id, event.condition_id, event.period, event.action, event.argument, event.strict);
    }

	//now we need to catch up on events that happened while we were away
	//and use them to alter just the condition variables.

	//each spawn2 will then use its correct condition value when
	//it decides what to do. This essentially forces a 'depop' action
	//on spawn points which are turned off, and a 'repop' action on
	//spawn points which get turned on. Im too lazy to figure out a
	//better solution, and I just dont care thats much.
	//get our current time
	TimeOfDay_Struct tod;
	zone->zone_time.GetCurrentEQTimeOfDay(&tod);

	for(auto cur = spawn_events.begin(); cur != spawn_events.end(); ++cur) {
		SpawnEvent &cevent = *cur;

		bool StrictCheck = false;
		if(cevent.strict &&
			cevent.next.hour == tod.hour &&
			cevent.next.day == tod.day &&
			cevent.next.month == tod.month &&
			cevent.next.year == tod.year)
			StrictCheck = true;

		//If event is disabled, or we failed the strict check, set initial spawn_condition to 0.
		if(!cevent.enabled || !StrictCheck)
			SetCondition(zone->GetShortName(), zone->GetInstanceID(),cevent.condition_id,0);

		if(!cevent.enabled)
            continue;

        //watch for special case of all 0s, which means to reset next to now
        if(cevent.next.year == 0 && cevent.next.month == 0 && cevent.next.day == 0 && cevent.next.hour == 0 && cevent.next.minute == 0) {
            Log(Logs::Detail, Logs::Spawns, "Initial next trigger time set for spawn event %d", cevent.id);
            memcpy(&cevent.next, &tod, sizeof(cevent.next));
            //add one period
            EQTime::AddMinutes(cevent.period, &cevent.next);
            //save it in the db.
            UpdateDBEvent(cevent);
            continue;	//were done with this event.
        }

        bool ran = false;
        while(EQTime::IsTimeBefore(&tod, &cevent.next)) {
            Log(Logs::Detail, Logs::Spawns, "Catch up triggering on event %d", cevent.id);
            //this event has been triggered.
            //execute the event
            if(!cevent.strict || StrictCheck)
                ExecEvent(cevent, false);

            //add the period of the event to the trigger time
            EQTime::AddMinutes(cevent.period, &cevent.next);
            ran = true;
        }

        //only write it out if the event actually ran
        if(ran)
            UpdateDBEvent(cevent); //save the event in the DB
	}

	//now our event timers are all up to date, find our closest event.
	FindNearestEvent();

	return true;
}