View Single Post
  #2  
Old 03-08-2009, 01:26 PM
realityincarnate
Developer
 
Join Date: Dec 2007
Posts: 122
Default A more extensive modification

(this replaces the code posted above)
After playing around with the language stuff some more, I made a couple of changes to how language skill is handled. This system now uses both the speaker and listener skills in the language to more realistically determine how garbled text becomes. As a side effect, it also enables drunk talk (one of my favorite little touches in the game).

Code:
Index: client.cpp
===================================================================
--- client.cpp	(revision 376)
+++ client.cpp	(working copy)
@@ -670,7 +670,7 @@
 	return;
 }
 
-void Client::ChannelMessageReceived(int8 chan_num, int8 language, const char* message, const char* targetname) {
+void Client::ChannelMessageReceived(int8 chan_num, int8 language, int8 lang_skill, const char* message, const char* targetname) {
 	#if EQDEBUG >= 11
 		LogFile->write(EQEMuLog::Debug,"Client::ChannelMessageReceived() Channel:%i message:'%s'", chan_num, message);
 	#endif
@@ -744,7 +744,7 @@
 
 		Group* group = GetGroup();
 		if(group != NULL) {
-			group->GroupMessage(this,(const char*) message);
+			group->GroupMessage(this,language,lang_skill,(const char*) message);
 		}
 		break;
 	}
@@ -760,7 +760,7 @@
 		if (GetPet() && GetPet()->FindType(SE_VoiceGraft))
 			sender = GetPet();
 
-		entity_list.ChannelMessage(sender, chan_num, language, message);
+		entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
  		break;
  	}
 	case 4: { // Auction
@@ -783,7 +783,7 @@
 		    if(!ooc_timer.Check())
 		{
 			if(strlen(targetname)==0)
-			ChannelMessageReceived(5, language, message,"discard"); //Fast typer or spammer??
+			ChannelMessageReceived(5, language, lang_skill, message,"discard"); //Fast typer or spammer??
 			else
 			return;
 		}
@@ -833,7 +833,7 @@
 			sender = GetPet();
 
 		printf("Message: %s\n",message);
-		entity_list.ChannelMessage(sender, chan_num, language, message);
+		entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
 
 		if (sender != this)
 			break;
@@ -892,7 +892,12 @@
 	}
 }
 
+// if no language skill is specified, call the function with a skill of 100.
 void Client::ChannelMessageSend(const char* from, const char* to, int8 chan_num, int8 language, const char* message, ...) {
+	ChannelMessageSend(from, to, chan_num, language, 100, message);
+}
+
+void Client::ChannelMessageSend(const char* from, const char* to, int8 chan_num, int8 language, int8 lang_skill, const char* message, ...) {
 	if ((chan_num==11 && !(this->GetGM())) || (chan_num==10 && this->Admin()<80)) // dont need to send /pr & /petition to everybody
 		return;
 	va_list argptr;
@@ -917,15 +922,30 @@
 		strcpy(cm->targetname, m_pp.name);
 	else
 		cm->targetname[0] = 0;
+	
+	int8 ListenerSkill;
+	
 	if (language < MAX_PP_LANGUAGE) {
-		cm->skill_in_language = m_pp.languages[language];
+		ListenerSkill = m_pp.languages[language];
 		cm->language = language;
+		if ((chan_num == 2) && (ListenerSkill < 100)) {	// group message in unmastered language, check for skill up
+			if ((m_pp.languages[language] <= lang_skill) && (from != this->GetName() )) 
+				CheckLanguageSkillIncrease(language, lang_skill);
+		}
 	}
 	else {
-		cm->skill_in_language = 100;
+		ListenerSkill = m_pp.languages[0];
 		cm->language = 0;
 	}
-
+	
+	// set effective language skill = average of sender and receiver skills
+	sint32 EffSkill = (lang_skill + ListenerSkill)/2;
+	if (EffSkill < 1)	// effective skill has a minimum value of 1...
+		EffSkill = 1;
+	else if (EffSkill > 100)	// ...and a maximum value of 100
+		EffSkill;
+	cm->skill_in_language = EffSkill;
+	
 	cm->chan_num = chan_num;
 	strcpy(&cm->message[0], buffer);
 	QueuePacket(&app);
@@ -1920,6 +1940,25 @@
 	return false;
 }
 
