ArcEmu: Mirror Image Workshop - ArcEmu

Jump to content

Toggle shoutbox Lastest Announcements

dfighter  : (07 December 2014 - 12:06 PM) Arcemu is in hibernation mode, please read http://arcemu.org/fo...showtopic=26903
dfighter  : (01 January 2013 - 05:56 PM) Arcemu wishes you all a happy new year!
Hasbro  : (12 September 2012 - 10:01 AM) Please excuse our outage from the web! Our web host had a major malfunction!
dfighter  : (01 September 2012 - 04:05 PM) Since the spam bots just don't want to stop, I've enabled admin verification when registering.
dfighter  : (23 January 2012 - 09:56 PM) Please note that from now on you will need to confirm your email on the wiki in order to edit it!
Hasbro  : (31 December 2011 - 12:50 PM) Happy New Years all!
Navid  : (26 December 2011 - 04:09 AM) Merry Christmas !!!!!! Happy holidays all :)
WAmadeus  : (24 December 2011 - 03:54 PM) Merry Christmas to all!
dfighter  : (24 December 2011 - 11:05 AM) The Arcemu team wishes y'all a Merry Christmukkah!
Hasbro  : (05 October 2011 - 12:53 PM) Looking for web designers for upcoming web related project. If you're interested in designing user interfaces contact me
dfighter  : (02 September 2011 - 03:47 PM) So who here wants vehicles in Arcemu? :P http://arcemu.org/fo...showtopic=25440
Hasbro  : (14 August 2011 - 03:25 PM) Join us on irc, grab an irc client and connect to irc.freenode.net join channel #arcemu /server irc.freenode.net:6667 /join #arcemu
jackpoz  : (03 August 2011 - 05:33 AM) to all Lua Engine (old one) users: please check http://arcemu.org/fo...showtopic=25274
Hasbro  : (20 May 2011 - 05:27 PM) Looking for people experienced with CMake configuration and setup! Contact me asap
Hasbro  : (15 May 2011 - 05:03 PM) ArcEmu is recruiting C++ programmers, contact Hasbro if interested.
paroxysm  : (03 May 2011 - 06:26 PM) Updated luabridge gossip example to describe the whole gossip creation process rather than just how to create menu. Gossip tutorial
paroxysm  : (23 April 2011 - 11:35 AM) Lua writers can refer to the Luabridge Tutorials section in the Wiki to learn how to write gossip code correctly.
Hasbro  : (20 April 2011 - 05:22 PM) Thank you for your continuous contribution of bug reports, we are working on them.
Hasbro  : (17 April 2011 - 03:20 AM) Please consider donating to support our bills. Donations can be sent using PayPal to donations@arcemu.org - Thank you for your support.
paroxysm  : (10 April 2011 - 12:43 AM) Refer to the Luabridge Tutorials section in the Wiki to learn the new syntax of luabridge.
Resize Shouts Area

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Mirror Image Workshop

#1 User is offline   dfighter 

  • Titles are overrated
  • PipPipPipPipPipPipPipPipPipPip
  • Group: Administrator
  • Posts: 5,189
  • Joined: 14-June 08
  • IRC:dfighter
  • Gender:Male
  • Server OS:Linux

Posted 08 June 2010 - 12:39 PM

So I got curious about this thingie and I wanted to have fun with it, but I couldn't implement it properly due to my lack of spell knowledge, and the fact that I have no idea why the hell the images won't change their name (display is fine).
Thanks a bunch to those who (tried) to help me Andy, Elenion, Kekers, and TrinityCore too ofc as I had to take a look at their implementation.

TODO:
Implement the scripted targeting for the spells involved.
Implement the periodic trigger dummy spells involved.
Implement the threat inheritance of images.
Implement AI for the images.
Get the right formula for images' hp and mana.


http://www.wowhead.com/spell=45204
http://www.wowhead.com/spell=58836
http://www.wowhead.com/spell=58838


WARNING: It is full of hacks because I wanted to get it to show up the name first before moving on so I took hacking as a shortcut!
Those will have to be removed and implemented right, obviously ;)

At the moment it will spawn 3 images at the same place and set their displayid. They can also fight but with melee only but hit small.

Index: src/arcemu-world/HackFixes.cpp
===================================================================
--- src/arcemu-world/HackFixes.cpp	(revision 3395)
+++ src/arcemu-world/HackFixes.cpp	(working copy)
@@ -4830,6 +4830,11 @@
 
 	// Insert mage spell fixes here
 
+		// initialize images
+		sp = dbcSpell.LookupEntry( 58836 );
+		if( sp != NULL )
+			sp->EffectImplicitTargetA[ 0 ] = 32;
+
 		//Missile Barrage
 		sp = dbcSpell.LookupEntryForced( 44404 );
 	if( sp != NULL )
Index: src/arcemu-world/Spell.h
===================================================================
--- src/arcemu-world/Spell.h	(revision 3395)
+++ src/arcemu-world/Spell.h	(working copy)
@@ -1895,7 +1895,7 @@
 	void SpellEffectRestoreHealthPct(uint32 i);
 	void SpellEffectLearnSpec(uint32 i);
 	void SpellEffectActivateSpec(uint32 i);
-//	void SpellEffectActivateRune(uint32 i);
+	void SummonMirrorImage( uint32 i );
 
 	// Spell Targets Handlers
 	void SpellTargetNULL(uint32 i, uint32 j);
Index: src/arcemu-world/SpellAuras.cpp
===================================================================
--- src/arcemu-world/SpellAuras.cpp	(revision 3395)
+++ src/arcemu-world/SpellAuras.cpp	(working copy)
@@ -268,7 +268,7 @@
 		&Aura::SpellAuraNULL,//244
 		&Aura::SpellAuraNULL,//245
 		&Aura::SpellAuraNULL,//246
-		&Aura::SpellAuraNULL,//247
+		&Aura::SpellAuraMirrorImage,//247
 		&Aura::SpellAuraModCombatResultChance,//248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
 		&Aura::SpellAuraNULL,//249 - SpellAuraConvertRune
 		&Aura::SpellAuraAddHealth,//250
@@ -300,7 +300,7 @@
 		&Aura::SpellAuraNULL,//276 Mod Damage % Mechanic
 		&Aura::SpellAuraNULL,//277 SPELL_AURA_REDIRECT_THREAT or SPELL_AURA_MOD_MAX_AFFECTED_TARGETS ?
 		&Aura::SpellAuraNULL,//278 Mod Disarm Ranged
-		&Aura::SpellAuraNULL,//279 Modify models(?)
+		&Aura::SpellAuraMirrorImage2,//279 Modify models(?)
 		&Aura::SpellAuraModIgnoreArmorPct,//280 SPELL_AURA_IGNORE_ARMOR_PCT
 		&Aura::SpellAuraNULL,//281 Mod Honor gain increased by X pct. Final Reward Honor increased by X pct for Y Rank and above. (http://thottbot.com/s58560 && http://thottbot.com/s58557)
 		&Aura::SpellAuraModBaseHealth,//282 SPELL_AURA_MOD_BASE_HEALTH
@@ -589,7 +589,7 @@
 	"244",												// 244
 	"MOD_DURATION_OF_MAGIC_EFFECTS",					// 245
 	"246",												// 246
-	"247",												// 247
+	"MIRROR_IMAGE",												// 247
 	"MOD_COMBAT_RESULT_CHANCE",							// 248
 	"249",												// 249
 	"MOD_INCREASE_HEALTH_2",							// 250
@@ -9351,6 +9351,23 @@
 	}
 }
 
+void Aura::SpellAuraMirrorImage( bool apply ){
+	if( m_target == NULL || !m_target->IsCreature() )
+		return;
+
+	if( apply ){
+		Creature *c_target = static_cast< Creature* >( m_target );
+
+		if( c_target->GetOwner() != NULL )
+			c_target->SetDisplayId( c_target->GetOwner()->GetDisplayId() );
+
+		c_target->SetUInt32Value( UNIT_FIELD_FLAGS_2, c_target->GetUInt32Value( UNIT_FIELD_FLAGS_2 ) | 0x10 );
+	}else{
+	}
+
+	SpellAuraMirrorImage2( apply );
+}
+
 void Aura::SpellAuraModCombatResultChance(bool apply)
 {
 	if( !m_target )
@@ -9558,6 +9575,35 @@
 	}
 }
 
