Darthfett
Aerospace/Cybersecurity Software Engineer
- Reaction score
- 615
Darthfett presents:
Advanced Strings
Advanced Strings
I usually make my systems for whenever I find that I need to be able to do something, and there isn't something already out there. I like having my code relatively neat and easy to read through, so I decided to make an entire system out of common things I need to do with a string.
It started out because I'm creating a lot of text messages, but I don't want to overwhelm the player with a wall of white text. So I decided to make a mini library of common colors I used, with simple variable names for them, instead of an impossible to read |c00ff0000 "Yay" |r, etc.
Then, I started making commands for my map, but I wanted a lot of functionality, such as in my Multi Kick! system. It's never easy to explain to a player in a short message the "proper syntax" for putting in a command, so why not make your system easy for any player to use.
Here's the system, and an example of how I'm using it:
JASS:
//======================
//======================
//Created by Darthfett
//
//Version 1.65
//
//For use with Patch 1.24
//
//9/07/09
//======================
//======================
//======================
//Thanks to AceHart for finding lots of faster ways to do this,
//and for finding the StringCase function <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue :p" loading="lazy" data-shortname=":p" />
//
//Thanks to Romek for pointing out the StringCase(string,true) != StringCase(string,false)
//comparison as a way of knowing whether a string is letters or not.
//Thanks to SerraAvenger for the idea of using GetHandleId on GetPlayerColor, and the idea of dynamic playercolors
//======================
library AdvStrings initializer Init
//=======================
//Commonly used strings
//=======================
globals
constant string END = "|r"
//=========================
//Example defining of strings:
constant string LIGHTYELLOW = "|cffffff00"
constant string YELLOW = "|cffffcc00"
constant string GREEN = "|cff00ff00"
constant string BLUE = "|cff0000ff"
constant string RED = "|cffff0000"
constant string BROWN = "|cffcc9933"
constant string ORANGE = "|cffff6400"
constant string DARKGREEN = "|cff009600"
constant string AQUA = DARKGREEN
constant string DARKBLUE = "|cff000096"
constant string DARKRED = "|cff960000"
constant string DARKTEAL = "|cff009696"
constant string DARKCYAN = DARKTEAL
constant string DARKORANGE = "|cffc86400"
constant string DARKGRAY = "|cff666666"
constant string DARKGREY = DARKGRAY
//Example Usage:
//call BJDebugMsg(YELLOW + "some string" + END)
//call BJDebugMsg(GREEN + "don't kill" + END + RED + " that " + END + GREEN + "unit!" + END)
//=========================
endglobals
globals
//These three are private on PURPOSE! Use the P2CS,I2CS,P2CSN,I2CSN for the playerColorStr and playerColoredName functions.
private string array playerColors //EX: "red", "blue", ... "lightblue"... etc.
private string array playerColorStr //EX: "|cffff0303"
private string array playerColoredName //EX: A player's name colored in their own unit colors
//temp
private integer temp
private string array tempColors
private string array tempColors2
endglobals
//=========================
//String-Type Comparisons -- System independent. Copy and pasta as you need.
//=========================
function IsInt takes string s returns boolean
//Does not Auto-Inline (returns whether a string is an integer, for strings longer than 8, see isNumeric
return I2S(S2I(s)) == s
endfunction
function IsNumeric takes string str returns boolean
//returns whether a string only contains numbers
local integer i = 0
local string s
loop
set s = SubString(str, i, i + 8)
exitwhen s == ""
if I2S(S2I(s)) != s then
return false
endif
set i = i + 8
endloop
return true
endfunction
function IsLetter takes string s returns boolean
//returns whether a character is a letter
return I2S(S2I(s)) == s and StringCase(s,true) != StringCase(s,false)
endfunction
function IsLetters takes string s returns boolean
//returns whether a string only contains letters
local integer i = 0
local string str
loop
set str = SubString(s, i, i + 1)
exitwhen str == ""
if StringCase(s,true) == StringCase(s,false) then
return false
endif
set i = i + 1
endloop
return true
endfunction
function IsMeta takes string s returns boolean
//returns whether a character is a metacharacter
return I2S(S2I(s)) != s and StringCase(s,true) == StringCase(s,false)
endfunction
function IsMetas takes string s returns boolean
//returns whether a string only contains metacharacters
local integer i = 0
local string str
if StringCase(s,true) != StringCase(s,false) then
return false
endif
loop
set str = SubString(s, i, i + 8)
exitwhen str == ""
if I2S(S2I(str)) != str then
return false
endif
set i = i + 8
endloop
return true
endfunction
//===================
// String Formatting -- System independent. Copy and pasta as you need.
//===================
function RemoveChar takes string s, string char returns string
//Removes all instances of one character from an entire string
local integer i = 0
local string str = ""
local string c
loop
set c = SubString(s, i, i + 1)
exitwhen c == ""
if c != char then
set str = str + c
endif
set i = i + 1
endloop
return str
endfunction
function RemoveNumbers takes string s returns string
//Remove all numeric characters from a string
local integer i = 0
local string str = ""
local string c
loop
set c = SubString(s,i,i+1)
exitwhen c == ""
if I2S(S2I(c)) != c then
set str = str + c
endif
set i = i + 1
endloop
return str
endfunction
function RemoveLetters takes string s returns string
//Remove all letters from a string
local integer i = 0
local string str = ""
local string c
loop
set c = SubString(s,i,i+1)
exitwhen c == ""
if StringCase(c,true) == StringCase(c,false) then
set str = str + c
endif
set i = i + 1
endloop
return str
endfunction
function RemoveMetas takes string s returns string
//Remove all meta characters from a string
local integer i = 0
local string str = ""
local string c
loop
set c = SubString(s,i,i+1)
exitwhen c == ""
if I2S(S2I(c)) == c or StringCase(c,true) != StringCase(c,false) then
set str = str + c
endif
set i = i + 1
endloop
return str
endfunction
function RemoveUpper takes string str returns string
//Removes all uppercase letters from a string
local integer i = 0
local string s = ""
local string c
loop
set c = SubString(str,i,i+1)
exitwhen c == ""
if StringCase(c,false) == c then
set s = s + c
endif
set i = i + 1
endloop
return s
endfunction
function RemoveLower takes string str returns string
//Removes all lowercase letters from a string
local integer i = 0
local string s = ""
local string c
loop
set c = SubString(str,i,i+1)
exitwhen c == ""
if StringCase(c,true) == c then
set s = s + c
endif
set i = i + 1
endloop
return s
endfunction
function ReplaceString takes string str, string substr, string replacement returns string
//Finds all instances of substr in str, and replaces them with replacement
local string new
local integer i = 0
local integer strlen = StringLength(str)
local integer sublen = StringLength(substr)
if sublen > strlen then
return str
endif
loop
exitwhen i+sublen > strlen
if SubString(str,i,i+sublen) == substr then
set new = new + SubString(str,i,i+sublen)
else
set new = new + SubString(str,i,i+1)
endif
set i = i + 1
endloop
return new + SubString(str,i,strlen)
endfunction
//================
// String Seeking -- System independent. Copy and pasta as you need.
//================
function StringContainsString takes string str, string partial returns boolean
//Returns true if the full string is contained inside. Capitalization matters!
local integer i = 0
local integer l = StringLength(partial)
local integer l2 = StringLength(str)
loop
exitwhen i > l2
if SubString(str,i,i+l) == partial then
return true
endif
set i = i + 1
endloop
return false
endfunction
function GetStringFirstIndex takes string s, string partial returns integer
//Searches through the string to find the SubString
//If found, it returns the start index
//returns 0 if not found
local integer i = 0
local integer l = StringLength(partial)
local integer l2 = StringLength(s)
loop
exitwhen i >= l2
if SubString(s,i,i+l) == partial then
return i
endif
set i = i + 1
endloop
return 0 //String does not contain string.
//This should never happen if you first check that the string contains the string already.
endfunction
function GetStringLastIndex takes string str, string partial returns integer
//Searches through the string to find the partial string.
//If it finds it, it returns the integer after the index.
//returns 0 if not found
local integer i = 0
local integer l = StringLength(partial)
local integer l2 = StringLength(str)
loop
exitwhen i > l2
if SubString(str,i,i+l) == partial then
return i + l
endif
set i = i + 1
endloop
return 0 //String does not contain string.
//This should never happen if you first check that the string contains the string already.
endfunction
function GetStringToChar takes string str, integer i, string char returns string
//Gets from i, the start of the substring, to the next instance of char, or til the end of the line.
local integer j = i
local integer l = StringLength(str)
local string s = ""
local string c
loop
set c = SubString(str,j,j+1)
exitwhen c == "" or c == char
set s = s + c
set j = j + 1
endloop
return s
endfunction
//===============
//PlayerStrings -- All the playerstring functions require other functions in the library. NOT system indepenent!!
//===============
function P2CS takes player p returns string
//Player to Colored String returns the hex color code of the player's color
return playerColorStr[GetHandleId(GetPlayerColor(p))]
endfunction
function I2CS takes integer i returns string
//Integer to Colored String returns the hex color code of the player's color
return playerColorStr[GetHandleId(GetPlayerColor(Player(i)))]
endfunction
function P2CSN takes player p returns string
//Player to Colored String Name returns the colored player's Name
return playerColorStr[GetHandleId(GetPlayerColor(p))] + GetPlayerName(p) + END
endfunction
function I2CSN takes integer i returns string
//Integer to Colored String Name returns the colored player's Name
return playerColorStr[GetHandleId(GetPlayerColor(Player(i)))] + GetPlayerName(Player(i)) + END
endfunction
function S2P takes string argstr returns player
//String to Player returns a player from a Player's color (e.g. "Blue", "Light Blue", "lIghtBlUe"),
//a player's number (1 for red, 2 for blue),
//a player's name (e.g. "Darthfett"),
//or a piece of a player's name (e.g. "Darth").
//Invalid names return Player(12) (Neutral Passive) in Debug Mode, or null when not in debug mode.
local string s = RemoveChar(StringCase(argstr,false)," ")
local integer i = 0
local playercolor color
if "gray" == s then
loop
exitwhen temp >= 12
if GetPlayerColor(Player(12)) == PLAYER_COLOR_LIGHT_GRAY then
return Player(temp)
endif
set temp = temp + 1
endloop
endif
set temp = S2I(s)
if I2S(temp) == s then
if temp < 13 and temp > 0 then
return Player(temp-1)
else
debug call BJDebugMsg("ERROR: Advanced Strings - S2P: Invalid player number")
debug return Player(12) //to avoid crashes
return null
endif
endif
set temp = 0
loop
exitwhen temp >= 12
if playerColors[temp] == s then
set color = ConvertPlayerColor(temp)
loop
exitwhen i >= 12
if color == GetPlayerColor(Player(i)) then
return Player(i)
endif
set i = i + 1
endloop
endif
set temp = temp + 1
endloop
set temp = 0
loop
exitwhen temp >= 12
if StringContainsString(RemoveChar(StringCase(GetPlayerName(Player(temp)),false)," "),s) then
return Player(temp)
endif
set temp = temp + 1
endloop
debug call BJDebugMsg("ERROR: Advanced Strings - S2P: Invalid player string")
debug return Player(12) //to avoid crashes
return null
endfunction
function S2PI takes string argstr returns integer
//String to PlayerId returns the player number in a similar fashion to that of S2P.
//Invalid arguments in debug mode will return 12, for Player Neutral Passive, or -1 when not in debug mode.
local string s = RemoveChar(StringCase(argstr,false)," ")
local integer i = 0
local playercolor color
if "gray" == s then //simplest comparisons first is the most efficient way, as it means less calculations in some cases.
loop
exitwhen temp >= 12
if GetPlayerColor(Player(12)) == PLAYER_COLOR_LIGHT_GRAY then
return temp
endif
set temp = temp + 1
endloop
endif
set temp = S2I(s)
if I2S(temp) == s then
if temp < 13 and temp > 0 then
return temp-1
else
debug call BJDebugMsg("ERROR: Advanced Strings - S2PI: Invalid player number")
return 0
endif
endif
set temp = 0
loop
exitwhen temp >= 12
if playerColors[temp] == s then
set color = ConvertPlayerColor(temp)
loop
exitwhen i >= 12
if color == GetPlayerColor(Player(i)) then
return i
endif
set i = i + 1
endloop
endif
set temp = temp + 1
endloop
set temp = 0
loop
exitwhen temp >= 12
if StringContainsString(RemoveChar(StringCase(GetPlayerName(Player(temp)),false)," "),s) then
return temp
endif
set temp = temp + 1
endloop
debug call BJDebugMsg("ERROR: Advanced Strings - S2PI: Invalid player number")
return 0
endfunction
//======================
//Initializing Strings -- Used for the Player String functions
//======================
private function Init takes nothing returns nothing
//Variable Initializing
set playerColors[0] = "red"
set playerColors[1] = "blue"
set playerColors[2] = "teal"
set playerColors[3] = "purple"
set playerColors[4] = "yellow"
set playerColors[5] = "orange"
set playerColors[6] = "green"
set playerColors[7] = "pink"
set playerColors[8] = "grey"
set playerColors[9] = "lightblue"
set playerColors[10] = "darkgreen"
set playerColors[11] = "brown"
set playerColorStr[0] = "|cffff0303"
set playerColorStr[1] = "|cff0042ff"
set playerColorStr[2] = "|cff1ce6b9"
set playerColorStr[3] = "|cff540081"
set playerColorStr[4] = "|cfffffc01"
set playerColorStr[5] = "|cfffeba0e"
set playerColorStr[6] = "|cff20c000"
set playerColorStr[7] = "|cffr55bb0"
set playerColorStr[8] = "|cff959697"
set playerColorStr[9] = "|cff7ebff1"
set playerColorStr[10] = "|cff107246"
set playerColorStr[11] = "|cff4e2a04"
endfunction
endlibrary
The "i" variable would be set to the start index, after -zoom, and before the 1000, which is used in the GetStringToChar function. The GetStringToChar function then takes the string, and outputs the number, from the 1 to the 0, since it then reaches the end of the line, or a space.
This is useful when you want players to be able to type multiple commands in one line, such as "-ap -zoom1200" I will admit the example doesn't really work very well here, since zoom is a function you want to be able to say during chat without the game thinking it's a command, but when you need it for setting the number of rounds of a game, for example, it could be useful.
Comments, suggestions, and questions are all welcome!