Продвинутые сообщения
В этом небольшой туториале показано, как переопределить функции Say() (и TeamSay()) из класса PlayerPawn для того, чтобы игроки могли пользоваться определенными escape кодами во время передачи сообщения. Чтобы все выглядело аккуратно, я просто создал новую функцию ParseChatString(), которая принимает в качестве параметра текст сообщения, разбирает его на составляющие, модифицирует его исходя из содержания и, затем, возвращает конечную строку сообщения. Также я написал новые версии функций Say() и TeamSay(), которые в свою очередь вызывают метод ParseChatString() и отображают на экране модифицированное сообщение. Поэтому, теоретически, если Вы хотите интегрировать этот подход в Ваш мод, Вы можете просто вставить эти три функции в созданный Вами подкласс класса PlayerPawn.
ParseChatString принимает строку сообщения, затем перебирает ее посимвольно, ища при этом символ #. Как только такой символ найден, скрипт обращается к следующему символу, и, исходя из того, каким является следующий символ, вставляет соответствующую информацию в конечную строку, затем продолжает поиск других символов #, и так до конца исходной строки. Затем функция возвращает измененную строку сообщения.
// function string ParseChatString(string Msg) // // escape коды: // ============= // #N - имя игрока // #L - положение игрока // #S - статус игрока (здоровье/броня) // #H - здоровье игрока // #A - броня игрока // #B - друзья, перечисляет всех "дружественных" игроков в определенном радиусе // #W - оружие игрока // #T - тестовый код // ## - выводит символ '#' // // Для поиска друзей скрипт использует свойство RadiusActors (радиус актера), // затем проверяет, является ли актер "дружественным", т.е. проверяет // в одной ли Вы команде, и если так, то добавляет его в список друзей (bStr), // затем, когда весь список готов, преобразовывает строку в "грамматически" // правильную, т.е. добавляет союзы "and" между именами. Я знаю, что это // трата времени, но я был в шоке от того, что это заработало с первого раза :) // // Если Вы хотите иметь больше escape кодов, просто добавьте дополнительные // case в операторе switch, где и дописывайте к конечной строке // нужную Вам информацию // // Что еще: // - можно сделать многоуровневые escape коды, например, #b:5 возвращающий // только пять друзей function string ParseChatString(string Msg) { local int i, amt, numBuddy, lBuddyLen; local float BuddyRadius; local string nMsg, tStr, bStr, lbStr; local Inventory Inv; local Pawn Buddy; local PlayerReplicationInfo mPRI, bPRI; BuddyRadius = 1500.0; mPRI = PlayerReplicationInfo; // перебираем посимвольно всю строку в поисках символа # // Len(string) возвращает длину строки for (i = 0;i <= Len(Msg);i++) { // используем функцию Mid для получения определенного символа в строке, // т.к. выражение Msg[i] не работает // Mid(string, pos, count) возвращает подстроку данной строки, начиная // с позиции pos и кончая pos+count-1 (включительно), поэтому, чтобы // вытащить один символ из строки, указываем count равный 1 if (Mid(Msg, i, 1) == "#") { // найден escape символ #, // теперь необходимо узнать следующий за ним символ i += 1; tStr = Mid(Msg,i,1); // здесь находится сердце функции - switch оператор, // если нужно больше escape кодов, просто добавьте // необходимое количество case-ов switch (tStr) { // оружие игрока - вставляет наименование Вашего оружия case "W": nMsg = nMsg $ Weapon.ItemName; break; // имя игрока - вставляет Ваше имя case "N": nMsg = nMsg $ mPRI.PlayerName; break; // положение игрока - вставляет Ваше местоположение case "L": if (mPRI.PlayerLocation != NONE) nMsg = nMsg $ mPRI.PlayerLocation.LocationName; else if (mPRI.PlayerZone != NONE) nMsg = nMsg $ mPRI.PlayerZone.ZoneName; else nMsg = nMsg $ "somewhere"; break; // броня игрока - вставляет количество Вашей брони case "A": amt = 0; for (Inv = Inventory; Inv != NONE; Inv = Inv.Inventory) if (Inv.bIsAnArmor) amt += Inv.Charge; nMsg = nMsg $ amt; break; // здоровье игрока - вставляет количество Вашего здоровья case "H": nMsg = nMsg $ Health; break; // статус игрока - вставляет Ваш статус (Health: xxx Armor: xxx) case "S": amt = 0; for (Inv = Inventory; Inv != NONE; Inv = Inv.Inventory) if (Inv.bIsAnArmor) amt += Inv.Charge; nMsg = nMsg $ "Health: " $ Health $ " Armor: " $ amt; break; // друзья - вставляет список друзей, // находящихся в определенном радиусе case "B": numBuddy = 0; foreach RadiusActors(class'Pawn', Buddy, BuddyRadius) { bPRI = Buddy.PlayerReplicationInfo; if (Buddy != Self && Buddy.bIsPlayer && bPRI.Team == mPRI.Team) { lbStr = bPRI.PlayerName; lBuddyLen = Len(lbStr); if (numBuddy < 1) bStr = lbStr; else bStr = bStr $ ", " $ lbStr; numBuddy++; } } // вставляем в список друзей союзы "and" между их именами // в случае если их больше одного. Эх, грамматика, грамматика... if (numBuddy >= 3) bStr = Left(bStr, Len(bStr) - lBuddyLen) $ " and " $ lbStr; else if (numBuddy == 2) bStr = Left(bStr, Len(bStr) - lBuddyLen - 2) $ " and " $ lbStr; else if (numBuddy == 0) bStr = "nobody"; nMsg = nMsg $ bStr; break; // тестовый символ - ничего не вставляет case "T": nMsg = nMsg $ "<test>"; break; // символ '#' - вставляет символ '#' (мало ли - может понадобится :) case "#": nMsg = nMsg $ "#"; break; default: break; } } // если символ не является escape кодом (#), // просто дописываем его в конечную строку else nMsg = nMsg $ Mid(Msg, i, 1); } // и, наконец, возвращаем модифицированное сообщение return nMsg; } |
На этом этапе осталось только "заставить" Ваши функции Say() и TeamSay() вызывать метод ParseChatString(), а затем, для вывода сообщения воспользоваться услугами родительских Say() и TeamSay() функций.
exec function Say( string Msg ) { // подвергаем сообщение модификации Msg = ParseChatString(Msg); // вызываем родительский метод Say() // для вывода нового сообщения на экран Super.Say(Msg); } exec function TeamSay(string Msg) { // подвергаем сообщение модификации Msg = ParseChatString(Msg); // вызываем родительский метод SayTeam() // для вывода нового сообщения на экран Super.TeamSay(Msg); } |
Вот и все. Если Вы хотите использовать это, Вы должны вставить этот скрипт в новый подкласс класса PlayerPawn и затем поменять Ваш ut.ini или создать новый тип игры (GameType), для того, чтобы быть уверенным, что порождается (spawn) именно новый класс... но это уже не укладывается в рамки этого туториала.
Автор
crack_addict
Источник: www.unrealscript.com
Перевод сделан 32_Pistoleta