+
+void Aura::SpellAuraMirrorImage2( bool apply ){
+	if( m_target == NULL )
+		return;
+
+	if( apply ){
+		if( GetCaster()->IsPlayer() ){
+
+			Player *p = static_cast< Player* >( GetCaster() );
+
+			Item *item;
+			
+			item = p->GetItemInterface()->GetInventoryItem( EQUIPMENT_SLOT_MAINHAND );
+			if( item != NULL )
+				m_target->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID, item->GetProto()->ItemId );
+
+			item = p->GetItemInterface()->GetInventoryItem( EQUIPMENT_SLOT_OFFHAND );
+			if( item != NULL )
+				m_target->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID + 1, item->GetProto()->ItemId );
+		}else{
+			m_target->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID, GetCaster()->GetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID ) );
+			m_target->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID + 1, GetCaster()->GetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID + 1 ) );
+			m_target->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID + 2, GetCaster()->GetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID + 2) );
+		}
+
+		}else{
+	}
+}
+
 void Aura::SpellAuraModIgnoreArmorPct(bool apply)
 {
 	if(!m_target)
Index: src/arcemu-world/SpellAuras.h
===================================================================
--- src/arcemu-world/SpellAuras.h	(revision 3395)
+++ src/arcemu-world/SpellAuras.h	(working copy)
@@ -693,6 +693,7 @@
 	void SpellAuraReduceEffectDuration(bool apply);
 	void HandleAuraControlVehicle(bool apply);
 	void EventPeriodicDrink(uint32 amount);
+	void SpellAuraMirrorImage(bool apply);
 	void SpellAuraModCombatResultChance(bool apply);
 	void SpellAuraAddHealth(bool apply);
 	void SpellAuraRemoveReagentCost(bool apply);
@@ -706,6 +707,7 @@
 	void SpellAuraConsumeNoAmmo( bool apply );
 	void SpellAuraIgnoreShapeshift(bool apply);
 	void SpellAuraPhase(bool apply);
+	void SpellAuraMirrorImage2( bool apply );
 	void SpellAuraModIgnoreArmorPct(bool apply);
 	void SpellAuraModBaseHealth(bool apply);
 	void SpellAuraModAttackPowerOfArmor(bool apply);
Index: src/arcemu-world/SpellEffects.cpp
===================================================================
--- src/arcemu-world/SpellEffects.cpp	(revision 3395)
+++ src/arcemu-world/SpellEffects.cpp	(working copy)
@@ -3116,6 +3116,7 @@
 	case 65:
 	case 428:	SpellEffectSummonPossessed(i);	return;
 	case 66:	SpellEffectSummonDemon(i);		return;
+	case 1021: SummonMirrorImage(i); return;
 	}
 	if( !u_caster ) return;
 
@@ -5681,6 +5682,16 @@
 				GetPlayerTarget()->ModGold( 50000000 );
 			}
 		}break;
+	case 45204: // Clone Me!
+	case 41055: // Copy Weapon
+	case 45206: // Copy Off-hand Weapon
+		unitTarget->CastSpell( u_caster, damage, false);
+		break;
+	
+	case 45205: // Copy Offhand Weapon
+	case 41054: // Copy Weapon
+		u_caster->CastSpell(unitTarget, damage, false);
+		break;
 	case 61288:
 		// Minor Inscription Research
 	case 61177:
@@ -5883,6 +5894,57 @@
 	sEventMgr.AddEvent(gameObjTarget, &GameObject::Deactivate, EVENT_GAMEOBJECT_DEACTIVATE, GetDuration(), 1);*/
 }
 
