hlmod.hu

Magyar Half-Life Mód közösség!
Pontos idő: 2024.03.28. 11:52



Jelenlévő felhasználók

Jelenleg 235 felhasználó van jelen :: 0 regisztrált, 0 rejtett és 235 vendég

A legtöbb felhasználó (1565 fő) 2020.11.21. 11:26-kor tartózkodott itt.

Regisztrált felhasználók: nincs regisztrált felhasználó az elmúlt 5 percben aktív felhasználók alapján

Utoljára aktív
Ahhoz hogy lásd ki volt utoljára aktív, be kell jelentkezned.



Az oldal teljeskörű
használatához regisztrálj.

Regisztráció

Kereső


Új téma nyitása  Hozzászólás a témához  [ 6 hozzászólás ] 
Szerző Üzenet
HozzászólásElküldve: 2015.12.11. 19:26 
Offline
Tag

Csatlakozott: 2015.12.05. 14:36
Hozzászólások: 34
Megköszönt másnak: 16 alkalommal
Úgy kéne hogy az az admin nevét azt zölden írja és amit az admin ír az meg csapatszín legyen .

SMA Forráskód: [ Mindet kijelol ]
  1. #include <amxmodx>
  2. #include <amxmisc>
  3.  
  4. #define PLUGIN "Admin Chat Colors"
  5. #define VERSION "2.0"
  6. #define AUTHOR "Arion"
  7.  
  8. #define ACCESS_LEVEL ADMIN_IMMUNITY
  9. #define ADMIN_LISTEN ADMIN_LEVEL_C
  10.  
  11. new message[192]
  12. new sayText
  13. new teamInfo
  14. new maxPlayers
  15.  
  16. new g_AdminListen
  17.  
  18. new strName[191]
  19. new alive[11]
  20.  
  21. new const g_szTag[][] = {
  22. "",
  23. "[Tulajdonos]",
  24. "[Configos]",
  25. "[Admin]"
  26. }
  27.  
  28. public plugin_init()
  29. {
  30. register_plugin(PLUGIN, VERSION, AUTHOR)
  31.  
  32. g_AdminListen = register_cvar("amx_listen", "1") // Set whether admins see or not all messages(Alive, dead and team-only)
  33.  
  34.  
  35. sayText = get_user_msgid("SayText")
  36. teamInfo = get_user_msgid("TeamInfo")
  37. maxPlayers = get_maxplayers()
  38.  
  39. register_clcmd("say", "hook_say")
  40. register_clcmd("say_team", "hook_teamsay")
  41. }
  42.  
  43. public hook_say(id)
  44. {
  45. read_args(message, 191)
  46. remove_quotes(message)
  47.  
  48. // Gungame commands and empty messages
  49. if(message[0] == '@' || message[0] == '/' || message[0] == '!' || equal(message, "")) // Ignores Admin Hud Messages, Admin Slash commands,
  50. return PLUGIN_CONTINUE
  51.  
  52. new name[32]
  53. get_user_name(id, name, 31)
  54.  
  55. new admin = 0, iFlags = get_user_flags(id)
  56.  
  57. if(iFlags & ADMIN_IMMUNITY)
  58. admin = 1
  59. else if(iFlags & ADMIN_CFG)
  60. admin = 2
  61. else if(iFlags & ADMIN_BAN)
  62. admin = 3
  63.  
  64. new isAlive
  65.  
  66. if(is_user_alive(id))
  67. {
  68. isAlive = 1
  69. alive = "^x01"
  70. }
  71. else
  72. {
  73. isAlive = 0
  74. alive = "^x01*DEAD* "
  75. }
  76.  
  77. static color[10]
  78.  
  79. if(admin)
  80. {
  81. get_user_team(id, color, 9)
  82. format(strName, 191, "^x04%s %s^x03%s", g_szTag[admin], alive, name)
  83. format(message, 191, "%s ^x01:^x04 %s", strName, message)
  84. }
  85. else // Player is not admin. Team-color name : Yellow message
  86. {
  87. get_user_team(id, color, 9)
  88. format(strName, 191, "%s^x03%s", alive, name)
  89. format(message, 191, "^%s^x01 : %s", strName, message)
  90. }
  91.  
  92.  
  93. sendMessage(color, isAlive) // Sends the colored message
  94.  
  95. return PLUGIN_HANDLED
  96. }
  97.  
  98.  
  99. public hook_teamsay(id)
  100. {
  101. new playerTeam = get_user_team(id)
  102. new playerTeamName[19]
  103.  
  104. switch(playerTeam) // Team names which appear on team-only messages
  105. {
  106. case 1:
  107. copy(playerTeamName, 11, "Terrorista")
  108.  
  109. case 2:
  110. copy(playerTeamName, 18, "Anti-Terrorista")
  111.  
  112. default:
  113. copy(playerTeamName, 9, "Néző")
  114. }
  115.  
  116. read_args(message, 191)
  117. remove_quotes(message)
  118.  
  119. // Gungame commands and empty messages
  120. if(message[0] == '@' || message[0] == '/' || message[0] == '!' || equal(message, "")) // Ignores Admin Hud Messages, Admin Slash commands,
  121. return PLUGIN_CONTINUE
  122.  
  123. new name[32]
  124. get_user_name(id, name, 31)
  125.  
  126. new admin = 0, iFlags = get_user_flags(id)
  127.  
  128. if(iFlags & ADMIN_IMMUNITY)
  129. admin = 1
  130. else if(iFlags & ADMIN_CFG)
  131. admin = 2
  132. else if(iFlags & ADMIN_BAN)
  133. admin = 3
  134.  
  135. new isAlive
  136.  
  137. if(is_user_alive(id))
  138. {
  139. isAlive = 1
  140. alive = "^x01"
  141. }
  142. else
  143. {
  144. isAlive = 0
  145. alive = "^x01*HALOTT* "
  146. }
  147.  
  148. static color[10]
  149.  
  150. if(admin)
  151. {
  152. get_user_team(id, color, 9)
  153. format(strName, 191, "%s(%s)^x04%s ^x03%s", alive, playerTeamName, g_szTag[admin], name)
  154. format(message, 191, "%s ^x01: ^x04%s", strName, message)
  155. }
  156. else // Player is not admin. Team-color name : Yellow message
  157. {
  158. get_user_team(id, color, 9)
  159. format(strName, 191, "%s(%s) ^x03%s", alive, playerTeamName, name)
  160. format(message, 191, "%s ^x01: %s", strName, message)
  161. }
  162.  
  163.  
  164. sendTeamMessage(color, isAlive, playerTeam) // Sends the colored message
  165.  
  166. return PLUGIN_HANDLED
  167. }
  168.  
  169. public sendMessage(color[], alive)
  170. {
  171. new teamName[10]
  172.  
  173. for(new player = 1; player < maxPlayers; player++)
  174. {
  175. if(!is_user_connected(player))
  176. continue
  177.  
  178. if(alive && is_user_alive(player) || !alive && !is_user_alive(player) || get_pcvar_num(g_AdminListen) && get_user_flags(player) & ADMIN_LISTEN)
  179. {
  180. get_user_team(player, teamName, 9) // Stores user's team name to change back after sending the message
  181. changeTeamInfo(player, color) // Changes user's team according to color choosen
  182. writeMessage(player, message) // Writes the message on player's chat
  183. changeTeamInfo(player, teamName) // Changes user's team back to original
  184. }
  185. }
  186. }
  187.  
  188.  
  189. public sendTeamMessage(color[], alive, playerTeam)
  190. {
  191. new teamName[10]
  192.  
  193. for(new player = 1; player < maxPlayers; player++)
  194. {
  195. if(!is_user_connected(player))
  196. continue
  197.  
  198. if(get_user_team(player) == playerTeam || get_pcvar_num(g_AdminListen) && get_user_flags(player) & ADMIN_LISTEN)
  199. {
  200. if(alive && is_user_alive(player) || !alive && !is_user_alive(player) || get_pcvar_num(g_AdminListen) && get_user_flags(player) & ADMIN_LISTEN)
  201. {
  202. get_user_team(player, teamName, 9) // Stores user's team name to change back after sending the message
  203. changeTeamInfo(player, color) // Changes user's team according to color choosen
  204. writeMessage(player, message) // Writes the message on player's chat
  205. changeTeamInfo(player, teamName) // Changes user's team back to original
  206. }
  207. }
  208. }
  209. }
  210.  
  211.  
  212. public changeTeamInfo(player, team[])
  213. {
  214. message_begin(MSG_ONE, teamInfo, _, player) // Tells to to modify teamInfo(Which is responsable for which time player is)
  215. write_byte(player) // Write byte needed
  216. write_string(team) // Changes player's team
  217. message_end() // Also Needed
  218. }
  219.  
  220.  
  221. public writeMessage(player, message[])
  222. {
  223. message_begin(MSG_ONE, sayText, {0, 0, 0}, player) // Tells to modify sayText(Which is responsable for writing colored messages)
  224. write_byte(player) // Write byte needed
  225. write_string(message) // Effectively write the message, finally, afterall
  226. message_end() // Needed as always
  227. }
  228.  


