View Single Post
  #1  
Old 03-07-2009, 12:54 PM
realityincarnate
Developer
 
Join Date: Dec 2007
Posts: 122
Default Learning Languages

This fix allows players to teach each other languages while grouped. It only works while grouped and in the same zone. I think the rate of learning feels about right, but it could be tinkered with. I also set the rate to be modified by the SkillUpModifier rule.

Can anyone point me to a good XS reference? I needed to modify the perl_groups code this time, and while I was able to get most of the idea by looking at other parts of the code, this part is pretty foreign to me.

Here's the diff, against R373
Code:
Index: zone/client.cpp
===================================================================
--- zone/client.cpp	(revision 373)
+++ zone/client.cpp	(working copy)
@@ -744,7 +744,7 @@
 
 		Group* group = GetGroup();
 		if(group != NULL) {
-			group->GroupMessage(this,(const char*) message);
+			group->GroupMessage(this,language,(const char*) message);
 		}
 		break;
 	}
@@ -920,6 +920,11 @@
 	if (language < MAX_PP_LANGUAGE) {
 		cm->skill_in_language = m_pp.languages[language];
 		cm->language = language;
+		if ((chan_num == 2) && (language != 0)) {	// for group messages not in common, check for language skill up
+			int SenderSkill = entity_list.GetClientByName(from)->m_pp.languages[language];
+			if ((m_pp.languages[language] <= SenderSkill) && (from != this->GetName() )) 
+				CheckLanguageSkillIncrease(language, SenderSkill);
+		}
 	}
 	else {
 		cm->skill_in_language = 100;
@@ -1920,6 +1925,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: zone/client.h
===================================================================
--- zone/client.h	(revision 373)
+++ zone/client.h	(working copy)
@@ -550,6 +550,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: zone/groups.cpp
===================================================================
--- zone/groups.cpp	(revision 373)
+++ zone/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, 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,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: zone/groups.h
===================================================================
--- zone/groups.h	(revision 373)
+++ zone/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,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: zone/perl_groups.cpp
===================================================================
--- zone/perl_groups.cpp	(revision 373)
+++ zone/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, message);
+		}
+		else {	// if no language is specificed, send it in common
+			message = (char *)SvPV_nolen(ST(2));
+			THIS->GroupMessage(sender,0, message);
+		}
 	}
 	XSRETURN_EMPTY;
 }
Reply With Quote