+void Spell::SummonMirrorImage( uint32 i ){
+	CreatureInfo * ci = CreatureNameStorage.LookupEntry(GetProto()->EffectMiscValue[i]);
+	CreatureProto * cp = CreatureProtoStorage.LookupEntry(GetProto()->EffectMiscValue[i]);
+
+	if( ci == NULL || cp == NULL )
+		return;
+
+	Creature * pCreature = u_caster->GetMapMgr()->CreateCreature( ci->Id );
+	pCreature->SetInstanceID(u_caster->GetMapMgr()->GetInstanceID());
+	pCreature->Load(cp, m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ());
+	pCreature->SetFaction( u_caster->GetFaction() );
+	pCreature->setLevel( u_caster->getLevel() );
+	pCreature->SetPowerType( u_caster->GetPowerType() );
+	pCreature->SetMaxPower( pCreature->GetPowerType(), u_caster->GetMaxPower( u_caster->GetPowerType() ) );
+	pCreature->SetPower( pCreature->GetPowerType(), pCreature->GetMaxPower( pCreature->GetPowerType() ) );	
+	pCreature->SetAttackPower( u_caster->GetAttackPower() / 3 );
+
+	u_caster->AddGuardianRef( pCreature );
+	pCreature->SetOwner( u_caster );
+
+	pCreature->SetCreatedByGUID( u_caster->GetGUID() );
+	pCreature->SetCreatedBySpell( GetProto()->Id );
+
+	pCreature->setRace( u_caster->getRace() );
+	pCreature->setGender( u_caster->getGender() );
+	pCreature->setClass( u_caster->getClass() );
+
+
+	pCreature->SetUInt32Value(UNIT_FIELD_FLAGS, 0x8 );
+	pCreature->SetUInt32Value(UNIT_FIELD_FLAGS_2, 0x800 );
+	pCreature->SetUInt32Value( UNIT_FIELD_BYTES_2, 1 );
+
+	pCreature->GetAIInterface()->Init(pCreature,AITYPE_PET,MOVEMENTTYPE_NONE,u_caster);
+	pCreature->GetAIInterface()->SetUnitToFollow(u_caster);
+	pCreature->GetAIInterface()->SetUnitToFollowAngle(float( (M_PI/4)));
+	pCreature->GetAIInterface()->SetFollowDistance( GetRadius( i ) );
+
+	if( u_caster->IsPvPFlagged() )
+		pCreature->SetPvPFlag();
+	else
+		pCreature->RemovePvPFlag();
+
+	pCreature->PushToWorld(u_caster->GetMapMgr());
+
+	
+	u_caster->CastSpell( pCreature->GetGUID(), 45204, false );
+	u_caster->CastSpell( pCreature->GetGUID(), 58838, false );
+	
+	sEventMgr.AddEvent(pCreature, &Creature::RemoveFromWorld, false, true, EVENT_CREATURE_REMOVE_CORPSE, GetDuration(), 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);
+}
+
 void Spell::SpellEffectSummonTotem(uint32 i) // Summon Totem
 {
 	if(!p_caster) return;
Index: src/arcemu-world/SpellTarget.cpp
===================================================================
--- src/arcemu-world/SpellTarget.cpp	(revision 3395)
+++ src/arcemu-world/SpellTarget.cpp	(working copy)
@@ -249,7 +249,7 @@
 	return;
 }
 
-//#define I_AM_STUPID_BUT_I_JUST_WANT_TO_TRY_THIS
+#define I_AM_STUPID_BUT_I_JUST_WANT_TO_TRY_THIS
 void Spell::SpellTargetNULL(uint32 i, uint32 j)
 {
 	sLog.outDebug("[SPELL][TARGET] Unhandled target typeA: %u typeB: %u", m_spellInfo->EffectImplicitTargetA[j], m_spellInfo->EffectImplicitTargetB[j]);
@@ -258,8 +258,9 @@
 		TargetsList* tmpMap=&m_targetUnits[i];
 		SafeAddTarget(tmpMap,m_targets.m_unitTarget);
 	#endif
+
 }
-//#undef I_AM_STUPID_BUT_I_JUST_WANT_TO_TRY_THIS
+#undef I_AM_STUPID_BUT_I_JUST_WANT_TO_TRY_THIS
 
 /// Spell Target Handling for type 0: Default targeting
 void Spell::SpellTargetDefault(uint32 i, uint32 j)
Index: src/arcemu-world/Unit.cpp
===================================================================
--- src/arcemu-world/Unit.cpp	(revision 3395)
+++ src/arcemu-world/Unit.cpp	(working copy)
@@ -6358,7 +6358,7 @@
 			data << uint32( aur->GetDuration() );
 			data << uint32( aur->GetTimeLeft() );
 		}