A hozzászólást 1 alkalommal szerkesztették, utoljára mforce 2015.12.11. 19:31-kor.
Témanév javítva! Legközelebb figyelj oda!


Hozzászólás jelentése
Vissza a tetejére
   
HozzászólásElküldve: 2015.12.11. 19:30 
Offline
Felfüggesztve
Avatar

Csatlakozott: 2013.06.09. 18:47
Hozzászólások: 2004
Megköszönt másnak: 1 alkalommal
Megköszönték neki: 220 alkalommal
Változtasd meg a témanevet erre(Admin írás más színnel vagy Admin Chat Colors módosítása) és akkor segítek.

_________________
Ha elnyerte valamelyik témában a hozzászólásom a tetszésedet melyet olvastál, akkor egy egyszerű gombnyomással kifejezheted, hogy tetszett.


Hozzászólás jelentése
Vissza a tetejére
   
HozzászólásElküldve: 2015.12.11. 19:31 
Offline
Tiszteletbeli
Avatar

Csatlakozott: 2014.09.08. 22:21
Hozzászólások: 3014
Megköszönt másnak: 96 alkalommal
Megköszönték neki: 555 alkalommal
És ilyenkor vagyok bajba az sma taggel, tehetek mindent vágólapra, hogy javítsam... xD