+void Client::CheckLanguageSkillIncrease(int8 langid, int8 TeacherSkill) {
+	if (langid >= MAX_PP_LANGUAGE)
+		return;		// do nothing if langid is an invalid language
+
+	int LangSkill = m_pp.languages[langid];		// get current language skill
+
+	if (LangSkill < 100) {	// if the language isn't already maxed
+		sint16 Chance = 5 + ((TeacherSkill - LangSkill)/10);	// greater chance to learn if teacher's skill is much higher than yours
+		Chance = (Chance * RuleI(Character, SkillUpModifier)/100);
+
+		if(MakeRandomFloat(0,100) < Chance) {	// if they make the roll
+			SetLanguageSkill(langid, LangSkill+1);	// increase the language skill by 1
+			_log(SKILLS__GAIN, "Language %d at value %d successfully gain with %.4f%%chance", langid, LangSkill, Chance);
+		} 
+		else
+			_log(SKILLS__GAIN, "Language %d at value %d failed to gain with %.4f%%chance", langid, LangSkill, Chance);
+	}
+}
+
 bool Client::HasSkill(SkillType skill_id) const {
 	return((GetSkill(skill_id) > 0) && CanHaveSkill(skill_id));
 }
Index: client.h
===================================================================
--- client.h	(revision 376)
+++ client.h	(working copy)
@@ -232,8 +232,9 @@
 	void	SendPacketQueue(bool Block = true);
 	void	QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
 	void	FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
-	void	ChannelMessageReceived(int8 chan_num, int8 language, const char* message, const char* targetname=NULL);
+	void	ChannelMessageReceived(int8 chan_num, int8 language, int8 lang_skill, const char* message, const char* targetname=NULL);
 	void	ChannelMessageSend(const char* from, const char* to, int8 chan_num, int8 language, const char* message, ...);
+	void	ChannelMessageSend(const char* from, const char* to, int8 chan_num, int8 language, int8 lang_skill, const char* message, ...);
 	void	Message(int32 type, const char* message, ...);
 	void    QuestJournalledMessage(const char *npcname, const char* message);
 	void	VoiceMacroReceived(int32 Type, char *Target, int32 MacroNumber);
@@ -550,6 +551,7 @@
 	void CheckSpecializeIncrease(int16 spell_id);
 	void CheckSongSkillIncrease(int16 spell_id);
 	bool	CheckIncreaseSkill(SkillType skillid, int chancemodi = 0);
+	void	CheckLanguageSkillIncrease(int8 langid, int8 TeacherSkill);
 	void    SetLanguageSkill(int langid, int value);
 	void	SetHoTT(int32 mobid);
 
Index: client_packet.cpp
===================================================================
--- client_packet.cpp	(revision 376)
+++ client_packet.cpp	(working copy)
@@ -2334,7 +2334,7 @@
 		return;
 	}
 
-	ChannelMessageReceived(cm->chan_num, cm->language, cm->message, cm->targetname);
+	ChannelMessageReceived(cm->chan_num, cm->language, cm->skill_in_language, cm->message, cm->targetname);
 	return;
 }
 
Index: entity.cpp
===================================================================
--- entity.cpp	(revision 376)
+++ entity.cpp	(working copy)
@@ -954,7 +954,12 @@
 	}
 }
 
+// if no language skill is specified, sent with 100 skill
 void EntityList::ChannelMessage(Mob* from, int8 chan_num, int8 language, const char* message, ...) {
+	ChannelMessage(from, chan_num, language, 100, message);
+}
+
+void EntityList::ChannelMessage(Mob* from, int8 chan_num, int8 language, int8 lang_skill, const char* message, ...) {
 	LinkedListIterator<Client*> iterator(client_list);
 	va_list argptr;
 	char buffer[4096];
@@ -976,7 +981,7 @@
 		if (chan_num != 8 || client->Dist(*from) < 200) // Only say is limited in range
 		{
 			if(filter==FilterNone || client->GetFilter(filter)!=FilterHide)
-				client->ChannelMessageSend(from->GetName(), 0, chan_num, language, buffer);
+				client->ChannelMessageSend(from->GetName(), 0, chan_num, language, lang_skill, buffer);
 		}
 		iterator.Advance();
 	}
