Thread: /rewind
View Single Post
  #2  
Old 04-21-2008, 01:35 PM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

I didn't think about the fact that many people aren't running the stock eqemu source, and that generated patch diffs might not be the best way for them to update their sources. With that said, here's a manual context diff. Just go through and add the red lines into your source, and you should be good to go.

Also, to clarify, this update gives functionality to the client /rewind feature. This command / feature was added to the client by Sony due to the collision issues (i.e. players getting stuck on trees and ladders, etc). This will allow players to "unstick" themselves if they are trapped in geometry without the need for GM assistance.

Without further delay, here is the code (note: this is the same code as my previous post - just in an easier to read format, for ServerOps that want to manually update their source):

patch_Titanium.conf (in your eqemu directory)

Code:
OP_LDoNButton=0x0000
OP_MoveCoin=0x7657
OP_ReloadUI=0x0000
OP_ZonePlayerToBind=0x385e		# FNW Discovered on Feb 9, 2007
OP_Rewind=0x4cfa				# Lieka: /rewind command

#bazaar trader stuff stuff:
#become and buy from
./common/emu_oplist.h

Code:
N(OP_Command),
N(OP_MailboxHeader),
N(OP_MailHeader),
N(OP_MailBody),
N(OP_NewMail),
N(OP_SentConfirm),
N(OP_ZonePlayerToBind),
N(OP_AutoFire),
N(OP_Rewind),

./zone/mob.h

Code:
	bool DivineAura() const;
    bool SpecAttacks[SPECATK_MAXNUM];
	Shielders_Struct shielder[MAX_SHIELDERS];
	Trade* trade;
	
	//temporary:
	bool fix_pathing;
	float rewind_x; //Lieka:  Used for storing /rewind values
	float rewind_y; //Lieka:  Used for storing /rewind values
	float rewind_z; //Lieka:  Used for storing /rewind values
	Timer rewind_timer; //Lieka:  Used for measuring how long a player stays in one spot
	inline float GetCWPX() const { return(cur_wp_x); }
	inline float GetCWPY() const { return(cur_wp_y); }
	inline float GetCWPZ() const { return(cur_wp_z); }
	inline float GetCWPP() const { return(cur_wp_pause); }
	inline int GetCWP() const { return(cur_wp); }
	virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }

./zone/client_packet.h

Code:
	void Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app);
	void Handle_OP_Ignore(const EQApplicationPacket *app);
	void Handle_OP_LoadSpellSet(const EQApplicationPacket *app);
	void Handle_OP_AutoFire(const EQApplicationPacket *app);
	void Handle_OP_Rewind(const EQApplicationPacket *app);
./zone/client.h

Code:
typedef enum {
	ZoneToSafeCoords,		// Always send ZonePlayerToBind_Struct to client: Succor/Evac
	GMSummon,				// Always send ZonePlayerToBind_Struct to client: Only a GM Summon
	ZoneToBindPoint,		// Always send ZonePlayerToBind_Struct to client: Death Only
	ZoneSolicited,			// Always send ZonePlayerToBind_Struct to client: Portal, Translocate, Evac spells that have a x y z coord in the spell data
	ZoneUnsolicited,
	GateToBindPoint,		// Always send RequestClientZoneChange_Struct to client: Gate spell or Translocate To Bind Point spell
	SummonPC,				// In-zone GMMove() always: Call of the Hero spell or some other type of in zone only summons
	Rewind,					// Lieka:  Summon to /rewind location.
	EvacToSafeCoords
} ZoneMode;
./zone/zoning.cpp

Code:
		case ZoneToBindPoint:
			ZonePC(zoneID, x, y, z, heading, ignorerestrictions, zm);
			break;
		case ZoneSolicited:
			ZonePC(zoneID, x, y, z, heading, ignorerestrictions, zm);
			break;
		case SummonPC:
			Message(15, "You have been summoned!");
			ZonePC(zoneID, x, y, z, heading, ignorerestrictions, zm);
			break;
		case Rewind:
			Message(15, "Rewinding to previous location.");
			ZonePC(zoneID, x, y, z, heading, ignorerestrictions, zm);
			break;
		default:
			LogFile->write(EQEMuLog::Error, "Client::ProcessMovePC received a reguest to perform an unsupported client zone operation.");
			break;
	}
}
Code:
		case ZoneToBindPoint:
			x = x_pos = m_pp.binds[0].x;
			y = y_pos = m_pp.binds[0].y;
			z = z_pos = m_pp.binds[0].z;
			heading = m_pp.binds[0].heading;
			
			zonesummon_ignorerestrictions = 1;
			LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
			break;
		case SummonPC:
			this->cheat_timer.Start(2500,false);
			zonesummon_x = x_pos = x;
			zonesummon_y = y_pos = y;
			zonesummon_z = z_pos = z;
			heading = heading;
			break;
		case Rewind:
			LogFile->write(EQEMuLog::Debug, "%s has requested a /rewind from %f, %f, %f, to %f, %f, %f in %s", GetName(), x_pos, y_pos, z_pos, rewind_x, rewind_y, rewind_z, zone->GetShortName());
			zonesummon_x = x_pos = x;
			zonesummon_y = y_pos = y;
			zonesummon_z = z_pos = z;
			heading = heading;
			break;
		default:
			LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
			ReadyToZone = false;
			break;
	}

./zone/mob.cpp

Code:
		tic_timer(6000),
		mana_timer(2000),
		spellend_timer(0),
		rewind_timer(30000), //Lieka:  Timer used for determining amount of time between actual player position updates for /rewind.
		stunned_timer(0),
		bardsong_timer(6000),
