02-15-12, 08:37 AM | #1 |
Need Lua Coding Help!
Hello!
I'm very new to lua and have been researching the language to learn how to make my first addon, called Blush Response. Please bear with me, as I don't know a lot of the vocabulary programmers use so I might mess up. I'm running into some trouble and was hoping an expert might help me a bit. (I realize there was another addon similar to this called Emote Reply, but it is severely out of date, and I am writing this addon from scratch.) The goal of my addon is to: 1. Trigger an emote response when a player targets you and emotes at you. 2. Make the triggered response fire after a 2-3 second delay, like a timer. 3. Trigger a /shrug or /ponder emote when a member of the opposite faction targets you and uses custom emotes. ie "%N makes strange gestures." 4. Not respond at all when a custom emote is used by another player while targeting you. 5. Allow you to add custom trigger/reply emotes through an in-game UI Frame. 6. Eventually allow random responses either through emote or /say. 7. Eventually allow profiling, especially for custom emotes. My current issue is that I'm stuck at the event handler section of the lua file, specifically where I want to tell my addon to reply with an emote, where the ????? are. Here is what I have so far: function BlushResponseVersion(self) print("They're just questions, Leon. In answer to your query, they're written down for me. It's a test, designed to provoke an emotional response... Shall we continue? --- Addon: Blush Response v. 1.0 successfully loaded!"); end function BlushResponse:OnEvent(event) if event == "CHAT_MSG_TEXT_EMOTE" then DoEmote(?????); elseif event == "CHAT_MSG_EMOTE" then DoEmote(?????); end end So my question here is, what string should go there, and where/how do I add the emote lists for replies and triggers? Any help would be super appreciated. Thanks! Last edited by Savaena : 02-16-12 at 08:59 AM. Reason: added desires to the goal of the addon |
|
02-15-12, 10:20 AM | #2 | |
DoEmote() takes in an emote token string that represents the emote you want to send. Here is a list of tokens taken from ChatFrame.lua line 357.
Code:
-- These are text emote tokens - add new ones at the bottom of the list! EMOTE1_TOKEN = "AGREE"; EMOTE2_TOKEN = "AMAZE"; EMOTE3_TOKEN = "ANGRY"; EMOTE4_TOKEN = "APOLOGIZE"; EMOTE5_TOKEN = "APPLAUD"; EMOTE6_TOKEN = "BASHFUL"; EMOTE7_TOKEN = "BECKON"; EMOTE8_TOKEN = "BEG"; EMOTE9_TOKEN = "BITE"; EMOTE10_TOKEN = "BLEED"; EMOTE11_TOKEN = "BLINK"; EMOTE12_TOKEN = "BLUSH"; EMOTE13_TOKEN = "BONK"; EMOTE14_TOKEN = "BORED"; EMOTE15_TOKEN = "BOUNCE"; EMOTE16_TOKEN = "BRB"; EMOTE17_TOKEN = "BOW"; EMOTE18_TOKEN = "BURP"; EMOTE19_TOKEN = "BYE"; EMOTE20_TOKEN = "CACKLE"; EMOTE21_TOKEN = "CHEER"; EMOTE22_TOKEN = "CHICKEN"; EMOTE23_TOKEN = "CHUCKLE"; EMOTE24_TOKEN = "CLAP"; EMOTE25_TOKEN = "CONFUSED"; EMOTE26_TOKEN = "CONGRATULATE"; EMOTE27_TOKEN = "UNUSED"; EMOTE28_TOKEN = "COUGH"; EMOTE29_TOKEN = "COWER"; EMOTE30_TOKEN = "CRACK"; EMOTE31_TOKEN = "CRINGE"; EMOTE32_TOKEN = "CRY"; EMOTE33_TOKEN = "CURIOUS"; EMOTE34_TOKEN = "CURTSEY"; EMOTE35_TOKEN = "DANCE"; EMOTE36_TOKEN = "DRINK"; EMOTE37_TOKEN = "DROOL"; EMOTE38_TOKEN = "EAT"; EMOTE39_TOKEN = "EYE"; EMOTE40_TOKEN = "FART"; EMOTE41_TOKEN = "FIDGET"; EMOTE42_TOKEN = "FLEX"; EMOTE43_TOKEN = "FROWN"; EMOTE44_TOKEN = "GASP"; EMOTE45_TOKEN = "GAZE"; EMOTE46_TOKEN = "GIGGLE"; EMOTE47_TOKEN = "GLARE"; EMOTE48_TOKEN = "GLOAT"; EMOTE49_TOKEN = "GREET"; EMOTE50_TOKEN = "GRIN"; EMOTE51_TOKEN = "GROAN"; EMOTE52_TOKEN = "GROVEL"; EMOTE53_TOKEN = "GUFFAW"; EMOTE54_TOKEN = "HAIL"; EMOTE55_TOKEN = "HAPPY"; EMOTE56_TOKEN = "HELLO"; EMOTE57_TOKEN = "HUG"; EMOTE58_TOKEN = "HUNGRY"; EMOTE59_TOKEN = "KISS"; EMOTE60_TOKEN = "KNEEL"; EMOTE61_TOKEN = "LAUGH"; EMOTE62_TOKEN = "LAYDOWN"; EMOTE63_TOKEN = "MASSAGE"; EMOTE64_TOKEN = "MOAN"; EMOTE65_TOKEN = "MOON"; EMOTE66_TOKEN = "MOURN"; EMOTE67_TOKEN = "NO"; EMOTE68_TOKEN = "NOD"; EMOTE69_TOKEN = "NOSEPICK"; EMOTE70_TOKEN = "PANIC"; EMOTE71_TOKEN = "PEER"; EMOTE72_TOKEN = "PLEAD"; EMOTE73_TOKEN = "POINT"; EMOTE74_TOKEN = "POKE"; EMOTE75_TOKEN = "PRAY"; EMOTE76_TOKEN = "ROAR"; EMOTE77_TOKEN = "ROFL"; EMOTE78_TOKEN = "RUDE"; EMOTE79_TOKEN = "SALUTE"; EMOTE80_TOKEN = "SCRATCH"; EMOTE81_TOKEN = "SEXY"; EMOTE82_TOKEN = "SHAKE"; EMOTE83_TOKEN = "SHOUT"; EMOTE84_TOKEN = "SHRUG"; EMOTE85_TOKEN = "SHY"; EMOTE86_TOKEN = "SIGH"; EMOTE87_TOKEN = "SIT"; EMOTE88_TOKEN = "SLEEP"; EMOTE89_TOKEN = "SNARL"; EMOTE90_TOKEN = "SPIT"; EMOTE91_TOKEN = "STARE"; EMOTE92_TOKEN = "SURPRISED"; EMOTE93_TOKEN = "SURRENDER"; EMOTE94_TOKEN = "TALK"; EMOTE95_TOKEN = "TALKEX"; EMOTE96_TOKEN = "TALKQ"; EMOTE97_TOKEN = "TAP"; EMOTE98_TOKEN = "THANK"; EMOTE99_TOKEN = "THREATEN"; EMOTE100_TOKEN = "TIRED"; EMOTE101_TOKEN = "VICTORY"; EMOTE102_TOKEN = "WAVE"; EMOTE103_TOKEN = "WELCOME"; EMOTE104_TOKEN = "WHINE"; EMOTE105_TOKEN = "WHISTLE"; EMOTE106_TOKEN = "WORK"; EMOTE107_TOKEN = "YAWN"; EMOTE108_TOKEN = "BOGGLE"; EMOTE109_TOKEN = "CALM"; EMOTE110_TOKEN = "COLD"; EMOTE111_TOKEN = "COMFORT"; EMOTE112_TOKEN = "CUDDLE"; EMOTE113_TOKEN = "DUCK"; EMOTE114_TOKEN = "INSULT"; EMOTE115_TOKEN = "INTRODUCE"; EMOTE116_TOKEN = "JK"; EMOTE117_TOKEN = "LICK"; EMOTE118_TOKEN = "LISTEN"; EMOTE119_TOKEN = "LOST"; EMOTE120_TOKEN = "MOCK"; EMOTE121_TOKEN = "PONDER"; EMOTE122_TOKEN = "POUNCE"; EMOTE123_TOKEN = "PRAISE"; EMOTE124_TOKEN = "PURR"; EMOTE125_TOKEN = "PUZZLE"; EMOTE126_TOKEN = "RAISE"; EMOTE127_TOKEN = "READY"; EMOTE128_TOKEN = "SHIMMY"; EMOTE129_TOKEN = "SHIVER"; EMOTE130_TOKEN = "SHOO"; EMOTE131_TOKEN = "SLAP"; EMOTE132_TOKEN = "SMIRK"; EMOTE133_TOKEN = "SNIFF"; EMOTE134_TOKEN = "SNUB"; EMOTE135_TOKEN = "SOOTHE"; EMOTE136_TOKEN = "STINK"; EMOTE137_TOKEN = "TAUNT"; EMOTE138_TOKEN = "TEASE"; EMOTE139_TOKEN = "THIRSTY"; EMOTE140_TOKEN = "VETO"; EMOTE141_TOKEN = "SNICKER"; EMOTE142_TOKEN = "TICKLE"; EMOTE143_TOKEN = "STAND"; EMOTE144_TOKEN = "VIOLIN"; EMOTE145_TOKEN = "SMILE"; EMOTE146_TOKEN = "RASP"; EMOTE147_TOKEN = "GROWL"; EMOTE148_TOKEN = "BARK"; EMOTE149_TOKEN = "PITY"; EMOTE150_TOKEN = "SCARED"; EMOTE151_TOKEN = "FLOP"; EMOTE152_TOKEN = "LOVE"; EMOTE153_TOKEN = "MOO"; EMOTE154_TOKEN = "COMMEND"; EMOTE155_TOKEN = "TRAIN"; EMOTE156_TOKEN = "HELPME"; EMOTE157_TOKEN = "INCOMING"; EMOTE158_TOKEN = "OPENFIRE"; EMOTE159_TOKEN = "CHARGE"; EMOTE160_TOKEN = "FLEE"; EMOTE161_TOKEN = "ATTACKMYTARGET"; EMOTE162_TOKEN = "OOM"; EMOTE163_TOKEN = "FOLLOW"; EMOTE164_TOKEN = "WAIT"; EMOTE165_TOKEN = "FLIRT"; EMOTE166_TOKEN = "HEALME"; EMOTE167_TOKEN = "JOKE"; EMOTE168_TOKEN = "WINK"; EMOTE169_TOKEN = "PAT"; EMOTE170_TOKEN = "GOLFCLAP"; EMOTE171_TOKEN = "MOUNTSPECIAL"; EMOTE304_TOKEN = "INCOMING"; EMOTE306_TOKEN = "FLEE"; EMOTE368_TOKEN = "BLAME" EMOTE369_TOKEN = "BLANK" EMOTE370_TOKEN = "BRANDISH" EMOTE371_TOKEN = "BREATH" EMOTE372_TOKEN = "DISAGREE" EMOTE373_TOKEN = "DOUBT" EMOTE374_TOKEN = "EMBARRASS" EMOTE375_TOKEN = "ENCOURAGE" EMOTE376_TOKEN = "ENEMY" EMOTE377_TOKEN = "EYEBROW" EMOTE380_TOKEN = "HIGHFIVE" EMOTE381_TOKEN = "ABSENT" EMOTE382_TOKEN = "ARM" EMOTE383_TOKEN = "AWE" EMOTE384_TOKEN = "BACKPACK" EMOTE385_TOKEN = "BADFEELING" EMOTE386_TOKEN = "CHALLENGE" EMOTE387_TOKEN = "CHUG" EMOTE389_TOKEN = "DING" EMOTE390_TOKEN = "FACEPALM" EMOTE391_TOKEN = "FAINT" EMOTE392_TOKEN = "GO" EMOTE393_TOKEN = "GOING" EMOTE394_TOKEN = "GLOWER" EMOTE395_TOKEN = "HEADACHE" EMOTE396_TOKEN = "HICCUP" EMOTE398_TOKEN = "HISS" EMOTE399_TOKEN = "HOLDHAND" EMOTE401_TOKEN = "HURRY" EMOTE402_TOKEN = "IDEA" EMOTE403_TOKEN = "JEALOUS" EMOTE404_TOKEN = "LUCK" EMOTE405_TOKEN = "MAP" EMOTE406_TOKEN = "MERCY" EMOTE407_TOKEN = "MUTTER" EMOTE408_TOKEN = "NERVOUS" EMOTE409_TOKEN = "OFFER" EMOTE410_TOKEN = "PET" EMOTE411_TOKEN = "PINCH" EMOTE413_TOKEN = "PROUD" EMOTE414_TOKEN = "PROMISE" EMOTE415_TOKEN = "PULSE" EMOTE416_TOKEN = "PUNCH" EMOTE417_TOKEN = "POUT" EMOTE418_TOKEN = "REGRET" EMOTE420_TOKEN = "REVENGE" EMOTE421_TOKEN = "ROLLEYES" EMOTE422_TOKEN = "RUFFLE" EMOTE423_TOKEN = "SAD" EMOTE424_TOKEN = "SCOFF" EMOTE425_TOKEN = "SCOLD" EMOTE426_TOKEN = "SCOWL" EMOTE427_TOKEN = "SEARCH" EMOTE428_TOKEN = "SHAKEFIST" EMOTE429_TOKEN = "SHIFTY" EMOTE430_TOKEN = "SHUDDER" EMOTE431_TOKEN = "SIGNAL" EMOTE432_TOKEN = "SILENCE" EMOTE433_TOKEN = "SING" EMOTE434_TOKEN = "SMACK" EMOTE435_TOKEN = "SNEAK" EMOTE436_TOKEN = "SNEEZE" EMOTE437_TOKEN = "SNORT" EMOTE438_TOKEN = "SQUEAL" EMOTE440_TOKEN = "SUSPICIOUS" EMOTE441_TOKEN = "THINK" EMOTE442_TOKEN = "TRUCE" EMOTE443_TOKEN = "TWIDDLE" EMOTE444_TOKEN = "WARN" EMOTE445_TOKEN = "SNAP" EMOTE446_TOKEN = "CHARM" EMOTE447_TOKEN = "COVEREARS" EMOTE448_TOKEN = "CROSSARMS" EMOTE449_TOKEN = "LOOK" EMOTE450_TOKEN = "OBJECT" EMOTE451_TOKEN = "SWEAT" EMOTE452_TOKEN = "YW" EMOTE453_TOKEN = "READ" Notice the tokens are assigned to globals in the format EMOTE<TokenID>_TOKEN. If you look up in this list for the same <TokenID>, you can find the corresponding slash commands assigned to globals in the format EMOTE<TokenID>_CMD<Index>. Note <Index> is just a sequential number with no other use than to allow more than one slash command to be registered for a token. The following is taken from GlobalStrings.lua line 2467. Code:
EMOTE100_CMD1 = "/tired"; EMOTE100_CMD2 = "/tired"; EMOTE101_CMD = "/victory"; EMOTE101_CMD1 = "/victory"; EMOTE101_CMD2 = "/victory"; EMOTE101_CMD3 = "/victory"; EMOTE102_CMD1 = "/wave"; EMOTE102_CMD2 = "/wave"; EMOTE103_CMD1 = "/welcome"; EMOTE103_CMD2 = "/welcome"; EMOTE104_CMD1 = "/whine"; EMOTE104_CMD2 = "/whine"; EMOTE105_CMD1 = "/whistle"; EMOTE105_CMD2 = "/whistle"; EMOTE106_CMD1 = "/work"; EMOTE106_CMD2 = "/work"; EMOTE107_CMD1 = "/yawn"; EMOTE107_CMD2 = "/yawn"; EMOTE107_CMD3 = "/yawn"; EMOTE108_CMD1 = "/boggle"; EMOTE108_CMD2 = "/boggle"; EMOTE109_CMD1 = "/calm"; EMOTE109_CMD2 = "/calm"; EMOTE109_CMD3 = "/calm"; EMOTE10_CMD1 = "/bleed"; EMOTE10_CMD2 = "/blood"; EMOTE10_CMD3 = "/bleed"; EMOTE10_CMD4 = "/blood"; EMOTE110_CMD1 = "/cold"; EMOTE110_CMD2 = "/cold"; EMOTE111_CMD1 = "/comfort"; EMOTE111_CMD2 = "/comfort"; EMOTE112_CMD1 = "/cuddle"; EMOTE112_CMD2 = "/spoon"; EMOTE112_CMD3 = "/cuddle"; EMOTE112_CMD4 = "/spoon"; EMOTE113_CMD1 = "/duck"; EMOTE113_CMD2 = "/duck"; EMOTE114_CMD1 = "/insult"; EMOTE114_CMD2 = "/insult"; EMOTE114_CMD3 = "/insult"; EMOTE115_CMD1 = "/introduce"; EMOTE115_CMD2 = "/introduce"; EMOTE116_CMD1 = "/jk"; EMOTE116_CMD2 = "/jk"; EMOTE117_CMD1 = "/lick"; EMOTE117_CMD2 = "/lick"; EMOTE118_CMD1 = "/listen"; EMOTE118_CMD2 = "/listen"; EMOTE119_CMD1 = "/lost"; EMOTE119_CMD2 = "/lost"; EMOTE11_CMD1 = "/blink"; EMOTE11_CMD2 = "/blink"; EMOTE120_CMD1 = "/mock"; EMOTE120_CMD2 = "/mock"; EMOTE121_CMD1 = "/ponder"; EMOTE121_CMD2 = "/ponder"; EMOTE122_CMD1 = "/pounce"; EMOTE122_CMD2 = "/pounce"; EMOTE123_CMD1 = "/praise"; EMOTE123_CMD2 = "/lavish"; EMOTE123_CMD3 = "/praise"; EMOTE123_CMD4 = "/lavish"; EMOTE124_CMD1 = "/purr"; EMOTE124_CMD2 = "/purr"; EMOTE125_CMD1 = "/puzzled"; EMOTE125_CMD2 = "/puzzled"; EMOTE126_CMD1 = "/raise"; EMOTE126_CMD2 = "/volunteer"; EMOTE126_CMD3 = "/raise"; EMOTE126_CMD4 = "/volunteer"; EMOTE127_CMD1 = "/ready"; EMOTE127_CMD2 = "/rdy"; EMOTE127_CMD3 = "/ready"; EMOTE127_CMD4 = "/rdy"; EMOTE128_CMD1 = "/shimmy"; EMOTE128_CMD2 = "/shimmy"; EMOTE129_CMD1 = "/shiver"; EMOTE129_CMD2 = "/shiver"; EMOTE12_CMD1 = "/blush"; EMOTE12_CMD2 = "/blush"; EMOTE130_CMD1 = "/shoo"; EMOTE130_CMD2 = "/pest"; EMOTE130_CMD3 = "/shoo"; EMOTE130_CMD4 = "/pest"; EMOTE131_CMD1 = "/slap"; EMOTE131_CMD2 = "/slap"; EMOTE132_CMD1 = "/smirk"; EMOTE132_CMD2 = "/smirk"; EMOTE133_CMD1 = "/sniff"; EMOTE133_CMD2 = "/sniff"; EMOTE134_CMD1 = "/snub"; EMOTE134_CMD2 = "/snub"; EMOTE135_CMD1 = "/soothe"; EMOTE135_CMD2 = "/soothe"; EMOTE136_CMD1 = "/stink"; EMOTE136_CMD2 = "/smell"; EMOTE136_CMD3 = "/stink"; EMOTE136_CMD4 = "/smell"; EMOTE137_CMD1 = "/taunt"; EMOTE137_CMD2 = "/taunt"; EMOTE138_CMD1 = "/tease"; EMOTE138_CMD2 = "/tease"; EMOTE139_CMD1 = "/thirsty"; EMOTE139_CMD2 = "/thirsty"; EMOTE13_CMD1 = "/bonk"; EMOTE13_CMD2 = "/doh"; EMOTE13_CMD3 = "/bonk"; EMOTE13_CMD4 = "/doh"; EMOTE140_CMD1 = "/veto"; EMOTE140_CMD2 = "/veto"; EMOTE141_CMD1 = "/snicker"; EMOTE141_CMD2 = "/snicker"; EMOTE142_CMD1 = "/tickle"; EMOTE142_CMD2 = "/tickle"; EMOTE143_CMD1 = "/stand"; EMOTE143_CMD2 = "/stand"; EMOTE144_CMD1 = "/violin"; EMOTE144_CMD2 = "/violin"; EMOTE145_CMD1 = "/smile"; EMOTE145_CMD2 = "/smile"; EMOTE146_CMD1 = "/rasp"; EMOTE146_CMD2 = "/rasp"; EMOTE147_CMD1 = "/growl"; EMOTE147_CMD2 = "/growl"; EMOTE148_CMD1 = "/bark"; EMOTE148_CMD2 = "/bark"; EMOTE149_CMD1 = "/pity"; EMOTE149_CMD2 = "/pity"; EMOTE14_CMD1 = "/bored"; EMOTE14_CMD2 = "/bored"; EMOTE150_CMD1 = "/scared"; EMOTE150_CMD2 = "/scared"; EMOTE151_CMD1 = "/flop"; EMOTE151_CMD2 = "/flop"; EMOTE152_CMD1 = "/love"; EMOTE152_CMD2 = "/love"; EMOTE153_CMD1 = "/moo"; EMOTE153_CMD2 = "/moo"; EMOTE154_CMD1 = "/commend"; EMOTE154_CMD2 = "/commend"; EMOTE155_CMD1 = "/train"; EMOTE155_CMD2 = "/train"; EMOTE156_CMD1 = "/helpme"; EMOTE156_CMD2 = "/helpme"; EMOTE157_CMD1 = "/incoming"; EMOTE157_CMD2 = "/incoming"; EMOTE158_CMD1 = "/openfire"; EMOTE158_CMD2 = "/openfire"; EMOTE159_CMD1 = "/charge"; EMOTE159_CMD2 = "/charge"; EMOTE15_CMD1 = "/bounce"; EMOTE15_CMD2 = "/bounce"; EMOTE160_CMD1 = "/flee"; EMOTE160_CMD2 = "/flee"; EMOTE161_CMD1 = "/attacktarget"; EMOTE161_CMD2 = "/attacktarget"; EMOTE162_CMD1 = "/oom"; EMOTE162_CMD2 = "/oom"; EMOTE163_CMD1 = "/followme"; EMOTE163_CMD2 = "/followme"; EMOTE164_CMD1 = "/wait"; EMOTE164_CMD2 = "/wait"; EMOTE165_CMD1 = "/flirt"; EMOTE165_CMD2 = "/flirt"; EMOTE166_CMD1 = "/healme"; EMOTE166_CMD2 = "/healme"; EMOTE167_CMD1 = "/silly"; EMOTE167_CMD2 = "/silly"; EMOTE168_CMD1 = "/wink"; EMOTE168_CMD2 = "/wink"; EMOTE169_CMD1 = "/pat"; EMOTE169_CMD2 = "/pat"; EMOTE16_CMD1 = "/brb"; EMOTE16_CMD2 = "/brb"; EMOTE170_CMD1 = "/golfclap"; EMOTE170_CMD2 = "/golfclap"; EMOTE171_CMD1 = "/mountspecial"; EMOTE171_CMD2 = "/mountspecial"; EMOTE17_CMD1 = "/bow"; EMOTE17_CMD2 = "/bow"; EMOTE18_CMD1 = "/burp"; EMOTE18_CMD2 = "/belch"; EMOTE18_CMD3 = "/burp"; EMOTE18_CMD4 = "/belch"; EMOTE19_CMD1 = "/bye"; EMOTE19_CMD2 = "/goodbye"; EMOTE19_CMD3 = "/farewell"; EMOTE19_CMD4 = "/bye"; EMOTE19_CMD5 = "/goodbye"; EMOTE19_CMD6 = "/farewell"; EMOTE1_CMD1 = "/agree"; EMOTE1_CMD2 = "/agree"; EMOTE20_CMD1 = "/cackle"; EMOTE20_CMD2 = "/cackle"; EMOTE21_CMD1 = "/cheer"; EMOTE21_CMD2 = "/cheer"; EMOTE21_CMD3 = "/woot"; EMOTE21_CMD4 = "/woot"; EMOTE22_CMD1 = "/chicken"; EMOTE22_CMD2 = "/flap"; EMOTE22_CMD3 = "/strut"; EMOTE22_CMD4 = "/chicken"; EMOTE22_CMD5 = "/flap"; EMOTE22_CMD6 = "/strut"; EMOTE23_CMD1 = "/chuckle"; EMOTE23_CMD2 = "/chuckle"; EMOTE24_CMD1 = "/clap"; EMOTE24_CMD2 = "/clap"; EMOTE25_CMD1 = "/confused"; EMOTE25_CMD2 = "/confused"; EMOTE26_CMD1 = "/congratulate"; EMOTE26_CMD2 = "/congrats"; EMOTE26_CMD3 = "/cong"; EMOTE26_CMD4 = "/congratulate"; EMOTE26_CMD5 = "/grats"; EMOTE26_CMD6 = "/cong"; EMOTE27_CMD1 = "/unused"; EMOTE27_CMD2 = "/unused"; EMOTE28_CMD1 = "/cough"; EMOTE28_CMD2 = "/cough"; EMOTE29_CMD1 = "/cower"; EMOTE29_CMD2 = "/fear"; EMOTE29_CMD3 = "/cower"; EMOTE29_CMD4 = "/fear"; EMOTE2_CMD1 = "/amaze"; EMOTE2_CMD2 = "/amaze"; EMOTE304_CMD1 = "/incoming"; EMOTE304_CMD3 = "/incoming"; EMOTE304_CMD4 = "/inc"; EMOTE306_CMD1 = "/retreat"; EMOTE306_CMD2 = "/retreat"; EMOTE306_CMD3 = "/flee"; EMOTE306_CMD4 = "/flee"; EMOTE30_CMD1 = "/crack"; EMOTE30_CMD2 = "/knuckles"; EMOTE30_CMD3 = "/crack"; EMOTE30_CMD4 = "/knuckles"; EMOTE31_CMD1 = "/cringe"; EMOTE31_CMD2 = "/cringe"; EMOTE32_CMD1 = "/cry"; EMOTE32_CMD2 = "/sob"; EMOTE32_CMD3 = "/weep"; EMOTE32_CMD4 = "/cry"; EMOTE32_CMD5 = "/sob"; EMOTE32_CMD6 = "/weep"; EMOTE33_CMD1 = "/curious"; EMOTE33_CMD2 = "/curious"; EMOTE34_CMD1 = "/curtsey"; EMOTE34_CMD2 = "/curtsey"; EMOTE35_CMD1 = "/dance"; EMOTE35_CMD2 = "/dance"; EMOTE368_CMD1 = "/blame"; EMOTE368_CMD2 = "/blame"; EMOTE369_CMD1 = "/blank"; EMOTE369_CMD2 = "/blank"; EMOTE36_CMD1 = "/drink"; EMOTE36_CMD2 = "/shindig"; EMOTE36_CMD3 = "/drink"; EMOTE36_CMD4 = "/shindig"; EMOTE370_CMD1 = "/brandish"; EMOTE370_CMD2 = "/brandish"; EMOTE371_CMD1 = "/breath"; EMOTE371_CMD2 = "/breath"; EMOTE372_CMD1 = "/disagree"; EMOTE372_CMD2 = "/disagree"; EMOTE373_CMD1 = "/doubt"; EMOTE373_CMD2 = "/doubt"; EMOTE374_CMD1 = "/embarrass"; EMOTE374_CMD2 = "/embarrass"; EMOTE375_CMD1 = "/encourage"; EMOTE375_CMD2 = "/encourage"; EMOTE376_CMD1 = "/enemy"; EMOTE376_CMD2 = "/enemy"; EMOTE377_CMD1 = "/eyebrow"; EMOTE377_CMD2 = "/eyebrow"; EMOTE377_CMD3 = "/brow"; EMOTE377_CMD4 = "/brow"; EMOTE37_CMD1 = "/drool"; EMOTE37_CMD2 = "/drool"; EMOTE380_CMD1 = "/highfive"; EMOTE380_CMD2 = "/highfive"; EMOTE381_CMD1 = "/absent"; EMOTE381_CMD2 = "/absent"; EMOTE382_CMD1 = "/arm"; EMOTE382_CMD2 = "/arm"; EMOTE383_CMD1 = "/awe"; EMOTE383_CMD2 = "/awe"; EMOTE384_CMD1 = "/backpack"; EMOTE384_CMD2 = "/backpack"; EMOTE384_CMD3 = "/pack"; EMOTE384_CMD4 = "/pack"; EMOTE385_CMD1 = "/badfeeling"; EMOTE385_CMD2 = "/badfeeling"; EMOTE385_CMD3 = "/bad"; EMOTE385_CMD4 = "/bad"; EMOTE386_CMD1 = "/challenge"; EMOTE386_CMD2 = "/challenge"; EMOTE387_CMD1 = "/chug"; EMOTE387_CMD2 = "/chug"; EMOTE389_CMD1 = "/ding"; EMOTE389_CMD2 = "/ding"; EMOTE38_CMD1 = "/eat"; EMOTE38_CMD2 = "/chew"; EMOTE38_CMD3 = "/feast"; EMOTE38_CMD4 = "/eat"; EMOTE38_CMD5 = "/chew"; EMOTE38_CMD6 = "/feast"; EMOTE390_CMD1 = "/facepalm"; EMOTE390_CMD2 = "/facepalm"; EMOTE390_CMD3 = "/palm"; EMOTE390_CMD4 = "/palm"; EMOTE391_CMD1 = "/faint"; EMOTE391_CMD2 = "/faint"; EMOTE392_CMD1 = "/go"; EMOTE392_CMD2 = "/go"; EMOTE393_CMD1 = "/going"; EMOTE393_CMD2 = "/going"; EMOTE394_CMD1 = "/glower"; EMOTE394_CMD2 = "/glower"; EMOTE395_CMD1 = "/headache"; EMOTE395_CMD2 = "/headache"; EMOTE396_CMD1 = "/hiccup"; EMOTE396_CMD2 = "/hiccup"; EMOTE398_CMD1 = "/hiss"; EMOTE398_CMD2 = "/hiss"; EMOTE399_CMD1 = "/holdhand"; EMOTE399_CMD2 = "/holdhand"; EMOTE39_CMD1 = "/eye"; EMOTE39_CMD2 = "/eye"; EMOTE3_CMD1 = "/angry"; EMOTE3_CMD2 = "/mad"; EMOTE3_CMD3 = "/angry"; EMOTE3_CMD4 = "/mad"; EMOTE401_CMD1 = "/hurry"; EMOTE401_CMD2 = "/hurry"; EMOTE402_CMD1 = "/idea"; EMOTE402_CMD2 = "/idea"; EMOTE403_CMD1 = "/jealous"; EMOTE403_CMD2 = "/jealous"; EMOTE404_CMD1 = "/luck"; EMOTE404_CMD2 = "/luck"; EMOTE405_CMD1 = "/map"; EMOTE405_CMD2 = "/map"; EMOTE406_CMD1 = "/mercy"; EMOTE406_CMD2 = "/mercy"; EMOTE407_CMD1 = "/mutter"; EMOTE407_CMD2 = "/mutter"; EMOTE408_CMD1 = "/nervous"; EMOTE408_CMD2 = "/nervous"; EMOTE409_CMD1 = "/offer"; EMOTE409_CMD2 = "/offer"; EMOTE40_CMD1 = "/fart"; EMOTE40_CMD2 = "/fart"; EMOTE410_CMD1 = "/pet"; EMOTE410_CMD2 = "/pet"; EMOTE411_CMD1 = "/pinch"; EMOTE411_CMD2 = "/pinch"; EMOTE413_CMD1 = "/proud"; EMOTE413_CMD2 = "/proud"; EMOTE414_CMD1 = "/promise"; EMOTE414_CMD2 = "/promise"; EMOTE415_CMD1 = "/pulse"; EMOTE415_CMD2 = "/pulse"; EMOTE416_CMD1 = "/punch"; EMOTE416_CMD2 = "/punch"; EMOTE417_CMD1 = "/pout"; EMOTE417_CMD2 = "/pout"; EMOTE418_CMD1 = "/regret"; EMOTE418_CMD2 = "/regret"; EMOTE41_CMD1 = "/fidget"; EMOTE41_CMD2 = "/impatient"; EMOTE41_CMD3 = "/fidget"; EMOTE41_CMD4 = "/impatient"; EMOTE420_CMD1 = "/revenge"; EMOTE420_CMD2 = "/revenge"; EMOTE421_CMD1 = "/rolleyes"; EMOTE421_CMD2 = "/rolleyes"; EMOTE421_CMD3 = "/eyeroll"; EMOTE421_CMD4 = "/eyeroll"; EMOTE422_CMD1 = "/ruffle"; EMOTE422_CMD2 = "/ruffle"; EMOTE423_CMD1 = "/sad"; EMOTE423_CMD2 = "/sad"; EMOTE424_CMD1 = "/scoff"; EMOTE424_CMD2 = "/scoff"; EMOTE425_CMD1 = "/scold"; EMOTE425_CMD2 = "/scold"; EMOTE426_CMD1 = "/scowl"; EMOTE426_CMD2 = "/scowl"; EMOTE427_CMD1 = "/search"; EMOTE427_CMD2 = "/search"; EMOTE428_CMD1 = "/shakefist"; EMOTE428_CMD2 = "/shakefist"; EMOTE428_CMD3 = "/fist"; EMOTE428_CMD4 = "/fist"; EMOTE429_CMD1 = "/shifty"; EMOTE429_CMD2 = "/shifty"; EMOTE42_CMD1 = "/flex"; EMOTE42_CMD2 = "/strong"; EMOTE42_CMD3 = "/flex"; EMOTE42_CMD4 = "/strong"; EMOTE430_CMD1 = "/shudder"; EMOTE430_CMD2 = "/shudder"; EMOTE431_CMD1 = "/signal"; EMOTE431_CMD2 = "/signal"; EMOTE432_CMD1 = "/silence"; EMOTE432_CMD2 = "/silence"; EMOTE432_CMD3 = "/shush"; EMOTE432_CMD4 = "/shush"; EMOTE433_CMD1 = "/sing"; EMOTE433_CMD2 = "/sing"; EMOTE434_CMD1 = "/smack"; EMOTE434_CMD2 = "/smack"; EMOTE435_CMD1 = "/sneak"; EMOTE435_CMD2 = "/sneak"; EMOTE436_CMD1 = "/sneeze"; EMOTE436_CMD2 = "/sneeze"; EMOTE437_CMD1 = "/snort"; EMOTE437_CMD2 = "/snort"; EMOTE438_CMD1 = "/squeal"; EMOTE438_CMD2 = "/squeal"; EMOTE43_CMD1 = "/frown"; EMOTE43_CMD2 = "/disappointed"; EMOTE43_CMD3 = "/disappointment"; EMOTE43_CMD4 = "/frown"; EMOTE43_CMD5 = "/disappointed"; EMOTE43_CMD6 = "/disappointment"; EMOTE440_CMD1 = "/suspicious"; EMOTE440_CMD2 = "/suspicious"; EMOTE441_CMD1 = "/think"; EMOTE441_CMD2 = "/think"; EMOTE442_CMD1 = "/truce"; EMOTE442_CMD2 = "/truce"; EMOTE443_CMD1 = "/twiddle"; EMOTE443_CMD2 = "/twiddle"; EMOTE444_CMD1 = "/warn"; EMOTE444_CMD2 = "/warn"; EMOTE445_CMD1 = "/snap"; EMOTE445_CMD2 = "/snap"; EMOTE446_CMD1 = "/charm"; EMOTE446_CMD2 = "/charm"; EMOTE447_CMD1 = "/coverears"; EMOTE447_CMD2 = "/coverears"; EMOTE448_CMD1 = "/crossarms"; EMOTE448_CMD2 = "/crossarms"; EMOTE449_CMD1 = "/look"; EMOTE449_CMD2 = "/look"; EMOTE44_CMD1 = "/gasp"; EMOTE44_CMD2 = "/gasp"; EMOTE44_CMD3 = "/gasp"; EMOTE450_CMD1 = "/object"; EMOTE450_CMD2 = "/object"; EMOTE450_CMD3 = "/objection"; EMOTE450_CMD4 = "/objection"; EMOTE450_CMD5 = "/holdit"; EMOTE450_CMD6 = "/holdit"; EMOTE451_CMD1 = "/sweat"; EMOTE451_CMD2 = "/sweat"; EMOTE452_CMD1 = "/yw"; EMOTE452_CMD2 = "/yw"; EMOTE453_CMD1 = "/read"; EMOTE453_CMD2 = "/read"; EMOTE45_CMD1 = "/gaze"; EMOTE45_CMD2 = "/gaze"; EMOTE46_CMD1 = "/giggle"; EMOTE46_CMD2 = "/giggle"; EMOTE47_CMD1 = "/glare"; EMOTE47_CMD2 = "/glare"; EMOTE48_CMD1 = "/gloat"; EMOTE48_CMD2 = "/gloat"; EMOTE49_CMD1 = "/greet"; EMOTE49_CMD2 = "/greetings"; EMOTE49_CMD3 = "/greet"; EMOTE49_CMD4 = "/greetings"; EMOTE4_CMD1 = "/apologize"; EMOTE4_CMD2 = "/sorry"; EMOTE4_CMD3 = "/apologize"; EMOTE4_CMD4 = "/sorry"; EMOTE50_CMD1 = "/grin"; EMOTE50_CMD2 = "/wicked"; EMOTE50_CMD3 = "/wickedly"; EMOTE50_CMD4 = "/grin"; EMOTE50_CMD5 = "/wicked"; EMOTE50_CMD6 = "/wickedly"; EMOTE51_CMD1 = "/groan"; EMOTE51_CMD2 = "/groan"; EMOTE52_CMD1 = "/grovel"; EMOTE52_CMD2 = "/peon"; EMOTE52_CMD3 = "/grovel"; EMOTE52_CMD4 = "/peon"; EMOTE53_CMD1 = "/guffaw"; EMOTE53_CMD2 = "/guffaw"; EMOTE54_CMD1 = "/hail"; EMOTE54_CMD2 = "/hail"; EMOTE55_CMD1 = "/happy"; EMOTE55_CMD2 = "/glad"; EMOTE55_CMD3 = "/yay"; EMOTE55_CMD4 = "/happy"; EMOTE55_CMD5 = "/glad"; EMOTE55_CMD6 = "/yay"; EMOTE56_CMD1 = "/hello"; EMOTE56_CMD2 = "/hi"; EMOTE56_CMD3 = "/hello"; EMOTE56_CMD4 = "/hi"; EMOTE57_CMD1 = "/hug"; EMOTE57_CMD2 = "/hug"; EMOTE58_CMD1 = "/hungry"; EMOTE58_CMD2 = "/food"; EMOTE58_CMD3 = "/hungry"; EMOTE58_CMD4 = "/food"; EMOTE58_CMD5 = "/pizza"; EMOTE58_CMD6 = "/pizza"; EMOTE59_CMD1 = "/kiss"; EMOTE59_CMD2 = "/blow"; EMOTE59_CMD3 = "/kiss"; EMOTE59_CMD4 = "/blow"; EMOTE5_CMD1 = "/applaud"; EMOTE5_CMD2 = "/bravo"; EMOTE5_CMD3 = "/applause"; EMOTE5_CMD4 = "/applaud"; EMOTE5_CMD5 = "/bravo"; EMOTE5_CMD6 = "/applause"; EMOTE60_CMD1 = "/kneel"; EMOTE60_CMD2 = "/kneel"; EMOTE60_CMD3 = "/kneel"; EMOTE61_CMD1 = "/laugh"; EMOTE61_CMD2 = "/lol"; EMOTE61_CMD3 = "/laugh"; EMOTE61_CMD4 = "/lol"; EMOTE62_CMD1 = "/laydown"; EMOTE62_CMD2 = "/liedown"; EMOTE62_CMD3 = "/lay"; EMOTE62_CMD4 = "/lie"; EMOTE62_CMD5 = "/laydown"; EMOTE62_CMD6 = "/liedown"; EMOTE62_CMD7 = "/lay"; EMOTE62_CMD8 = "/lie"; EMOTE63_CMD1 = "/massage"; EMOTE63_CMD2 = "/massage"; EMOTE64_CMD1 = "/moan"; EMOTE64_CMD2 = "/moan"; EMOTE65_CMD1 = "/moon"; EMOTE65_CMD2 = "/moon"; EMOTE66_CMD1 = "/mourn"; EMOTE66_CMD2 = "/mourn"; EMOTE67_CMD1 = "/no"; EMOTE67_CMD2 = "/no"; EMOTE68_CMD1 = "/nod"; EMOTE68_CMD2 = "/yes"; EMOTE68_CMD3 = "/nod"; EMOTE68_CMD4 = "/yes"; EMOTE69_CMD1 = "/nosepick"; EMOTE69_CMD2 = "/pick"; EMOTE69_CMD3 = "/nosepick"; EMOTE69_CMD4 = "/pick"; EMOTE6_CMD1 = "/bashful"; EMOTE6_CMD2 = "/bashful"; EMOTE70_CMD1 = "/panic"; EMOTE70_CMD2 = "/panic"; EMOTE71_CMD1 = "/peer"; EMOTE71_CMD2 = "/peer"; EMOTE72_CMD1 = "/plead"; EMOTE72_CMD2 = "/plead"; EMOTE73_CMD1 = "/point"; EMOTE73_CMD2 = "/point"; EMOTE74_CMD1 = "/poke"; EMOTE74_CMD2 = "/poke"; EMOTE75_CMD1 = "/pray"; EMOTE75_CMD2 = "/pray"; EMOTE76_CMD1 = "/roar"; EMOTE76_CMD2 = "/roar"; EMOTE76_CMD3 = "/rawr"; EMOTE76_CMD4 = "/rawr"; EMOTE77_CMD1 = "/rofl"; EMOTE77_CMD2 = "/rofl"; EMOTE78_CMD1 = "/rude"; EMOTE78_CMD2 = "/rude"; EMOTE79_CMD1 = "/salute"; EMOTE79_CMD2 = "/salute"; EMOTE7_CMD1 = "/beckon"; EMOTE7_CMD2 = "/beckon"; EMOTE80_CMD1 = "/scratch"; EMOTE80_CMD2 = "/cat"; EMOTE80_CMD3 = "/catty"; EMOTE80_CMD4 = "/scratch"; EMOTE80_CMD5 = "/cat"; EMOTE80_CMD6 = "/catty"; EMOTE81_CMD1 = "/sexy"; EMOTE81_CMD2 = "/sexy"; EMOTE82_CMD1 = "/shake"; EMOTE82_CMD2 = "/rear"; EMOTE82_CMD3 = "/shake"; EMOTE82_CMD4 = "/rear"; EMOTE83_CMD1 = "/shout"; EMOTE83_CMD2 = "/holler"; EMOTE83_CMD3 = "/holler"; EMOTE84_CMD1 = "/shrug"; EMOTE84_CMD2 = "/shrug"; EMOTE85_CMD1 = "/shy"; EMOTE85_CMD2 = "/shy"; EMOTE86_CMD1 = "/sigh"; EMOTE86_CMD2 = "/sigh"; EMOTE87_CMD1 = "/sit"; EMOTE87_CMD2 = "/sit"; EMOTE88_CMD1 = "/sleep"; EMOTE88_CMD2 = "/sleep"; EMOTE89_CMD1 = "/snarl"; EMOTE89_CMD2 = "/snarl"; EMOTE8_CMD1 = "/beg"; EMOTE8_CMD2 = "/beg"; EMOTE90_CMD1 = "/spit"; EMOTE90_CMD2 = "/spit"; EMOTE91_CMD1 = "/stare"; EMOTE91_CMD2 = "/stare"; EMOTE92_CMD1 = "/surprised"; EMOTE92_CMD2 = "/surprised"; EMOTE93_CMD1 = "/surrender"; EMOTE93_CMD2 = "/surrender"; EMOTE94_CMD1 = "/talk"; EMOTE94_CMD2 = "/talk"; EMOTE95_CMD1 = "/talkex"; EMOTE95_CMD2 = "/excited"; EMOTE95_CMD3 = "/talkex"; EMOTE95_CMD4 = "/excited"; EMOTE96_CMD1 = "/talkq"; EMOTE96_CMD2 = "/question"; EMOTE96_CMD3 = "/talkq"; EMOTE96_CMD4 = "/question"; EMOTE97_CMD1 = "/tap"; EMOTE97_CMD2 = "/tap"; EMOTE98_CMD1 = "/thank"; EMOTE98_CMD2 = "/thanks"; EMOTE98_CMD3 = "/ty"; EMOTE98_CMD4 = "/thank"; EMOTE98_CMD5 = "/thanks"; EMOTE98_CMD6 = "/ty"; EMOTE99_CMD1 = "/threaten"; EMOTE99_CMD2 = "/doom"; EMOTE99_CMD3 = "/threat"; EMOTE99_CMD4 = "/wrath"; EMOTE99_CMD5 = "/threaten"; EMOTE99_CMD6 = "/doom"; EMOTE99_CMD7 = "/threat"; EMOTE99_CMD8 = "/wrath"; EMOTE9_CMD1 = "/bite"; EMOTE9_CMD2 = "/bite"; For example, /lol is listed for token ID 61, which matches the ID assigned for LAUGH, so you would run DoEmote("LAUGH") to perform that emote.
__________________
WoWInterface AddOns
|
||
02-15-12, 10:22 AM | #3 |
I also replied earlier to your curseforge forums mirror post (which I saw on Wowace actually)
|
|
02-15-12, 10:38 PM | #4 |
Thank you so much for the help so far! I have a copy up for download at:
http://www.wowinterface.com/download...20857-1.0.html But I'm still having trouble getting it to respond correctly. Is there an element I'm forgetting? |
|
02-16-12, 05:03 AM | #5 | |
Could you further explain what it's doing and how it differs from what you want it to do?
__________________
WoWInterface AddOns
|
||
02-16-12, 08:23 AM | #6 |
Sure, okay, so I've been going over this script and added/changed a few things, but I still can't seem to get it to function at all. My game doesn't even register the welcome message when I enter world. When a player targets me and does a built in /emote, my character does not react at all.
What I want to have happen is my character replies with an emote after a 3 second delay. I also want my addon to show me a welcome message in the chat box in game when I enter world. I have a full download of my most updated version addon available at: http://www.wowinterface.com/download...onse.html#info But here is my current file structure and layout of my addon as well (in case this is easier for you) I just can't figure out why this won't run. >.< Folder Layout: Interface>Addons>BlushResponse Interface>Addons>Ace3 Files Contained in BlushResponse: AceTimer-3.0.lua AceTimer-3.0.xml BlushResponse.xml BlushResponse.lua BlushResponse.toc LibStub.lua BlushResponse.toc File Code:
## Interface: 40300 ## Title: Blush Response ## Notes: Build Version 1.2 - An addon that replies to emotes for you! Dependencies: Ace Timer and LibStub ## Author: Savaena and Poisoned Lizard BlushResponse.lua BlushResponse.xml AceTimer-3.0.lua AceTimer-3.0.xml LibStub.lua Code:
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd"> </Ui> Code:
-- BLUSH RESPONSE ADDON -- local DELAY = 3 -- Number of seconds before we reply with an emote. local MAX_REPLIES = 1 -- The maximum number of reply emotes sent for every emote used on you. local OPPOSITE_FACTION; -- These two get assigned values when PLAYER_LOGIN fires. local PLAYER_GUID; local ALLIANCE_RACES = { Dwarf = true, Draenei = true, Gnome = true, Human = true, NightElf = true, Worgen = true, } local HORDE_RACES = { BloodElf = true, Goblin = true, Orc = true, Tauren = true, Troll = true, Scourge = true, } local BR = CreateFrame("Frame") -- You can use BlushResponse instead of this frame if needed local BRVersion = CreateFrame("Frame") -- This is my version/greeting frame LibStub("AceTimer-3.0"):Embed(BR) -- Embed AceTimer, allowing use of its methods. local triggers = { -- This table contains the trigger phrases and reply type/messages. -- The trigger phrase can use any patterns recognised by string.find, but for best results use ^%S at the start to match the name of the emoter. -- The replyType can be "builtin" for an emote performed with DoEmote (e.g. /dance, /cower) or "custom" for an emote performed with SendChatMessage (e.g. /e is very scared!) -- The replyMsg can be an EmoteToken for builtin emotes or a message for custom emotes (optionally with %N, which will be replaced with the name of the emoter) -- You will need to figure out a way for the user to add/remove triggers from here. { trigger = "^%S+ licks you", replyType = "builtin", replyMsg = "COWER" }, { trigger = "^%S+ pokes you", replyType = "builtin", replyMsg = "FART" }, { trigger = "^%S+ hugs you", replyType = "builtin", replyMsg = "HELPME" }, { trigger = "^%S+ slaps you", replyType = "builtin", replyMsg = "BURP" }, { trigger = "^%S+ winks slyly at you", replyType = "builtin", replyMsg = "WINK" }, { trigger = "^%S+ cries on your shoulder", replyType = "builtin", replyMsg = "VIOLIN" }, { trigger = "^%S+ loves you", replyType = "builtin", replyMsg = "BLUSH" }, { trigger = "^%S+ thinks you are a sexy devil", replyType = "custom", replyMsg = "gasps in shock at %N!" }, { trigger = "^%S+ dances with you", replyType = "custom", replyMsg = "admires %N's moves." }, } BR:SetScript("OnEvent", function(self, event, ...) -- This part only works if BR is a frame self[event](self, ...) -- Call the event name as a method of BR with all the arguments supplied. end) BRVersion:RegisterEvent("PLAYER_LOGIN") BR:RegisterEvent("PLAYER_LOGIN") BR:RegisterEvent("CHAT_MSG_TEXT_EMOTE") -- Fired for builtin emotes like /dance BR:RegisterEvent("CHAT_MSG_EMOTE") -- Fired for custom emotes like /e is happy. function BR:ADDON_LOADED(self, event, arg1) if (event == "ADDON_LOADED") and (arg1 == "BR") then DEFAULT_CHAT_FRAME:AddMessage("Addon: Blush Response v. 1.2 successfully loaded!"); BR:LoadDefaults() self:UnregisterEvent("ADDON_LOADED") end end function BR:PLAYER_LOGIN() OPPOSITE_FACTION = UnitFactionGroup("player") == "Alliance" and HORDE_RACES or ALLIANCE_RACES PLAYER_GUID = UnitGUID("player") end local function PerformEmotes(args) -- AceTimer only allows us to call the function with a single argument, so we put the message and name in a table local msg, name = unpack(args) local numEmotes = 0 for _, data in ipairs(triggers) do if msg:find(data.trigger) then numEmotes = numEmotes + 1 if data.replyType == "builtin" then DoEmote(data.replyMsg) else SendChatMessage(data.replyMsg:gsub("%%N", name), "EMOTE") end if numEmotes == MAX_EMOTES then break end -- Break the loop if we've performed the maximum number of reply emotes end end end function BR:CHAT_MSG_TEXT_EMOTE(msg, name, _, _, _, _, _, _, _, _, lineId, GUID) if GUID == PLAYER_GUID then return end -- Don't respond to emotes the player sent. local className, classId, raceName, raceId, gender, name, realm = GetPlayerInfoByGUID(GUID) if OPPOSITE_FACTION[raceId] then DoEmote("PONDER") end self:ScheduleTimer(PerformEmotes, DELAY, {msg, name}) -- Call PerformEmotes in DELAY seconds with a table of the message and name as its only argument end function BR:CHAT_MSG_EMOTE(msg, name, _, _, _, _, _, _, _, _, lineId, GUID) if GUID == PLAYER_GUID then return end self:ScheduleTimer(PerformEmotes, DELAY, {msg, name}) end function BR:LoadDefaults() BR = {} for i = 1, #Defaults do tinsert(EmoteReply.Emotes, Defaults[i]) end end function BR:CHAT_MSG_EMOTE(msg, name, _, _, _, _, _, _, _, _, lineId, GUID) if ( event == "CHAT_MSG_TEXT_EMOTE" ) then print(arg1) local arg1 = string.lower(arg1) --turns all uppercase letters into lowercase ones. foreach(trigger, function(k,v) if (string.find(arg1, v.Trigger)) then if (string.find(arg1)) then replyMsg; end return; end end ); end end Code:
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info -- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! local LibStub = _G[LIBSTUB_MAJOR] if not LibStub or LibStub.minor < LIBSTUB_MINOR then LibStub = LibStub or {libs = {}, minors = {} } _G[LIBSTUB_MAJOR] = LibStub LibStub.minor = LIBSTUB_MINOR function LibStub:NewLibrary(major, minor) assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") local oldminor = self.minors[major] if oldminor and oldminor >= minor then return nil end self.minors[major], self.libs[major] = minor, self.libs[major] or {} return self.libs[major], oldminor end function LibStub:GetLibrary(major, silent) if not self.libs[major] and not silent then error(("Cannot find a library instance of %q."):format(tostring(major)), 2) end return self.libs[major], self.minors[major] end function LibStub:IterateLibraries() return pairs(self.libs) end setmetatable(LibStub, { __call = LibStub.GetLibrary }) end Code:
--- **AceTimer-3.0** provides a central facility for registering timers. -- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient -- data structure that allows easy dispatching and fast rescheduling. Timers can be registered, rescheduled -- or canceled at any time, even from within a running timer, without conflict or large overhead.\\ -- AceTimer is currently limited to firing timers at a frequency of 0.1s. This constant may change -- in the future, but for now it seemed like a good compromise in efficiency and accuracy. -- -- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you -- need to cancel or reschedule the timer you just registered. -- -- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by -- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object -- and can be accessed directly, without having to explicitly call AceTimer itself.\\ -- It is recommended to embed AceTimer, otherwise you'll have to specify a custom `self` on all calls you -- make into AceTimer. -- @class file -- @name AceTimer-3.0 -- @release $Id: AceTimer-3.0.lua 1037 2011-09-02 16:24:08Z mikk $ --[[ Basic assumptions: * In a typical system, we do more re-scheduling per second than there are timer pulses per second * Regardless of timer implementation, we cannot guarantee timely delivery due to FPS restriction (may be as low as 10) This implementation: CON: The smallest timer interval is constrained by HZ (currently 1/10s). PRO: It will still correctly fire any timer slower than HZ over a length of time, e.g. 0.11s interval -> 90 times over 10 seconds PRO: In lag bursts, the system simly skips missed timer intervals to decrease load CON: Algorithms depending on a timer firing "N times per minute" will fail PRO: (Re-)scheduling is O(1) with a VERY small constant. It's a simple linked list insertion in a hash bucket. CAUTION: The BUCKETS constant constrains how many timers can be efficiently handled. With too many hash collisions, performance will decrease. Major assumptions upheld: - ALLOWS scheduling multiple timers with the same funcref/method - ALLOWS scheduling more timers during OnUpdate processing - ALLOWS unscheduling ANY timer (including the current running one) at any time, including during OnUpdate processing ]] local MAJOR, MINOR = "AceTimer-3.0", 6 local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR) if not AceTimer then return end -- No upgrade needed AceTimer.hash = AceTimer.hash or {} -- Array of [0..BUCKET-1] = linked list of timers (using .next member) -- Linked list gets around ACE-88 and ACE-90. AceTimer.selfs = AceTimer.selfs or {} -- Array of [self]={[handle]=timerobj, [handle2]=timerobj2, ...} AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame") -- Lua APIs local assert, error, loadstring = assert, error, loadstring local setmetatable, rawset, rawget = setmetatable, rawset, rawget local select, pairs, type, next, tostring = select, pairs, type, next, tostring local floor, max, min = math.floor, math.max, math.min local tconcat = table.concat -- WoW APIs local GetTime = GetTime -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- List them here for Mikk's FindGlobals script -- GLOBALS: DEFAULT_CHAT_FRAME, geterrorhandler -- Simple ONE-SHOT timer cache. Much more efficient than a full compost for our purposes. local timerCache = nil --[[ Timers will not be fired more often than HZ-1 times per second. Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999) If this is ever LOWERED, all existing timers need to be enforced to have a delay >= 1/HZ on lib upgrade. If this number is ever changed, all entries need to be rehashed on lib upgrade. ]] local HZ = 11 --[[ Prime for good distribution If this number is ever changed, all entries need to be rehashed on lib upgrade. ]] local BUCKETS = 131 local hash = AceTimer.hash for i=1,BUCKETS do hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes end --[[ xpcall safecall implementation ]] local xpcall = xpcall local function errorhandler(err) return geterrorhandler()(err) end local function CreateDispatcher(argCount) local code = [[ local xpcall, eh = ... -- our arguments are received as unnamed values in "..." since we don't have a proper function declaration local method, ARGS local function call() return method(ARGS) end local function dispatch(func, ...) method = func if not method then return end ARGS = ... return xpcall(call, eh) end return dispatch ]] local ARGS = {} for i = 1, argCount do ARGS[i] = "arg"..i end code = code:gsub("ARGS", tconcat(ARGS, ", ")) return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler) end local Dispatchers = setmetatable({}, { __index=function(self, argCount) local dispatcher = CreateDispatcher(argCount) rawset(self, argCount, dispatcher) return dispatcher end }) Dispatchers[0] = function(func) return xpcall(func, errorhandler) end local function safecall(func, ...) return Dispatchers[select('#', ...)](func, ...) end local lastint = floor(GetTime() * HZ) -- -------------------------------------------------------------------- -- OnUpdate handler -- -- traverse buckets, always chasing "now", and fire timers that have expired local function OnUpdate() local now = GetTime() local nowint = floor(now * HZ) -- Have we passed into a new hash bucket? if nowint == lastint then return end local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2 -- Pass through each bucket at most once -- Happens on e.g. instance loads, but COULD happen on high local load situations also for curint = (max(lastint, nowint - BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteration local curbucket = (curint % BUCKETS)+1 -- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks. local nexttimer = hash[curbucket] hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash while nexttimer do local timer = nexttimer nexttimer = timer.next local when = timer.when if when < soon then -- Call the timer func, either as a method on given object, or a straight function ref local callback = timer.callback if type(callback) == "string" then safecall(timer.object[callback], timer.object, timer.arg) elseif callback then safecall(callback, timer.arg) else -- probably nilled out by CancelTimer timer.delay = nil -- don't reschedule it end local delay = timer.delay -- NOW make a local copy, can't do it earlier in case the timer cancelled itself in the callback if not delay then -- single-shot timer (or cancelled) AceTimer.selfs[timer.object][tostring(timer)] = nil timerCache = timer else -- repeating timer local newtime = when + delay if newtime < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.) newtime = now + delay end timer.when = newtime -- add next timer execution to the correct bucket local bucket = (floor(newtime * HZ) % BUCKETS) + 1 timer.next = hash[bucket] hash[bucket] = timer end else -- if when>=soon -- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution) timer.next = hash[curbucket] hash[curbucket] = timer end -- if when<soon ... else end -- while nexttimer do end -- for curint=lastint,nowint lastint = nowint end -- --------------------------------------------------------------------- -- Reg( callback, delay, arg, repeating ) -- -- callback( function or string ) - direct function ref or method name in our object for the callback -- delay(int) - delay for the timer -- arg(variant) - any argument to be passed to the callback function -- repeating(boolean) - repeating timer, or oneshot -- -- returns the handle of the timer for later processing (canceling etc) local function Reg(self, callback, delay, arg, repeating) if type(callback) ~= "string" and type(callback) ~= "function" then local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer" error(MAJOR..": " .. error_origin .. "(callback, delay, arg): 'callback' - function or method name expected.", 3) end if type(callback) == "string" then if type(self)~="table" then local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer" error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'self' - must be a table.", 3) end if type(self[callback]) ~= "function" then local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer" error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'methodName' - method not found on target object.", 3) end end if delay < (1 / (HZ - 1)) then delay = 1 / (HZ - 1) end -- Create and stuff timer in the correct hash bucket local now = GetTime() local timer = timerCache or {} -- Get new timer object (from cache if available) timerCache = nil timer.object = self timer.callback = callback timer.delay = (repeating and delay) timer.arg = arg timer.when = now + delay local bucket = (floor((now+delay)*HZ) % BUCKETS) + 1 timer.next = hash[bucket] hash[bucket] = timer -- Insert timer in our self->handle->timer registry local handle = tostring(timer) local selftimers = AceTimer.selfs[self] if not selftimers then selftimers = {} AceTimer.selfs[self] = selftimers end selftimers[handle] = timer selftimers.__ops = (selftimers.__ops or 0) + 1 return handle end --- Schedule a new one-shot timer. -- The timer will fire once in `delay` seconds, unless canceled before. -- @param callback Callback function for the timer pulse (funcref or method name). -- @param delay Delay for the timer, in seconds. -- @param arg An optional argument to be passed to the callback function. -- @usage -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0") -- -- function MyAddon:OnEnable() -- self:ScheduleTimer("TimerFeedback", 5) -- end -- -- function MyAddon:TimerFeedback() -- print("5 seconds passed") -- end function AceTimer:ScheduleTimer(callback, delay, arg) return Reg(self, callback, delay, arg) end --- Schedule a repeating timer. -- The timer will fire every `delay` seconds, until canceled. -- @param callback Callback function for the timer pulse (funcref or method name). -- @param delay Delay for the timer, in seconds. -- @param arg An optional argument to be passed to the callback function. -- @usage -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0") -- -- function MyAddon:OnEnable() -- self.timerCount = 0 -- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5) -- end -- -- function MyAddon:TimerFeedback() -- self.timerCount = self.timerCount + 1 -- print(("%d seconds passed"):format(5 * self.timerCount)) -- -- run 30 seconds in total -- if self.timerCount == 6 then -- self:CancelTimer(self.testTimer) -- end -- end function AceTimer:ScheduleRepeatingTimer(callback, delay, arg) return Reg(self, callback, delay, arg, true) end --- Cancels a timer with the given handle, registered by the same addon object as used for `:ScheduleTimer` -- Both one-shot and repeating timers can be canceled with this function, as long as the `handle` is valid -- and the timer has not fired yet or was canceled before. -- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer` -- @param silent If true, no error is raised if the timer handle is invalid (expired or already canceled) -- @return True if the timer was successfully cancelled. function AceTimer:CancelTimer(handle, silent) if not handle then return end -- nil handle -> bail out without erroring if type(handle) ~= "string" then error(MAJOR..": CancelTimer(handle): 'handle' - expected a string", 2) -- for now, anyway end local selftimers = AceTimer.selfs[self] local timer = selftimers and selftimers[handle] if silent then if timer then timer.callback = nil -- don't run it again timer.delay = nil -- if this is the currently-executing one: don't even reschedule -- The timer object is removed in the OnUpdate loop end return not not timer -- might return "true" even if we double-cancel. we'll live. else if not timer then geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - no such timer registered") return false end if not timer.callback then geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - timer already cancelled or expired") return false end timer.callback = nil -- don't run it again timer.delay = nil -- if this is the currently-executing one: don't even reschedule return true end end --- Cancels all timers registered to the current addon object ('self') function AceTimer:CancelAllTimers() if not(type(self) == "string" or type(self) == "table") then error(MAJOR..": CancelAllTimers(): 'self' - must be a string or a table",2) end if self == AceTimer then error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2) end local selftimers = AceTimer.selfs[self] if selftimers then for handle,v in pairs(selftimers) do if type(v) == "table" then -- avoid __ops, etc AceTimer.CancelTimer(self, handle, true) end end end end --- Returns the time left for a timer with the given handle, registered by the current addon object ('self'). -- This function will raise a warning when the handle is invalid, but not stop execution. -- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer` -- @return The time left on the timer, or false if the handle is invalid. function AceTimer:TimeLeft(handle) if not handle then return end if type(handle) ~= "string" then error(MAJOR..": TimeLeft(handle): 'handle' - expected a string", 2) -- for now, anyway end local selftimers = AceTimer.selfs[self] local timer = selftimers and selftimers[handle] if not timer then geterrorhandler()(MAJOR..": TimeLeft(handle): '"..tostring(handle).."' - no such timer registered") return false end return timer.when - GetTime() end -- --------------------------------------------------------------------- -- PLAYER_REGEN_ENABLED: Run through our .selfs[] array step by step -- and clean it out - otherwise the table indices can grow indefinitely -- if an addon starts and stops a lot of timers. AceBucket does this! -- -- See ACE-94 and tests/AceTimer-3.0-ACE-94.lua local lastCleaned = nil local function OnEvent(this, event) if event~="PLAYER_REGEN_ENABLED" then return end -- Get the next 'self' to process local selfs = AceTimer.selfs local self = next(selfs, lastCleaned) if not self then self = next(selfs) end lastCleaned = self if not self then -- should only happen if .selfs[] is empty return end -- Time to clean it out? local list = selfs[self] if (list.__ops or 0) < 250 then -- 250 slosh indices = ~10KB wasted (worst case!). For one 'self'. return end -- Create a new table and copy all members over local newlist = {} local n=0 for k,v in pairs(list) do newlist[k] = v if type(v)=="table" and v.callback then -- if the timer is actually live: count it n=n+1 end end newlist.__ops = 0 -- Reset operation count -- And since we now have a count of the number of live timers, check that it's reasonable. Emit a warning if not. if n>BUCKETS then DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(self).."' has "..n.." live timers. Surely that's not intended?") end selfs[self] = newlist end -- --------------------------------------------------------------------- -- Embed handling AceTimer.embeds = AceTimer.embeds or {} local mixins = { "ScheduleTimer", "ScheduleRepeatingTimer", "CancelTimer", "CancelAllTimers", "TimeLeft" } function AceTimer:Embed(target) AceTimer.embeds[target] = true for _,v in pairs(mixins) do target[v] = AceTimer[v] end return target end -- AceTimer:OnEmbedDisable( target ) -- target (object) - target object that AceTimer is embedded in. -- -- cancel all timers registered for the object function AceTimer:OnEmbedDisable( target ) target:CancelAllTimers() end for addon in pairs(AceTimer.embeds) do AceTimer:Embed(addon) end -- --------------------------------------------------------------------- -- Debug tools (expose copies of internals to test suites) AceTimer.debug = AceTimer.debug or {} AceTimer.debug.HZ = HZ AceTimer.debug.BUCKETS = BUCKETS -- --------------------------------------------------------------------- -- Finishing touchups AceTimer.frame:SetScript("OnUpdate", OnUpdate) AceTimer.frame:SetScript("OnEvent", OnEvent) AceTimer.frame:RegisterEvent("PLAYER_REGEN_ENABLED") -- In theory, we could hide&show the frame based on there being timers or not. -- However, this job is fairly expensive, and the chance that there will -- actually be zero timers running is diminuitive to say the least. Code:
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd"> <Script file="AceTimer-3.0.lua"/> </Ui> |
|
02-16-12, 10:09 AM | #7 |
Before I (or someone else) comments on the code first things first.
It's best if you get a few things out of the way surrounding development before going into the actual lua. 1. Do not package the whole Ace3 framework with your addon. Libraries (where needed) are meant to be embedded in your addon folder (simplest case) For example if you need AceTimer-3.0 a typical folder structure would be. BlushResponse\Libs\AceTimer-3.0\AceTimer-3.0.xml (and other files contained in the library folder) BlushResponse\Libs\LibStub\LibStub.lua BlushResponse\Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml (and other files) Your .toc file references files relative to the addon folder so BlushResponse is the 'root' folder where the .toc is concerned. .toc Code:
Libs\LibStub\LibStub.lua Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml Libs\AceTimer-3.0\AceTimer-3.0\AceTimer-3.0.xml BlushResponse.lua 2. Get rid of the .xml file, as long as you're creating the frames in lua (there is equivalent API allowing you to create frames, set scripts etc without using xml) 3. If you're just getting started with addon writing and since this addon is relatively simple in scope I'd suggest you stay away from frameworks for your first project. Libraries simplify common or repetitive tasks but they're only a time saver when the need to use them has arisen 'naturally' as you find yourself writing your Nth command handler, options table etc. For an author just beginning, the overhead of an additional layer of API over the base wow lua API is probably going to be more confusion than help. Will get back to you with some code snippets but any author contributing is unlikely to fix your existing code, more likely re-write it Edit: Forgot 4. Make sure you have an error display addon installed (!BugGrabber + BugSack are a good option) or at the least the in-game option to "Show Lua Errors" (under game preferences -> Help) enabled. World of Warcraft\Logs\FrameXML.log might also hold error information about your addon. Last edited by Dridzt : 02-16-12 at 10:19 AM. |
|
02-16-12, 06:45 PM | #8 | |
Also, loading both the Lua and XML files for AceTimer only causes you to load the library twice, as the XML file is nothing but a "loading stub" that points to the Lua file. This is a common convention in libraries, with the idea that addon authors can just list a single XML file, and if more files are added to the library, the library author can just add them to the XML file, and the addon author does not have to add more files to his/her TOC file. However, I feel this is a bad idea, for several reasons: (1) It promotes laziness on the part of addon authors. If a library change is major enough to add or remove files, an addon author probably needs to update his/her addon anyway, at at the very least should review his/her addon to make sure no such updates are needed. (2) Most libraries only have one Lua file, so going through an XML stub just doubles the time it takes to load the library (since WoW has to read two files instead of one). Since reading files from your hard disk is by far the biggest contributor to load times, you should avoid reading any more files than are absolutely necessary. Also, as Dridzt already mentioned, using XML in your addon is a waste of time (both to write it, and to load it every time you log in) unless your addon is tackling one of the very few, very advanced tasks where custom secure frame templates are required. Since your addon isn't doing this, don't use XML. Your TOC file listing should look more like this: Code:
Libs\LibStub\LibStub.lua Libs\AceTimer-3.0\Acetimer-3.0.lua BlushResponse.xml -- only if you really need XML for some reason BlushResponse.lua |
||
02-17-12, 05:55 AM | #9 | |
I tried to keep from doing this, but I went ahead and rewrote all of the code. This goes at a different approach using an emote queuing system that handles both delays on individual emotes and a global cooldown between sending out more. The trigger table uses the text following the sender as the key for a table of responses. The addon first checks if the response text is a slash command for an emote. Second, it checks if it matches a token ID. If either of these are true, it runs the built-in emote. Otherwise, it sends the text out as a custom emote. Tables supplying multiple responses will have all responses sent sequentially.
This code is standalone and requires no libraries. lua Code:
__________________
WoWInterface AddOns
Last edited by SDPhantom : 02-19-12 at 05:44 AM. |
||
02-17-12, 03:26 PM | #10 |
Wow- see, the way you write that out makes soooo much more sense to me when I look at it. I used to write batch files as a kid for my computer when I was bored, but never went beyond that, so my understanding of coding lua is limited.
However, your code here seems so much simpler. Overlaying an API on top of another one to start my first addon was probably not a wise idea. XD I'm about to test this coding with just a toc file that loads the BlushResponse.lua. Were you able to successfully get your rewrite above to work for you? |
|
02-17-12, 05:43 PM | #11 | |
I haven't had time to test it since I wrote the entire thing in about an hour before going to bed. If you have any problems with it, I'll load it in and try to debug it.
I started with MS-DOS batch files as a kid too. I later moved onto HTML and Javascript, then just spread out from there over the many years.
__________________
WoWInterface AddOns
Last edited by SDPhantom : 02-17-12 at 05:47 PM. |
||
02-18-12, 09:44 PM | #12 |
I see several problems with your code, SDPhantom...
#1 - You typed semicolons instead of commas inside a table definition: Code:
local FactionRaces={ Dwarf ="Alliance"; Draenei ="Alliance"; #3 - The player's GUID is not available when the main chunk executes at login, so this will not work: Code:
local PlayerGUID=UnitGUID("player"); #4 - I don't really know what you were trying to do here: Code:
BRFrame:SetScript("OnEvent",function(self,event,...) local guid,msg,sender=select(12,...),...; Code:
BRFrame:SetScript("OnEvent", function(self, event, ...) local msg, sender, _, _, _, _, _, _, _, _, _, guid = ... #5 - This: Code:
if guid~=PLAYER_GUID then-- Don't respond to emotes the player sent. -- Do stuff here. end Code:
if guid == PLAYER_GUID then return end -- Don't respond to emotes the player sent. -- Do stuff here. I don't have time to go through it in more detail than that right now, but there may be other issues as well. TL;DR: Don't write code while you are falling asleep. |
|
02-19-12, 05:19 AM | #13 | |
#1: Lua allows use of both commas and semicolons as a field delimiter in table construction. I prefer semicolons when I have a single entry per line.
#2: I'm used to programming languages requiring lines ending with a semicolon. I know Lua doesn't, but it's my programming style to have them in anyway. It doesn't impact processing in any way and I see no need to remove them. As far as making code difficult to read, I don't believe that at all. #3: I'll have to test this myself, but I was sure I had some player-specific data loading at addon load. Edit: Tested and was found not to be one of the functions. #4: It's unconventional and may not be the best way to do it, but the 12th arg is assigned to guid and the first and second are assigned to the other two. Note select() has values listed after it (another vararg), so the extra values from select() are dropped. I've used this before, I know it works and the process that makes it work. #5: I see no difference in between the performance of these two methods. Again, it's up to programming style. You're running the same number of conditionals, the same checks, even the same relative structure. You move the end keyword up to the top, flip the condition, and add a return keyword for it to run. And the load time changes how? Update: The GUID detection has been fixed in the code above. Another bug was missing a couple instances of the renamed upvalue.
__________________
WoWInterface AddOns
Last edited by SDPhantom : 02-19-12 at 06:09 AM. |
||
02-19-12, 08:11 PM | #14 | |||
What does change is the time it takes to execute that code path. Here are two ways to write the same thing. Highlighted in yellow are the parts that actually execute when the function is called but you want it to do nothing: Code:
function DoStuff(guid) if guid == playerGUID then return end -- Function stops here. if FactionRaces[select(4,GetPlayerInfoByGUID(guid)) or ""]==PLAYER_FACTION then self:QueueEmote(CrossFactionEmote,sender); else local response=Triggers[msg:match("^%S+%s*(.-)$")]; if type(response)=="table" then-- Handle table syntax for i,j in ipairs(response) do self:QueueEmote(j,sender); end elseif type(response=="string" then-- Handle single string self:QueueEmote(response,sender); end end end Code:
function DoStuff(guid) if guid ~= playerGUID then if FactionRaces[select(4,GetPlayerInfoByGUID(guid)) or ""]==PLAYER_FACTION then self:QueueEmote(CrossFactionEmote,sender); else local response=Triggers[msg:match("^%S+%s*(.-)$")]; if type(response)=="table" then-- Handle table syntax for i,j in ipairs(response) do self:QueueEmote(j,sender); end elseif type(response=="string" then-- Handle single string self:QueueEmote(response,sender); end end end end -- Function stops here. |
||||
02-20-12, 05:32 AM | #15 | |
Still on the subject of returning form a function at the top instead of having the chunk in an entire conditional. It all depends on how the built-in compiler for Lua handles the situation. I wouldn't call it sufficient enough data to determine the magnitude of efficiency of either method unless run times are actually posted.
I ran the following code to test both methods: lua Code:
What this does is run each function 1 million times and take times it takes the function to return as well as mark high and low times and compare which runs one function performs better than the other and through which, when both return within the exact same time. If there was any clear "better" method, you'd see most of the run counts add to one side consistently instead of half being in equal and split results to each side. One such data set would look like: Code:
Totals 1348.4072361132 1372.1531647122 Avg 0.0013484072361132 0.0013721531647122 High 6.8232135648525 2.1843558329341 Low 0.000838095344534452004 0.000838095344534452004 Best 247849 173504 Equal 578647 Also increasing the payload of skipped code does not seem to affect times at all. Update: For some strange reason, Lua seems to favor which of the functions runs first. Values trend one way when func1() runs before func2() and another when the order is reversed.
__________________
WoWInterface AddOns
Last edited by SDPhantom : 02-20-12 at 05:36 AM. |
||
02-20-12, 11:31 AM | #16 |
Regardless of real or imagined parsing time differences, I prefer the early-bailout method to reduce nesting which in turn increases clarity.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes". Author of NPCScan and many other AddOns. |
|
02-20-12, 01:28 PM | #17 | |
Just proving there isn't much if any difference at all and the moot point of criticizing one's programming style when the situation is such.
__________________
WoWInterface AddOns
|
||
02-21-12, 04:27 AM | #18 | |
People are different and have different opinions. There may be general consense but that doesn't mean you have to follow. You don't have to prove yourself for thinking different.
__________________
| Simple is beautiful. | WoWI AddOns | GitHub | Zork (WoW)
|
||
WoWInterface » Developer Discussions » General Authoring Discussion » Need Lua Coding Help! |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|