-
+		
 		SendMessageToSet(&data, true);
 	}
 
Index: src/arcemu-world/WorldSession.cpp
===================================================================
--- src/arcemu-world/WorldSession.cpp	(revision 3395)
+++ src/arcemu-world/WorldSession.cpp	(working copy)
@@ -946,6 +946,8 @@
 	WorldPacketHandlers[CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY].handler = &WorldSession::HandleInrangeQuestgiverQuery;
 	WorldPacketHandlers[CMSG_REMOVE_GLYPH].handler = &WorldSession::HandleRemoveGlyph;
 	WorldPacketHandlers[CMSG_ALTER_APPEARANCE].handler = &WorldSession::HandleBarberShopResult;
+
+	WorldPacketHandlers[CMSG_GET_MIRRORIMAGE_DATA].handler = &WorldSession::HandleMirrorImageOpcode;
 }
 
 void SessionLogWriter::writefromsession(WorldSession* session, const char* format, ...)
@@ -1280,3 +1282,80 @@
 
 	SendPacket( &data );
 }
+
+void WorldSession::HandleMirrorImageOpcode( WorldPacket &recv_data ){
+	if( !_player->IsInWorld() )
+		return;
+
+	sLog.outDebug("Received CMG_GET_MIRRORIMAGE_DATA");
+
+	uint64 GUID;
+
+	recv_data >> GUID;
+
+
+	Unit *Image = _player->GetMapMgr()->GetUnit( GUID );
+	if( Image == NULL )
+		return; // ups no unit found with that GUID on the map. Spoofed packet?
+
+	if( static_cast< Creature* >( Image )->GetOwner() == NULL )
+		return;
+
+	uint64 CasterGUID = static_cast< Creature* >( Image )->GetOwner()->GetGUID();
+	Unit *Caster = _player->GetMapMgr()->GetUnit( CasterGUID );
+	if( Caster == NULL )
+		return; // apperantly this mirror image mirrors nothing, poor lonely soul :(
+	 	// Maybe it's the Caster's ghost called Casper
+
+	WorldPacket data( SMSG_MIRRORIMAGE_DATA, 68 );
+
+	data << uint64( GUID );
+	data << uint32( Caster->GetDisplayId() );
+	data << uint8( Caster->getRace() );
+
+	if( Caster->IsPlayer() ){
+		Player *pcaster = static_cast< Player* >( Caster );
+
+		data << uint8( pcaster->getGender() );
+		data << uint8( pcaster->getClass() );
+		
+		// facial features, like big nose, piercings, bonehead, etc
+		data << uint8( pcaster->GetByte( PLAYER_BYTES, 0 ) ); // skin color
+		data << uint8( pcaster->GetByte( PLAYER_BYTES, 1 ) ); // face
+		data << uint8( pcaster->GetByte( PLAYER_BYTES, 2 ) ); // hair style 
+		data << uint8( pcaster->GetByte( PLAYER_BYTES, 3 ) ); // hair color		
+		data << uint8( pcaster->GetByte( PLAYER_BYTES_2, 0 ) ); // facial hair
+		
+		if( pcaster->IsInGuild() )
+			data << uint32( pcaster->GetGuildId() );
+		else
+			data << uint32( 0 );
+
+		static const uint32 imageitemslots[] = {
+			EQUIPMENT_SLOT_HEAD,
+			EQUIPMENT_SLOT_SHOULDERS,
+			EQUIPMENT_SLOT_BODY,
+			EQUIPMENT_SLOT_CHEST,
+			EQUIPMENT_SLOT_WAIST,
+			EQUIPMENT_SLOT_LEGS,
+			EQUIPMENT_SLOT_FEET,
+			EQUIPMENT_SLOT_WRISTS,
+			EQUIPMENT_SLOT_HANDS,
+			EQUIPMENT_SLOT_BACK,
+			EQUIPMENT_SLOT_TABARD
+		};
+
+		for( uint32 i = 0; i < 11; ++i ){
+			Item *item = pcaster->GetItemInterface()->GetInventoryItem( static_cast< int16 >( imageitemslots[ i ] ) );
+
+			if( item != NULL )
+			 data << uint32( item->GetProto()->DisplayInfoID );
+			else
+			 data << uint32( 0 );
+		}
+	}
+
+	SendPacket( &data );
+
+	sLog.outDebug("Sent: SMSG_MIRRORIMAGE_DATA");
+}
Index: src/arcemu-world/WorldSession.h
===================================================================
--- src/arcemu-world/WorldSession.h	(revision 3395)
+++ src/arcemu-world/WorldSession.h	(working copy)
@@ -757,6 +757,7 @@
 	//MISC
 	void HandleWorldStateUITimerUpdate( WorldPacket & recv_data );
 	void HandleSetTaxiBenchmarkOpcode( WorldPacket & recv_data );