#ifdef FLEE_HP_RATIO
		flee_timer(FLEE_CHECK_TIMER),
#endif
		bindwound_timer(10000)
Code:
	tarx=0;
	tary=0;
	tarz=0;
	AI_Init();
	SetMoving(false);
	moved=false;
	rewind_x = 0;
	rewind_y = 0;
	rewind_z = 0;
	_egnode = NULL;
	adverrorinfo = 0;
	name[0]=0;
	clean_name[0]=0;
	lastname[0]=0;
./zone/client_packet.cpp

Code:
	ConnectedOpcodes[OP_FloatListThing] = &Client::Handle_OP_Ignore;
	ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore;
	ConnectedOpcodes[OP_LoadSpellSet] = &Client::Handle_OP_LoadSpellSet;
	ConnectedOpcodes[OP_AutoFire] = &Client::Handle_OP_AutoFire;
	ConnectedOpcodes[OP_Rewind] = &Client::Handle_OP_Rewind;

	
}
Code:
printf("%s: Large position change: %f units\n", GetName(), sqrtf(dist));
		printf("Coords: (%.4f, %.4f, %.4f) -> (%.4f, %.4f, %.4f)\n",
			x_pos, y_pos, z_pos, ppu->x_pos, ppu->y_pos, ppu->z_pos);
		printf("Deltas: (%.2f, %.2f, %.2f) -> (%.2f, %.2f, %.2f)\n",
			delta_x, delta_y, delta_z, ppu->delta_x, ppu->delta_y, ppu->delta_z);
	}

	//Lieka:  Check to see if PPU should trigger an update to the rewind position.
	float rewind_x_diff = 0;
	float rewind_y_diff = 0;
	float rewind_z_diff = 0;

	rewind_x_diff = ppu->x_pos - rewind_x;
	rewind_x_diff *= rewind_x_diff;
	rewind_y_diff = ppu->y_pos - rewind_y;
	rewind_y_diff *= rewind_y_diff;

	//Lieka:  We only need to store updated values if the player has moved.
	//If the player has moved more than  units for x or y, then we'll store
	//his pre-PPU x and y for /rewind, in case he gets stuck.
	if ((rewind_x_diff > 750) || (rewind_y_diff > 750)) { 
		rewind_x = x_pos;
		rewind_y = y_pos;
		rewind_z = z_pos;	
	}

	//Lieka:  If the PPU was a large jump, such as a cross zone gate or Call of Hero, 
	//just update rewind coords to the new ppu coords.  This will prevent exploitation.

	if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000)) { 
		rewind_x = ppu->x_pos;
		rewind_y = ppu->y_pos;
		rewind_z = ppu->z_pos;	
	}

	// solar: a very low chance to improve at sense heading, since
Code:
			sa_out->type = 0x03;
			sa_out->parameter = 0;
			entity_list.QueueClients(this, outapp, true);
			safe_delete(outapp);
			rewind_timer.Start(30000, true);
		}
	}
Code:
void Client::Handle_OP_BankerChange(const EQApplicationPacket *app)
{
	if(app->size != sizeof(BankerChange_Struct) && app->size!=4) // cb: Titanium only sends 4 Bytes for this
	{

		LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_BankerChange expected %i got %i", sizeof(BankerChange_Struct), app->size);
		DumpPacket(app);
		return;
	}
	
	EQApplicationPacket *outapp=new EQApplicationPacket(OP_BankerChange,NULL,sizeof(BankerChange_Struct));
	BankerChange_Struct *bc=(BankerChange_Struct *)outapp->pBuffer;
	uint32 cp=m_pp.copper+(m_pp.silver*10)+(m_pp.gold*100)+(m_pp.platinum*1000);
	m_pp.copper=cp%10;
	cp/=10;
	m_pp.silver=cp%10;
	cp/=10;
	m_pp.gold=cp%10;
	cp/=10;
	m_pp.platinum=cp;

	cp=m_pp.copper_bank+(m_pp.silver_bank*10)+(m_pp.gold_bank*100)+(m_pp.platinum_bank*1000);
	m_pp.copper_bank=cp%10;
	cp/=10;
	m_pp.silver_bank=cp%10;
	cp/=10;
	m_pp.gold_bank=cp%10;
	cp/=10;
	m_pp.platinum_bank=cp;

	bc->copper=m_pp.copper;
	bc->silver=m_pp.silver;
	bc->gold=m_pp.gold;
	bc->platinum=m_pp.platinum;

	bc->copper_bank=m_pp.copper_bank;
	bc->silver_bank=m_pp.silver_bank;
	bc->gold_bank=m_pp.gold_bank;
	bc->platinum_bank=m_pp.platinum_bank;

	FastQueuePacket(&outapp);

	return;
}

void Client::Handle_OP_AutoFire(const EQApplicationPacket *app)
{
	if(app->size != sizeof(bool)) {
		LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_AutoFire expected %i got %i", sizeof(bool), app->size);
		DumpPacket(app);
		return;
	}
	bool *af = (bool*)app->pBuffer;
	auto_fire = *af;
	SetAttackTimer();
}

void Client::Handle_OP_Rewind(const EQApplicationPacket *app)
{
	if ((rewind_timer.GetRemainingTime() > 1 && rewind_timer.Enabled())) {
			Message_StringID(MT_System, 4059); //You must wait a bit longer before using the rewind command again. 
	} else {
		CastToClient()->MovePC(zone->GetZoneID(), rewind_x, rewind_y, rewind_z, 0, 2, Rewind);	
		rewind_timer.Start(30000, true);
	}
}
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)
Reply With Quote