_________________
GitHub - mforce


Hozzászólás jelentése
Vissza a tetejére
   
HozzászólásElküldve: 2015.12.11. 19:37 
Offline
Senior Tag

Csatlakozott: 2015.08.03. 18:09
Hozzászólások: 216
Megköszönt másnak: 6 alkalommal
Megköszönték neki: 11 alkalommal
SMA Forráskód: [ Mindet kijelol ]
  1. #include <amxmodx>
  2. #include <amxmisc>
  3.  
  4. #define Tulajdonos ADMIN_LEVEL_E
  5. #define Admin ADMIN_LEVEL_D
  6. #define Configos ADMIN_LEVEL_C
  7.  
  8. #pragma tabsize 0
  9.  
  10. new message[192]
  11. new nev[32]
  12. static color[10]
  13. new Temp[192]
  14.  
  15.  
  16. public plugin_init() {
  17. register_plugin(PLUGIN, VERSION, AUTHOR)
  18. register_clcmd("say", "sayhook")
  19. }
  20.  
  21. public sayhook(id) {
  22. read_args (message, 191)
  23. remove_quotes (message)
  24. if (message[0] == '@' || message[0] == '/' || message[0] == '!' || equal (message, "")) {
  25. return PLUGIN_CONTINUE
  26. }
  27.  
  28. get_user_name(id, nev, 31)
  29. if(is_user_alive(id)) {
  30. get_user_team(id, color, 9)
  31.  
  32. if(get_user_flags(id) & Tulajdonos)
  33. formatex(Temp, 191, "^4[Tulajdonos]^x04%s: ^x03%s", nev, message)
  34. else if(get_user_flags(id) & Admin)
  35. formatex(Temp, 191, "^4[Admin]^x04%s: ^x03%s", nev, message)
  36. else if(get_user_flags(id) & Konfigos)
  37. formatex(Temp, 191, "^4[Konfigos]^x04^%s: ^x03%s", nev, message)
  38.  
  39. else formatex(Temp, 191, "^4[Játékos]^x04%s: ^1%s", nev, message)
  40.  
  41. }
  42. else {
  43. get_user_team(id, color, 9)
  44. if(get_user_flags(id) & Tulajdonos)
  45. formatex(Temp, 191, "^1*Halott*^4[Tulajdonos]^x04%s: ^x03%s", nev, message)
  46. else if(get_user_flags(id) & Admin)
  47. formatex(Temp, 191, "^1*Halott*^4[Admin]^x04%s: ^x03%s", nev, message)
  48. else if(get_user_flags(id) & Configos)
  49. formatex(Temp, 191, "^1*Halott*^4[Configos]^x04%s: ^x03%s", nev, message)
  50.  
  51. else formatex(Temp, 191, "^1*Halott*^4[Játékos]^x04%s: ^1%s", nev, message)
  52. }
  53. sendmessage(color)
  54. return PLUGIN_HANDLED
  55. }
  56. public sendmessage(color[]) {
  57. new teamName[10]
  58. for(new player = 1; player < get_maxplayers(); player++) {
  59. get_user_team (player, teamName, 9)
  60. teamf (player, color)
  61. elkuldes(player, Temp)
  62. teamf(player, teamName)
  63. }
  64. }
  65. public teamf(player, team[]) {
  66. message_begin(MSG_ONE, get_user_msgid("TeamInfo"), _, player)
  67. write_byte(player)
  68. write_string(team)
  69. message_end()
  70. }
  71. public elkuldes(player, Temp[]) {
  72. message_begin( MSG_ONE, get_user_msgid( "SayText" ), _, player)
  73. write_byte( player )
  74. write_string( Temp )
  75. message_end()
  76. }
  77.  


