- Mesaj
- 12.062
- Çözümler
- 571
- Beğeni
- 14.465
- Puan
- 5.915
- Ticaret Puanı
- 2
Merhaba arkadaşlar,
Casro2 serverini geliştirirken güzel bir şey keşfettim ve sizle paylaşmak istiyorum.
Metin2'nin ana görevlerini çevirirken ilginç bir tabir gördüm. Questlerin başında define ibaresi yazıyordu.
Haliyle o questleri build etmeye çalışınca hata alıyordum. Bu hatanın sebebi qc dosyamızda define ibaresinin ekli olmaması. Vanilla'nın srcsinde bunun ekli olduğunu gördüm ve kendi srcmin qc dosyasına da eklemeye çalıştım ve başarılı oldum.
Her şeyden önce...
Define nedir?
Define bir şeyleri tanımlamak için kullanılıyor. Biz burada sabit bir değişken olarak kullanacağız.
Örnek kullanım;
Bu kodu ben bir şeyi test etmek için yazmıştım. Fakat kodun bir çok bölümünü sildim. Burada önemli olan defineleri nerede kullanabileceğimiz.
Örnektede gördüğünüz için sayıları sürekli aklınızda tutmak yerine. Defineler tanımlayarak çook uzun questlerinizde rahatlıkla kullanabilirsiniz.
İleride questte değişiklik yaparken mesela kesme sayısını 10 değilde 20 yapacağız. Normalde her yerde bulup değiştirmek gerekiyor. Fakat burada definenin değerini değiştirince her yerde değişmiş olacak. Ne kaaa pratik dimi ^_^
qc dosyamıza nasıl ekleriz?
Çalışacağımız dosya;
game/src/quest/gc.cc dosyasıdır. Bu dosyayı açıp aşağıdaki işlemleri sırasıyla tamamlayın;
Not: Novaline srcsinin qc dosyasında yapılmıştır!!
Ara:
En başa ekle:
Ara:
Kod blogunun altına şunları ekle:
Ara:
Kod blogunun altına ekle:
void parse(char * filename) kod blogunda ara:
Altına ekle:
void parse(char * filename) kod blogunda ara:
Altına ekle:
void parse(char * filename) kod blogunda ara:
Altına ekle:
void parse(char * filename) kod blogunda ara:
swtich(ps) kod blogunun içine en başa bunu ekle:
void parse(char * filename) kod blogunda ara:
Bunu:
Şu şekilde değiştir:
Bunu:
Şu şekilde değiştir:
void parse(char * filename) kod blogunda ara:
Bunu:
Şu şekilde değiştir:
void parse(char * filename) kod blogunda ara:
Bunu:
Şu şekilde değiştir:
İşlemler bu kadardır.
Daha sonra build edebilirsiniz. qc dosyasını build etmek için;
Build olduktan sonra qc dosyasını alıp game/share/locale/turkey/quest içine atın.
Bu eklediğimiz kodların çalışma mantığı şu şekildedir. Siz questinizi build ederken eğer define belirtmişseniz. Sistem bunu önbelleğe alıyor. Daha sonra bu defineleri nerelerde kullandıysanız onu definenin değeri ile değiştiriyor. Kısacası oyunun çekirdek dosyasında hiçbir değişiklik yapmanıza gerek yok. Bu düzenlemeler sadece questlerin yazımı daha kolay ve anlaşılabilir olması içindir.
Konunun tüm anlatımı bana aittir arkadaşlar. Ne yazık ki çok araştırdım ama bulamadım. Elimdeki vanilla src sağolsun ondan bu kodları çıkarttım...
Casro2 serverini geliştirirken güzel bir şey keşfettim ve sizle paylaşmak istiyorum.
Metin2'nin ana görevlerini çevirirken ilginç bir tabir gördüm. Questlerin başında define ibaresi yazıyordu.
Haliyle o questleri build etmeye çalışınca hata alıyordum. Bu hatanın sebebi qc dosyamızda define ibaresinin ekli olmaması. Vanilla'nın srcsinde bunun ekli olduğunu gördüm ve kendi srcmin qc dosyasına da eklemeye çalıştım ve başarılı oldum.
Her şeyden önce...
Define nedir?
Define bir şeyleri tanımlamak için kullanılıyor. Biz burada sabit bir değişken olarak kullanacağız.
Örnek kullanım;
Lua (Quest):
define kesilecekMob 171
define kesilecekMobAdet 10
quest partyKillTest begin
state start begin
when login or levelup begin
set_state(gorev1)
end
end
state gorev1 begin
when kesilecekMob.party_kill with pc.getqf("partykilltestDurum") == 1 begin
local sayim = pc.getqf("partykilltestSayim") - 1
if sayim <= kesilecekMobAdet then
pc.setqf("partykilltestSayim", sayim)
q.set_counter("Aç Yabani Köpek", sayim)
end
if sayim == 0 then
pc.setqf("partykilltestDurum", 0)
pc.setqf("partykilltestSayim", 0)
clear_letter()
end
end
end
state __COMPLETE__ begin
end
end
Bu kodu ben bir şeyi test etmek için yazmıştım. Fakat kodun bir çok bölümünü sildim. Burada önemli olan defineleri nerede kullanabileceğimiz.
Örnektede gördüğünüz için sayıları sürekli aklınızda tutmak yerine. Defineler tanımlayarak çook uzun questlerinizde rahatlıkla kullanabilirsiniz.
İleride questte değişiklik yaparken mesela kesme sayısını 10 değilde 20 yapacağız. Normalde her yerde bulup değiştirmek gerekiyor. Fakat burada definenin değerini değiştirince her yerde değişmiş olacak. Ne kaaa pratik dimi ^_^
qc dosyamıza nasıl ekleriz?
Çalışacağımız dosya;
game/src/quest/gc.cc dosyasıdır. Bu dosyayı açıp aşağıdaki işlemleri sırasıyla tamamlayın;
Not: Novaline srcsinin qc dosyasında yapılmıştır!!
Ara:
C++:
enum parse_state
En başa ekle:
C++:
ST_DEFINE,
Ara:
C++:
ostream & operator << (ostream & ostr, const Token& tok)
Kod blogunun altına şunları ekle:
C++:
string token2string(const Token& t)
{
stringstream ss;
string token;
ss << t;
getline(ss, token);
return token;
}
static bool testnext(LexState * ls, std::string str) {
if (token2string(ls->t) == str) {
next(ls);
return true;
} else
return false;
}
Ara:
C++:
void load_quest_function_list(const char* filename)
Kod blogunun altına ekle:
C++:
class Constant {
map<string, string> storage;
public:
Constant() {}
void create(std::string key, std::string value) {
storage[key] = value;
}
void create(std::string key, const Token& t) {
string tvalue = token2string(t);
if (t.token == TK_STRING) {
tvalue.erase(0, 1);
tvalue.erase(tvalue.size() - 1, tvalue.size());
storage[key] = tvalue;
} else if (t.token == TK_NUMBER) {
storage[key] = token2string(t);
} else if (t.token == TK_NAME) {
storage[key] = storage[tvalue];
} else {
error("Gecersiz define formatı. define CONSTANT \"deger\"");
}
}
std::string get(std::string key) {
return storage[key];
}
bool exists(std::string key) {
return ! (storage.find(key) == storage.end());
}
};
void parse(char * filename) kod blogunda ara:
C++:
map<string, map<string, vector<AScript> > > state_arg_script_map;
Altına ekle:
C++:
Constant constant;
void parse(char * filename) kod blogunda ara:
C++:
Token& t= lexstate.t;
Altına ekle:
C++:
string lastDefine = "";
void parse(char * filename) kod blogunda ara:
C++:
int nested = 0;
Altına ekle:
C++:
string traFunc = "translating";
void parse(char * filename) kod blogunda ara:
C++:
switch(ps)
{
case ST_START:
swtich(ps) kod blogunun içine en başa bunu ekle:
C++:
case ST_DEFINE:
{
if (t.token == TK_QUEST) {
ps = ST_QUEST;
continue;
}
if (t.token == TK_NAME && string("define").compare(token2string(lexstate.t)) == 0) {
next(&lexstate);
if (lexstate.t.token == TK_NAME) {
lastDefine = token2string(lexstate.t);
} else {
error("Invalid constant name format.");
}
next(&lexstate);
constant.create(lastDefine, lexstate.t);
}
}
break;
void parse(char * filename) kod blogunda ara:
C++:
case ST_WHEN_NAME:
Bunu:
JavaScript:
else
{
current_when_name = getstr(t.seminfo.ts);
lookahead(&lexstate);
}
Şu şekilde değiştir:
C++:
else
{
current_when_name = getstr(t.seminfo.ts);
if (constant.exists(current_when_name)) { //c2 define okuyucu
current_when_name = constant.get(current_when_name);
}
lookahead(&lexstate);
}
Bunu:
C++:
if (!current_when_argument.empty())
{
cout << " (";
cout << current_when_argument.substr(1);
cout << ")";
}
Şu şekilde değiştir:
C++:
if (!current_when_argument.empty())
{
if (constant.exists("_TRA_"))
{
traFunc = constant.get("_TRA_");
}
size_t fpos = current_when_argument.find(traFunc);
if (fpos != string::npos) {
fpos += traFunc.size();
if (fpos < current_when_argument.size() && current_when_argument[fpos] == '.') {
current_when_argument[fpos] = '(';
current_when_argument.append(")");
} else {
error("tra fonksiyonu yanlis kullanilmis.");
}
}
cout << " (";
cout << current_when_argument.substr(1);
cout << ")";
}
void parse(char * filename) kod blogunda ara:
C++:
case ST_WHEN_BODY:
Bunu:
C++:
if (nested==2) break;
os << lexstate.t << ' ';
prev = lexstate;
next(&lexstate);
Şu şekilde değiştir:
C++:
if (nested==2) break;
/* Replace vars or function names with our constant value */
string tmpStr = token2string(lexstate.t);
if (lexstate.t.token == TK_NAME)
{
string ckey = token2string(lexstate.t);
if (constant.exists(ckey))
{
tmpStr = constant.get(ckey);
}
}
os << tmpStr << ' ';
//os << lexstate.t << ' ';
prev = lexstate;
next(&lexstate);
void parse(char * filename) kod blogunda ara:
C++:
case ST_FUNCTION_BODY:
Bunu:
C++:
os << lexstate.t << ' ';
Şu şekilde değiştir:
C++:
// Same piece of code used above - need refactoring
string tmpStr = token2string(lexstate.t);
if (lexstate.t.token == TK_NAME)
{
string ckey = token2string(lexstate.t);
if (constant.exists(ckey))
{
tmpStr = constant.get(ckey);
}
}
os << tmpStr << ' ';
//os << lexstate.t << ' ';
İşlemler bu kadardır.
Daha sonra build edebilirsiniz. qc dosyasını build etmek için;
Kod:
game/src/quest && gmake clean
gmake -j20
Build olduktan sonra qc dosyasını alıp game/share/locale/turkey/quest içine atın.
Bu eklediğimiz kodların çalışma mantığı şu şekildedir. Siz questinizi build ederken eğer define belirtmişseniz. Sistem bunu önbelleğe alıyor. Daha sonra bu defineleri nerelerde kullandıysanız onu definenin değeri ile değiştiriyor. Kısacası oyunun çekirdek dosyasında hiçbir değişiklik yapmanıza gerek yok. Bu düzenlemeler sadece questlerin yazımı daha kolay ve anlaşılabilir olması içindir.
Konunun tüm anlatımı bana aittir arkadaşlar. Ne yazık ki çok araştırdım ama bulamadım. Elimdeki vanilla src sağolsun ondan bu kodları çıkarttım...
Son düzenleme: