realityincarnate
03-07-2009, 12:54 PM
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
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;
}
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
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;
}