Index: entity.h
===================================================================
--- entity.h	(revision 376)
+++ entity.h	(working copy)
@@ -236,6 +236,7 @@
 	void	MessageClose_StringID(Mob *sender, bool skipsender, float dist, int32 type, int32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
 	void	ChannelMessageFromWorld(const char* from, const char* to, int8 chan_num, int32 guilddbid, int8 language, const char* message);
 	void    ChannelMessage(Mob* from, int8 chan_num, int8 language, const char* message, ...);
+	void    ChannelMessage(Mob* from, int8 chan_num, int8 language, int8 lang_skill, const char* message, ...);
 	void	ChannelMessageSend(Mob* to, int8 chan_num, int8 language, const char* message, ...);
 	void    SendZoneSpawns(Client*);
 	void	SendZonePVPUpdates(Client *);
Index: groups.cpp
===================================================================
--- groups.cpp	(revision 376)
+++ groups.cpp	(working copy)
@@ -664,14 +664,14 @@
 	return false;
 }
 
-void Group::GroupMessage(Mob* sender, const char* message) {
+void Group::GroupMessage(Mob* sender, int8 language, int8 lang_skill, const char* message) {
 	uint32 i;
 	for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
 		if(!members[i])
 			continue;
 
 		if (members[i]->IsClient() && members[i]->CastToClient()->GetFilter(FILTER_GROUP)!=0)
-			members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,0,message);
+			members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,language,lang_skill,message);
 		#ifdef IPC
 		if (members[i]->CastToNPC()->IsInteractive() && members[i] != sender)
 			members[i]->CastToNPC()->InteractiveChat(2,1,message,(sender->GetTarget() != NULL) ? sender->GetTarget()->GetName():sender->GetName(),sender);
Index: groups.h
===================================================================
--- groups.h	(revision 376)
+++ groups.h	(working copy)
@@ -68,7 +68,7 @@
 	void	CastGroupSpell(Mob* caster,uint16 spellid);
 	void	GroupBardPulse(Mob* caster,uint16 spellid);
 	void	SplitExp(uint32 exp, Mob* other);
-	void	GroupMessage(Mob* sender,const char* message);
+	void	GroupMessage(Mob* sender,int8 language,int8 lang_skill,const char* message);
 	void	GroupMessage_StringID(Mob* sender, int32 type, int32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, int32 distance = 0);
 	int32	GetTotalGroupDamage(Mob* other);
 	void	SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = NULL);
Index: perl_groups.cpp
===================================================================
--- perl_groups.cpp	(revision 376)
+++ perl_groups.cpp	(working copy)
@@ -168,12 +168,13 @@
 XS(XS_Group_GroupMessage)
 {
 	dXSARGS;
-	if (items != 3)
-		Perl_croak(aTHX_ "Usage: Group::GroupMessage(THIS, sender, message)");
+	if ((items != 3) && (items != 4))	// the 3 item version is kept for backwards compatability
+		Perl_croak(aTHX_ "Usage: Group::GroupMessage(THIS, sender, language, message)");
 	{
 		Group *		THIS;
 		Mob*		sender;
-		char*		message = (char *)SvPV_nolen(ST(2));
+		int8		language;
+		char*		message;
 
 		if (sv_derived_from(ST(0), "Group")) {
 			IV tmp = SvIV((SV*)SvRV(ST(0)));
@@ -193,7 +194,17 @@
 		if(sender == NULL)
 			Perl_croak(aTHX_ "sender is NULL, avoiding crash.");
 
-		THIS->GroupMessage(sender, message);
+		if (items == 4) {
+			language = (int8)SvUV(ST(2));
+			if ((language >= MAX_PP_LANGUAGE) || (language < 0))
+				language = 0;
+			message = (char *)SvPV_nolen(ST(3));
+			THIS->GroupMessage(sender, language, 100, message);
+		}
+		else {	// if no language is specificed, send it in common
+			message = (char *)SvPV_nolen(ST(2));
+			THIS->GroupMessage(sender,0, 100, message);
+		}
 	}
 	XSRETURN_EMPTY;
 }
Reply With Quote