+	void HandleMirrorImageOpcode( WorldPacket &recv_data );
 
 public:
 


"The demand for free goods is infinite."
0

#2 User is offline   jackpoz 

  • ArcEmu Lemon Priest
  • PipPipPipPipPipPipPipPip
  • Group: Developers
  • Posts: 2,153
  • Joined: 19-June 08
  • Gender:Male
  • Location:Italy
  • Server OS:Windows

Posted 08 June 2010 - 12:41 PM

imho you should finish it so the 3 images would help us fixing issues ;)
Posted Image We develop dreams. Your dreams ;)
Posted ImagePosted Image
0

#3 User is offline   dfighter 

  • Titles are overrated
  • PipPipPipPipPipPipPipPipPipPip
  • Group: Administrator
  • Posts: 5,189
  • Joined: 14-June 08
  • IRC:dfighter
  • Gender:Male
  • Server OS:Linux

Posted 08 June 2010 - 12:49 PM

View Postjackpoz, on 08 June 2010 - 12:41 PM, said:

imho you should finish it so the 3 images would help us fixing issues ;)

That would be great! Except when their timer expires their work would disappear too.
"The demand for free goods is infinite."
0

#4 User is offline   lesone 

  • Enthusiast
  • Group: Retired
  • Posts: 294
  • Joined: 07-June 08
  • Gender:Male
  • Location:Zpain
  • Interests:Programming--
  • Server OS:Windows

Posted 11 August 2010 - 03:24 AM

I think in your code you should add this,

       if( Caster->IsPlayer() ){
               Player *pcaster = static_cast< Player* >( Caster );

               data << uint8( pcaster->getGender() );
               data << uint8( pcaster->getClass() );



+       if( Caster->IsPlayer() ){
+               Player *pcaster = static_cast< Player* >( Caster );
+
+               data << uint8 (pcaster->getRace() );
+               data << uint8( pcaster->getGender() );
+               data << uint8( pcaster->getClass() );
+               



Don't think so, it should get race from plr.

Anyways about FollowDistance,

 pCreature->GetAIInterface()->SetFollowDistance(3.0f); 


I'll continue testing it
btw thanks Shauren for helping me out. :D
Posted Image
0

#5 User is offline   Neo_mat 

  • drunken bear rider
  • PipPipPip
  • Group: Developers
  • Posts: 278
  • Joined: 07-June 08
  • Gender:Male
  • Server OS:Linux

Posted 18 August 2010 - 03:46 AM

Quote

-//#undef I_AM_STUPID_BUT_I_JUST_WANT_TO_TRY_THIS
+#undef I_AM_STUPID_BUT_I_JUST_WANT_TO_TRY_THIS
Just epic :D
Posted Image
Posted Image
Posted Image
I am 91% addicted to World of Warcraft. What about you?
0

#6 User is offline   dfighter 

  • Titles are overrated
  • PipPipPipPipPipPipPipPipPipPip
  • Group: Administrator
  • Posts: 5,189
  • Joined: 14-June 08
  • IRC:dfighter
  • Gender:Male
  • Server OS:Linux

Posted 21 July 2011 - 07:16 PM

View PostNeo_mat, on 18 August 2010 - 03:46 AM, said:

Just epic :)

Yes having and working on hacked together ( rather than designed ) spell system is just fucking epic, isn't it?
"The demand for free goods is infinite."
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users