Tessék.
Mindegyiknek megcsináltam.
Ha segítettem nem felejtsd el megköszönni :)

_________________
.:[D@nGeR]:. [1] Only Dust2:
Kép

.:[D@nGeR]:. [2] Sniper:
Kép

Ők köszönték meg Patrik3 nek ezt a hozzászólást: ReC0iiL (2015.12.11. 19:37)
  Népszerűség: 2.27%


Hozzászólás jelentése
Vissza a tetejére
   
HozzászólásElküldve: 2015.12.11. 19:40 
Offline
Tag

Csatlakozott: 2015.12.05. 14:36
Hozzászólások: 34
Megköszönt másnak: 16 alkalommal
Welcome to the AMX Mod X 1.8.1-300 Compiler.
Copyright (c) 1997-2013 ITB CompuPhase, AMX Mod X Team

Error: Undefined symbol "PlUGIN" on line 17
Error: Undefined symbol "VERSION" on line 17
Error: Undefined symbol "AUTHOR" on line 17
Error: Too many error messages on one line on line 17

Compilation aborted.
4 Errors.
Could not locate output file C:\Users\Voga\Desktop\rang.amx (compile failed).



probléma.


Hozzászólás jelentése
Vissza a tetejére
   
HozzászólásElküldve: 2015.12.11. 19:46 
Offline
Felfüggesztve
Avatar

Csatlakozott: 2013.06.09. 18:47
Hozzászólások: 2004
Megköszönt másnak: 1 alkalommal
Megköszönték neki: 220 alkalommal
Fölöslegesen köszönted meg, az a plugin kuka.
Nincs definiálva az alap, meg hiányos az egész. Kuka szintén.

Te meg legközelebb azt a plugint módosítsd neki, amit kért, mert nem véletlenül posztolta az sma -t is.

Tessék, átírva:
AMXX Stúdió:
Welcome to the AMX Mod X 1.8.1-300 Compiler.
Copyright (c) 1997-2013 ITB CompuPhase, AMX Mod X Team

Header size: 636 bytes
Code size: 5280 bytes
Data size: 2772 bytes
Stack/heap size: 16384 bytes; estimated max. usage=781 cells (3124 bytes)
Total requirements: 25072 bytes
Done.


SMA Forráskód: [ Mindet kijelol ]
  1. #include <amxmodx>
  2. #include <amxmisc>
  3.  
  4. #define PLUGIN "Admin Chat Colors"
  5. #define VERSION "2.0"
  6. #define AUTHOR "Arion"
  7.  
  8. #define ACCESS_LEVEL ADMIN_IMMUNITY
  9. #define ADMIN_LISTEN ADMIN_LEVEL_C
  10.  
  11. new message[192]
  12. new sayText
  13. new teamInfo
  14. new maxPlayers
  15.  
  16. new g_AdminListen
  17.  
  18. new strName[191]
  19. new alive[11]
  20.  
  21. new const g_szTag[][] = {
  22. "",
  23. "[Tulajdonos]",
  24. "[Configos]",
  25. "[Admin]"
  26. }
  27.  
  28. public plugin_init()
  29. {
  30. register_plugin(PLUGIN, VERSION, AUTHOR)
  31.  
  32. g_AdminListen = register_cvar("amx_listen", "1") // Set whether admins see or not all messages(Alive, dead and team-only)
  33.  
  34.  
  35. sayText = get_user_msgid("SayText")
  36. teamInfo = get_user_msgid("TeamInfo")
  37. maxPlayers = get_maxplayers()
  38.  
  39. register_clcmd("say", "hook_say")
  40. register_clcmd("say_team", "hook_teamsay")
  41. }
  42.  
  43. public hook_say(id)
  44. {
  45. read_args(message, 191)
  46. remove_quotes(message)
  47.  
  48. // Gungame commands and empty messages
  49. if(message[0] == '@' || message[0] == '/' || message[0] == '!' || equal(message, "")) // Ignores Admin Hud Messages, Admin Slash commands,
  50. return PLUGIN_CONTINUE
  51.  
  52. new name[32]
  53. get_user_name(id, name, 31)
  54.  
  55. new admin = 0, iFlags = get_user_flags(id)
  56.  
  57. if(iFlags & ADMIN_IMMUNITY)
  58. admin = 1
  59. else if(iFlags & ADMIN_CFG)
  60. admin = 2
  61. else if(iFlags & ADMIN_BAN)
  62. admin = 3
  63.  
  64. new isAlive
  65.  
  66. if(is_user_alive(id))
  67. {
  68. isAlive = 1
  69. alive = "^x01"
  70. }
  71. else
  72. {
  73. isAlive = 0
  74. alive = "^x01*DEAD* "
  75. }
  76.  
  77. static color[10]
  78.  
  79. if(admin)
  80. {
  81. get_user_team(id, color, 9)
  82. format(strName, 191, "^x03%s %s^x04%s", g_szTag[admin], alive, name)
  83. format(message, 191, "%s ^x01:^x03 %s", strName, message)
  84. }
  85. else // Player is not admin. Team-color name : Yellow message
  86. {
  87. get_user_team(id, color, 9)
  88. format(strName, 191, "%s^x03%s", alive, name)
  89. format(message, 191, "^%s^x01 : %s", strName, message)
  90. }
  91.  
  92.  
  93. sendMessage(color, isAlive) // Sends the colored message
  94.  
  95. return PLUGIN_HANDLED
  96. }
  97.  
  98.  
  99. public hook_teamsay(id)
  100. {
  101. new playerTeam = get_user_team(id)
  102. new playerTeamName[19]
  103.  
  104. switch(playerTeam) // Team names which appear on team-only messages
  105. {
  106. case 1:
  107. copy(playerTeamName, 11, "Terrorista")
  108.  
  109. case 2:
  110. copy(playerTeamName, 18, "Anti-Terrorista")
  111.  
  112. default:
  113. copy(playerTeamName, 9, "Néző")
  114. }
  115.  
  116. read_args(message, 191)
  117. remove_quotes(message)
  118.  
  119. // Gungame commands and empty messages
  120. if(message[0] == '@' || message[0] == '/' || message[0] == '!' || equal(message, "")) // Ignores Admin Hud Messages, Admin Slash commands,
  121. return PLUGIN_CONTINUE
  122.  
  123. new name[32]
  124. get_user_name(id, name, 31)
  125.  
  126. new admin = 0, iFlags = get_user_flags(id)
  127.  
  128. if(iFlags & ADMIN_IMMUNITY)
  129. admin = 1
  130. else if(iFlags & ADMIN_CFG)
  131. admin = 2
  132. else if(iFlags & ADMIN_BAN)
  133. admin = 3
  134.  
  135. new isAlive
  136.  
  137. if(is_user_alive(id))
  138. {
  139. isAlive = 1
  140. alive = "^x01"
  141. }
  142. else
  143. {
  144. isAlive = 0
  145. alive = "^x01*HALOTT* "
  146. }
  147.  
  148. static color[10]
  149.  
  150. if(admin)
  151. {
  152. get_user_team(id, color, 9)
  153. format(strName, 191, "%s(%s)^x03%s ^x04%s", alive, playerTeamName, g_szTag[admin], name)
  154. format(message, 191, "%s ^x01: ^x03%s", strName, message)
  155. }
  156. else // Player is not admin. Team-color name : Yellow message
  157. {
  158. get_user_team(id, color, 9)
  159. format(strName, 191, "%s(%s) ^x03%s", alive, playerTeamName, name)
  160. format(message, 191, "%s ^x01: %s", strName, message)
  161. }
  162.  
  163.  
  164. sendTeamMessage(color, isAlive, playerTeam) // Sends the colored message
  165.  
  166. return PLUGIN_HANDLED
  167. }
  168.  
  169. public sendMessage(color[], alive)
  170. {
  171. new teamName[10]
  172.  
  173. for(new player = 1; player < maxPlayers; player++)
  174. {
  175. if(!is_user_connected(player))
  176. continue
  177.  
  178. if(alive && is_user_alive(player) || !alive && !is_user_alive(player) || get_pcvar_num(g_AdminListen) && get_user_flags(player) & ADMIN_LISTEN)
  179. {
  180. get_user_team(player, teamName, 9) // Stores user's team name to change back after sending the message
  181. changeTeamInfo(player, color) // Changes user's team according to color choosen
  182. writeMessage(player, message) // Writes the message on player's chat
  183. changeTeamInfo(player, teamName) // Changes user's team back to original
  184. }
  185. }
  186. }
  187.  
  188.  
  189. public sendTeamMessage(color[], alive, playerTeam)
  190. {
  191. new teamName[10]
  192.  
  193. for(new player = 1; player < maxPlayers; player++)
  194. {
  195. if(!is_user_connected(player))
  196. continue
  197.  
  198. if(get_user_team(player) == playerTeam || get_pcvar_num(g_AdminListen) && get_user_flags(player) & ADMIN_LISTEN)
  199. {
  200. if(alive && is_user_alive(player) || !alive && !is_user_alive(player) || get_pcvar_num(g_AdminListen) && get_user_flags(player) & ADMIN_LISTEN)
  201. {
  202. get_user_team(player, teamName, 9) // Stores user's team name to change back after sending the message
  203. changeTeamInfo(player, color) // Changes user's team according to color choosen
  204. writeMessage(player, message) // Writes the message on player's chat
  205. changeTeamInfo(player, teamName) // Changes user's team back to original
  206. }
  207. }
  208. }
  209. }
  210.  
  211.  
  212. public changeTeamInfo(player, team[])
  213. {
  214. message_begin(MSG_ONE, teamInfo, _, player) // Tells to to modify teamInfo(Which is responsable for which time player is)
  215. write_byte(player) // Write byte needed
  216. write_string(team) // Changes player's team
  217. message_end() // Also Needed
  218. }
  219.  
  220.  
  221. public writeMessage(player, message[])
  222. {
  223. message_begin(MSG_ONE, sayText, {0, 0, 0}, player) // Tells to modify sayText(Which is responsable for writing colored messages)
  224. write_byte(player) // Write byte needed
  225. write_string(message) // Effectively write the message, finally, afterall
  226. message_end() // Needed as always
  227. }
  228.  


[kozep]Kép[/kozep]

_________________
Ha elnyerte valamelyik témában a hozzászólásom a tetszésedet melyet olvastál, akkor egy egyszerű gombnyomással kifejezheted, hogy tetszett.

Ők köszönték meg Anonymous1337 nek ezt a hozzászólást: ReC0iiL (2015.12.11. 19:49)
  Népszerűség: 2.27%


Hozzászólás jelentése
Vissza a tetejére
   
Hozzászólások megjelenítése:  Rendezés  
Új téma nyitása  Hozzászólás a témához  [ 6 hozzászólás ] 


Ki van itt

Jelenlévő fórumozók: nincs regisztrált felhasználó valamint 39 vendég


Nyithatsz új témákat ebben a fórumban.
Válaszolhatsz egy témára ebben a fórumban.
Nem szerkesztheted a hozzászólásaidat ebben a fórumban.
Nem törölheted a hozzászólásaidat ebben a fórumban.
Nem küldhetsz csatolmányokat ebben a fórumban.

Keresés:
Ugrás:  
Powered by phpBB® Forum Software © phpBB Limited
Magyar fordítás © Magyar phpBB Közösség
Portal: Kiss Portal Extension © Michael O'Toole